35 Commits

Author SHA1 Message Date
root
d44f85ecf1 누락된 이미지 추가 2024-04-19 10:24:21 +09:00
정훈 변
e9b054c718 업데이트 2024-03-28 14:55:46 +09:00
정훈 변
3b833e025f kube_vip 비활성화 2024-03-28 12:17:37 +09:00
정훈 변
b5806110c9 내용 업데이트 2024-03-21 10:30:28 +09:00
정훈 변
021737539b image repo 주소 변경 2024-02-26 12:59:47 +09:00
정훈 변
0aa0497403 최초 image registry 구성 2024-02-26 12:07:55 +09:00
정훈 변
3fd554eee9 collection 교체 2024-02-23 16:37:40 +09:00
정훈 변
b494779b5b Update main.yml 2024-02-23 15:15:31 +09:00
정훈 변
96439acf91 Update main.yml 2024-02-20 16:18:59 +09:00
정훈 변
ff17600709 Update main.yml 2024-02-20 15:59:14 +09:00
정훈 변
929a7e319b registry 이미지 교체 2024-02-20 15:17:30 +09:00
ByeonJungHun
552ee76b4e cni_plugin install 로직 변경 2024-02-20 15:01:56 +09:00
정훈 변
68b1c26de5 Update registry.yml 2024-02-20 14:53:55 +09:00
정훈 변
8a3ccd056c Update registry.yml 2024-02-20 14:47:23 +09:00
정훈 변
4b14f84dd2 Update main.yml 2024-02-20 14:31:29 +09:00
정훈 변
792ee3498b 패키지 추가 2024-02-20 14:25:27 +09:00
정훈 변
7a25b61ce3 패키지 추가 2024-02-20 14:18:06 +09:00
정훈 변
ffb0ea4027 Update inventory.ini 2024-02-20 14:06:01 +09:00
정훈 변
2cb3576c8e ipvsadm 패키지 추가 2024-02-20 13:48:52 +09:00
정훈 변
39632ed5ef ipvsadm 패키지 추가 2024-02-20 12:18:20 +09:00
정훈 변
c6123d17d8 when 조건 수정 2024-02-20 12:03:31 +09:00
정훈 변
85d097ab18 ansible 바이너리 교체 2024-02-20 11:57:28 +09:00
정훈 변
ee17554213 Update README.md 2024-02-20 11:49:47 +09:00
ByeonJungHun
ed131defc0 ansible 버전 교체 2024-02-20 11:41:12 +09:00
정훈 변
ef3a7fbd46 Update infra-setting.yaml 2024-02-20 09:33:45 +09:00
정훈 변
d0cf9ec991 Update installer.sh 2024-02-20 09:33:16 +09:00
정훈 변
c264bdee39 경로 수정 2024-02-19 17:20:37 +09:00
정훈 변
aafccc0c4a script 수정 2024-02-19 16:21:48 +09:00
ByeonJungHun
0551d7058d playbook 추가 2024-02-19 16:11:31 +09:00
ByeonJungHun
f9d8451a8f .DS_Store 삭제 2024-02-19 16:08:18 +09:00
ByeonJungHun
2e29d65b99 불필요 파일 삭제 2024-02-19 16:06:11 +09:00
ByeonJungHun
360c6eef4a offline 작업 2024-02-19 16:02:29 +09:00
정훈 변
22bcf2d50b Update file README.md 2024-02-16 17:10:27 +09:00
변정훈
f69d904725 kubespray 2.24 추가 2024-02-16 17:08:09 +09:00
변정훈
1fa9b0df4b 브랜치 분리 2024-02-16 17:02:02 +09:00
6289 changed files with 749368 additions and 8 deletions

View File

@@ -3,12 +3,11 @@
## 개요
현재 모든 고객사가 모두 각기 다른 Kubernetes 버전 , 다른 CNI , 다른 CRI 로 구성이 되어 있음.<br>
올해 Kubernetes 버전 1.18 및 Docker 로 구축을 한 환경이 존재함.<br>
작년(2023년) Kubernetes 버전 1.18 및 Docker 로 구축을 한 환경이 존재함.<br>
(최신 버전의 Kubernetes는 1.28 / Docker는 공식적으로 Kubernetes에서 지원에서 제외 되었다)<br>
사실상 이해하기 어려운 구성의 환경들이 있는 관계로 최소한의 버전과 환경 통일을 위해 제작 되었음.<br>
최신 버전인 v1.28 로 구성하고 싶었지만 v1.27 과 v1.28 을 지원하는 kubespray 2.23 버전에서 버그 존재<br>
정상적으로 클러스터 구성을 못하는 문제가 있어서 v1.26 까지 지원하는 kubespray 2.22 버전으로 구성하였습니다.
최신 버전의 kubespray 2.24 기준으로 제작되었으며, kubernetes 버전 v1.28.6 을 지원하고 있음<br>
## 준비물
@@ -36,9 +35,9 @@
```yaml
[all]
hostname1 ansible_host=10.10.43.231 ip=10.10.43.231 etcd_member_name=hostname1 ansible_port=22 node_role=master
hostname2 ansible_host=10.10.43.232 ip=10.10.43.232 ansible_port=22 node_role=node
hostname3 ansible_host=10.10.43.233 ip=10.10.43.233 ansible_port=22 node_role=node
hostname1 ansible_host=10.10.43.231 ip=10.10.43.231 etcd_member_name=hostname1 ansible_port=22
hostname2 ansible_host=10.10.43.232 ip=10.10.43.232 ansible_port=22
hostname3 ansible_host=10.10.43.233 ip=10.10.43.233 ansible_port=22
[kube_control_plane]
hostname1
@@ -61,7 +60,6 @@ calico_rr
hostname1,2,3 , etcd_member_name 에 각각 사용할 서버들의 hostname을 입력<br>
ansible_host , ip 두 부분에 각 서버의 IP를 입력<br>
ansible_port 에 각 서버가 사용중인 ssh 포트 입력<br>
node_role 부분은 변경하지 않음, node_role=master 인 서버 즉 첫번째 입력을 하는 서버가 master 노드임<br>
7. `./installer.sh` 커맨드로 `install.sh` 실행 후 1번 메뉴 실행
@@ -88,4 +86,4 @@ httpd 를 마스터 노드에 설치 및 설정 ➝ local repo 생성
local registry 생성 (master node에 container)
kubernetes 클러스터 생성
10. 따란-! Kubernetes v1.26.5 구성 완료---!!
10. 따란-! Kubernetes v1.28.6 구성 완료---!!

View File

@@ -0,0 +1,8 @@
download_url: https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/ansible-netcommon-6.0.0.tar.gz
format_version: 1.0.0
name: netcommon
namespace: ansible
server: https://galaxy.ansible.com/api/
signatures: []
version: 6.0.0
version_url: /api/v3/plugin/ansible/content/published/collections/index/ansible/netcommon/versions/6.0.0/

View File

@@ -0,0 +1,8 @@
download_url: https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/ansible-posix-1.5.4.tar.gz
format_version: 1.0.0
name: posix
namespace: ansible
server: https://galaxy.ansible.com/api/
signatures: []
version: 1.5.4
version_url: /api/v3/plugin/ansible/content/published/collections/index/ansible/posix/versions/1.5.4/

View File

@@ -0,0 +1,8 @@
download_url: https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/ansible-utils-3.1.0.tar.gz
format_version: 1.0.0
name: utils
namespace: ansible
server: https://galaxy.ansible.com/api/
signatures: []
version: 3.1.0
version_url: /api/v3/plugin/ansible/content/published/collections/index/ansible/utils/versions/3.1.0/

View File

@@ -0,0 +1,7 @@
---
profile: production
exclude_paths:
- changelogs/changelog.yaml
skip_list:
# ansible-lint does not like the `import-3.11` ignore in tests/sanity/ignore-*.txt
- sanity[cannot-ignore]

View File

@@ -0,0 +1,45 @@
[flake8]
builtins = _
# Print the total number of errors:
count = true
# Don't even try to analyze these:
extend-exclude =
# vendored files
compat
# project env vars
.env,
# GitHub configs
.github,
.mypy_cache
# Cache files of pytest
.pytest_cache,
tests/output/
.tox
# Occasional virtualenv dirs
.venv
venv
# VS Code
.vscode,
# IMPORTANT: avoid using ignore option, always use extend-ignore instead
# Completely and unconditionally ignore the following errors:
extend-ignore =
# E123, E125 skipped as they are invalid PEP-8.
E123,
E125,
# annoy black by allowing white space before : https://github.com/psf/black/issues/315
E203,
# ansible requires import after doc strings
E402,
# given the ansible_collections this is nearly impossible
E501,
W503,
# Accessibility/large fonts and PEP8 unfriendly:
max-line-length = 100
# Count the number of occurrences of each error/warning code and print a report:
statistics = true

View File

@@ -0,0 +1,3 @@
---
# see https://github.com/ansible-community/devtools
_extends: ansible-community/devtools

View File

@@ -0,0 +1,15 @@
---
# See https://github.com/ansible-community/devtools/blob/main/.github/workflows/ack.yml
name: ack
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
on: # yamllint disable-line rule:truthy
pull_request_target:
types: [opened, labeled, unlabeled, synchronize]
jobs:
ack:
uses: ansible/devtools/.github/workflows/ack.yml@main

View File

@@ -0,0 +1,14 @@
---
name: code_coverage
on: # yamllint disable-line rule:truthy
push:
pull_request:
branches: [ main ]
jobs:
codecoverage:
uses: ansible-network/github_actions/.github/workflows/coverage_network_devices.yml@main
with:
collection_pre_install: >-
git+https://github.com/ansible-collections/ansible.utils.git

View File

@@ -0,0 +1,14 @@
---
name: ansible-lint
on: # yamllint disable-line rule:truthy
pull_request:
branches: ["main"]
jobs:
build:
name: Ansible Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run ansible-lint
uses: ansible/ansible-lint@main

View File

@@ -0,0 +1,27 @@
---
# push workflow is shared and expected to perform actions after a merge happens
# on a maintenance branch (default or release). For example updating the
# draft release-notes.
# based on great work from
# https://github.com/T-Systems-MMS/ansible-collection-icinga-director
name: push
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
on: # yamllint disable-line rule:truthy
workflow_dispatch:
env:
NAMESPACE: ansible
COLLECTION_NAME: netcommon
ANSIBLE_COLLECTIONS_PATHS: ./
jobs:
update_release_draft:
uses: ansible/devtools/.github/workflows/push_network.yml@main
with:
repo: ansible-collections/ansible.netcommon
secrets:
BOT_PAT: ${{ secrets.BOT_PAT }}

View File

@@ -0,0 +1,14 @@
---
name: release
on: # yamllint disable-line rule:truthy
release:
types: [published]
jobs:
release:
uses: ansible/devtools/.github/workflows/release_collection.yml@main
with:
environment: release
secrets:
ah_token: ${{ secrets.AH_TOKEN }}
ansible_galaxy_api_key: ${{ secrets.ANSIBLE_GALAXY_API_KEY }}

View File

@@ -0,0 +1,44 @@
---
name: CI
concurrency:
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on: # yamllint disable-line rule:truthy
pull_request:
branches: [main]
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
jobs:
changelog:
uses: ansible-network/github_actions/.github/workflows/changelog.yml@main
if: github.event_name == 'pull_request'
sanity:
uses: ansible-network/github_actions/.github/workflows/sanity.yml@main
unit-galaxy:
uses: ansible-network/github_actions/.github/workflows/unit_galaxy.yml@main
unit-source:
uses: ansible-network/github_actions/.github/workflows/unit_source.yml@main
with:
collection_pre_install: >-
git+https://github.com/ansible-collections/ansible.utils.git
all_green:
if: ${{ always() }}
needs:
- changelog
- sanity
- unit-galaxy
- unit-source
runs-on: ubuntu-latest
steps:
- run: >-
python -c "assert 'failure' not in
set([
'${{ needs.changelog.result }}',
'${{ needs.sanity.result }}',
'${{ needs.unit-galaxy.result }}',
'${{ needs.unit-source.result }}'
])"

View File

@@ -0,0 +1,14 @@
---
name: refresh_automation_hub_token
on: # yamllint disable-line rule:truthy
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
refresh:
uses: ansible/devtools/.github/workflows/ah_token_refresh.yml@main
with:
environment: release
secrets:
ah_token: ${{ secrets.AH_TOKEN }}

113
collection/ansible/netcommon/.gitignore vendored Normal file
View File

@@ -0,0 +1,113 @@
/tests/output/
/changelogs/.plugin-cache.yaml
# In case a collection directory is present, ignore it
/collections/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
# vs code configuration
.vscode/

View File

@@ -0,0 +1,6 @@
[settings]
known_first_party=ansible_collections.ansible.netcommon
line_length=100
lines_after_imports=2
lines_between_types=1
profile=black

View File

@@ -0,0 +1,34 @@
---
repos:
- repo: https://github.com/ansible-network/collection_prep
rev: 1.1.1
hooks:
- id: update-docs
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-merge-conflict
- id: debug-statements
- id: end-of-file-fixer
- id: no-commit-to-branch
- id: trailing-whitespace
- repo: https://github.com/pre-commit/mirrors-prettier
rev: "v3.1.0"
hooks:
- id: prettier
additional_dependencies:
- prettier
- prettier-plugin-toml
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort
args: ["--filter-files"]
- repo: https://github.com/psf/black
rev: 23.11.0
hooks:
- id: black

View File

@@ -0,0 +1,17 @@
# Stuff we don't want priettier to ever to look into
.*/
coverage/
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# A linked collection directory created by pytest-ansible-units
collections/
README.md

View File

@@ -0,0 +1,15 @@
---
extends: default
ignore: |
\.tox
changelogs/*
rules:
braces:
max-spaces-inside: 1
level: error
brackets:
max-spaces-inside: 1
level: error
line-length: disable

View File

@@ -0,0 +1,610 @@
==========================================
Ansible Netcommon Collection Release Notes
==========================================
.. contents:: Topics
v6.0.0
======
Release Summary
---------------
Starting from this release, the minimum `ansible-core` version this collection requires is `2.14.0`. That last known version compatible with ansible-core<2.14 is `v5.3.0`.
Major Changes
-------------
- Bumping `requires_ansible` to `>=2.14.0`, since previous ansible-core versions are EoL now.
v5.3.0
======
Minor Changes
-------------
- Add new module cli_backup that exclusively handles configuration backup.
Bugfixes
--------
- Fix attribute types from string to str in filter plugins.
v5.2.0
======
Minor Changes
-------------
- Add a new cliconf plugin ``default`` that can be used when no cliconf plugin is found for a given network_os. This plugin only supports ``get()``. (https://github.com/ansible-collections/ansible.netcommon/pull/569)
- httpapi - Add additional option ``ca_path``, ``client_cert``, ``client_key``, and ``http_agent`` that are available in open_url but not to httpapi. (https://github.com/ansible-collections/ansible.netcommon/issues/528)
- telnet - add crlf option to send CRLF instead of just LF (https://github.com/ansible-collections/ansible.netcommon/pull/440).
Deprecated Features
-------------------
- libssh - the ssh_*_args options are now marked that they will be removed after 2026-01-01.
Bugfixes
--------
- Ensure that all connection plugin options that should be strings are actually strings (https://github.com/ansible-collections/ansible.netcommon/pull/549).
New Plugins
-----------
Cliconf
~~~~~~~
- default - General purpose cliconf plugin for new platforms
v5.1.3
======
Bugfixes
--------
- Vendor telnetlib from cpython (https://github.com/ansible-collections/ansible.netcommon/pull/546)
v5.1.2
======
Bugfixes
--------
- Ensure that all connection plugin options that should be strings are actually strings (https://github.com/ansible-collections/ansible.netcommon/pull/549).
v5.1.1
======
Bugfixes
--------
- network_resource - do not append network_os to module names when building supported resources list. This fix is only valid for cases where FACTS_RESOURCE_SUBSETS is undefined.
v5.1.0
======
Minor Changes
-------------
- libssh - add ``config_file`` option to specify an alternate SSH config file to use.
- parse_cli - add support for multiple matches inside a block by adding new dictionary key to result
- telnet - add ``stdout`` and ``stdout_lines`` to module output.
- telnet - add support for regexes to ``login_prompt`` and ``password_prompt``.
- telnet - apply ``timeout`` to command prompts.
Bugfixes
--------
- httpapi - ``send()`` method no longer applied leftover kwargs to ``open_url()``. Fix applies those arguments as intended (https://github.com/ansible-collections/ansible.netcommon/pull/524).
- network_cli - network cli connection avoids traceback when using invalid user
- network_cli - when receiving longer responses with libssh, parts of the response were sometimes repeated. The response is now returned as it is received (https://github.com/ansible-collections/community.routeros/issues/132).
- network_resource - fix a potential UnboundLocalError if the module fails to import a Resource Module. (https://github.com/ansible-collections/ansible.netcommon/pull/513)
- restconf - creation of new resources is no longer erroneously forced to use POST. (https://github.com/ansible-collections/ansible.netcommon/issues/502)
v5.0.0
======
Minor Changes
-------------
- httpapi - Add option netcommon_httpapi_ciphers to allow overriding default SSL/TLS ciphers. (https://github.com/ansible-collections/ansible.netcommon/pull/494)
Breaking Changes / Porting Guide
--------------------------------
- NetworkConnectionBase now inherits from PersistentConnectionBase in ansible.utils. As a result, the minimum ansible.utils version has increased to 2.7.0.
- NetworkTemplate is no longer importable from ansible_collections.ansible.netcommon.plugins.module_utils.network.common and should now be found at its proper location ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template
- ResourceModule is no longer importable from ansible_collections.ansible.netcommon.plugins.module_utils.network.common and should now be found at its proper location ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module
- VALID_MASKS, is_masklen, is_netmask, to_bits, to_ipv6_network, to_masklen, to_netmask, and to_subnet are no longer importable from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils and should now be found at their proper location ansible.module_utils.common.network
Removed Features (previously deprecated)
----------------------------------------
- cli_parse - This plugin was moved to ansible.utils in version 1.0.0, and the redirect to that collection has now been removed.
Bugfixes
--------
- Cast AnsibleUnsafeText to str in convert_doc_to_ansible_module_kwargs() to keep CSafeLoader happy. This fixes issues with content scaffolding tools.
v4.1.0
======
Minor Changes
-------------
- Add implementation for content_templates_parser.
Bugfixes
--------
- restconf_get - fix direction of XML deserialization when ``output == 'xml'``
v4.0.0
======
Removed Features (previously deprecated)
----------------------------------------
- napalm - Removed unused connection plugin.
- net_banner - Use <network_os>_banner instead.
- net_interface - Use <network_os>_interfaces instead.
- net_l2_interface - Use <network_os>_l2_interfaces instead.
- net_l3_interface - Use <network_os>_l3_interfaces instead.
- net_linkagg - Use <network_os>_lag_interfaces instead.
- net_lldp - Use <network_os>_lldp_global instead.
- net_lldp_interface - Use <network_os>_lldp_interfaces instead.
- net_logging - Use <network_os>_logging_global instead.
- net_static_route - Use <network_os>_static_routes instead.
- net_system - Use <network_os>_system instead.
- net_user - Use <network_os>_user instead.
- net_vlan - Use <network_os>_vlans instead.
- net_vrf - Use <network_os>_vrf instead.
v3.1.3
======
Release Summary
---------------
The v3.1.2 is unavailable on Ansible Automation Hub because a technical issue. Please download and use v3.1.3 from Automation Hub.
v3.1.2
======
Bugfixes
--------
- libssh - check for minimum ansible-pylibssh version before using password_prompt option. (https://github.com/ansible-collections/ansible.netcommon/pull/467)
v3.1.1
======
Bugfixes
--------
- Fix a small number of potential use-before-assignment issues.
- Fix to set connection plugin options correctly.
- libssh - Removed the wording "Tech preview". From version 3.0.0 the default if installed.
- libssh - add ssh_args, ssh_common_args, and ssh_extra_args options. These options are exclusively for collecting proxy information from as an alternative to the proxy_command option.
v3.1.0
======
Minor Changes
-------------
- Add grpc connection plugin support.
- Adds a new option `terminal_errors` in network_cli, that determines how terminal setting failures are handled.
- libssh - Added `password_prompt` option to override default "password:" prompt used by pylibssh
New Plugins
-----------
Connection
~~~~~~~~~~
- grpc - Provides a persistent connection using the gRPC protocol
New Modules
-----------
- grpc_config - Fetch configuration/state data from gRPC enabled target hosts.
- grpc_get - Fetch configuration/state data from gRPC enabled target hosts.
v3.0.1
======
Bugfixes
--------
- httpapi - Fix for improperly set hostname in url
- libssh - Fix for improperly set hostname in connect
- restconf - When non-JSON data is encountered, return the bytes found instead of nothing.
v3.0.0
======
Major Changes
-------------
- cli_parse - this module has been moved to the ansible.utils collection. ``ansible.netcommon.cli_parse`` will continue to work to reference the module in its new location, but this redirect will be removed in a future release
- network_cli - Change default value of `ssh_type` option from `paramiko` to `auto`. This value will use libssh if the ansible-pylibssh module is installed, otherwise will fallback to paramiko.
Breaking Changes / Porting Guide
--------------------------------
- httpapi - Change default value of ``import_modules`` option from ``no`` to ``yes``
- netconf - Change default value of ``import_modules`` option from ``no`` to ``yes``
- network_cli - Change default value of ``import_modules`` option from ``no`` to ``yes``
Known Issues
------------
- eos - When using eos modules on Ansible 2.9, tasks will occasionally fail with ``import_modules`` enabled. This can be avoided by setting ``import_modules: no``
v2.6.1
======
Release Summary
---------------
Rereleased 2.6.0 with updated utils dependancy.
Bugfixes
--------
- Fix validate-module sanity test.
v2.6.0
======
Minor Changes
-------------
- Redirected ipaddr filters to ansible.utils (https://github.com/ansible-collections/ansible.netcommon/pull/359).
- httpapi - new parameter retries in send() method limits the number of times a request is retried when a HTTP error that can be worked around is encountered. The default is to retry indefinitely to maintain old behavior, but this default may change in a later breaking release.
Bugfixes
--------
- Fix issue with cli_parse native_parser plugin when input is empty (https://github.com/ansible-collections/ansible.netcommon/issues/347).
- No activity on the transport's channel was triggering a socket.timeout() after 30 secs, even if persistent_command_timeout is set to a higher value. This patch fixes it.
v2.5.1
======
Bugfixes
--------
- Fixed plugins inheriting from netcommon's base plugins (for example httpapi/restconf or netconf/default) so that they can be properly loaded (https://github.com/ansible-collections/ansible.netcommon/issues/356).
v2.5.0
======
Minor Changes
-------------
- Copied the cliconf, httpapi, netconf, and terminal base plugins and NetworkConnectionBase into netcommon. These base plugins may now be imported from netcommmon instead of ansible if a collection depends on netcommon versions newer than this version, allowing features and bugfixes to flow to those collections without upgrading ansible.
- Make ansible_network_os as optional param for httpapi connection plugin.
- Support removal of non-config lines from running config while taking backup.
- `network_cli` - added new option 'become_errors' to determine how privilege escalation failures are handled.
Bugfixes
--------
- network_cli - Provide clearer error message when a prompt regex fails to compile
- network_cli - fix issue when multiple terminal_initial_(prompt|answer) values are given (https://github.com/ansible-collections/ansible.netcommon/issues/331).
v2.4.0
======
Minor Changes
-------------
- Add network_resource plugin to manage and provide single entry point for all resource modules for higher oder roles.
Deprecated Features
-------------------
- network_cli - The paramiko_ssh setting ``look_for_keys`` was set automatically based on the values of the ``password`` and ``private_key_file`` options passed to network_cli. This option can now be set explicitly, and the automatic setting of ``look_for_keys`` will be removed after 2024-01-01 (https://github.com/ansible-collections/ansible.netcommon/pull/271).
Bugfixes
--------
- network_cli - Add ability to set options inherited from paramiko/libssh in ansible >= 2.11 (https://github.com/ansible-collections/ansible.netcommon/pull/271).
New Modules
-----------
- network_resource - Manage resource modules
v2.3.0
======
Minor Changes
-------------
- Add vlan_expander filter
- Persistent connection options (persistent_command_timeout, persistent_log_messages, etc.) have been unified across all persistent connections. New persistent connections may also now get these options by extending the connection_persistent documentation fragment.
v2.2.0
======
Minor Changes
-------------
- Add variable to control ProxyCommand with libssh connection.
- NetworkTemplate and ResouceModule base classes have been moved under module_utils.network.common.rm_base. Stubs have been kept for backwards compatibility. These will be removed after 2023-01-01. Please update imports for existing modules that subclass them. The `cli_rm_builder <https://github.com/ansible-network/cli_rm_builder>`_ has been updated to use the new imports.
Bugfixes
--------
- libssh - Fix fromatting of authenticity error message when not prompting for input (https://github.com/ansible-collections/ansible.netcommon/issues/283)
- netconf - Fix connection with ncclient versions < 0.6.10
- network_cli - Fix for execution failing when ansible_ssh_password is used to specify password (https://github.com/ansible-collections/ansible.netcommon/issues/288)
v2.1.0
======
Minor Changes
-------------
- Add support for ProxyCommand with netconf connection.
Bugfixes
--------
- Variables in play_context will now be updated for netconf connections on each task run.
- fix SCP/SFTP when using network_cli with libssh
v2.0.2
======
Bugfixes
--------
- Fix cli_parse issue with parsers in utils collection (https://github.com/ansible-collections/ansible.netcommon/pull/270)
- Support single_user_mode with Ansible 2.9.
v2.0.1
======
Minor Changes
-------------
- Several module_utils files were intended to be licensed BSD, but missing a license preamble in the files. The preamble has been added, and all authors for the files have given their assent to the intended license https://github.com/ansible-collections/ansible.netcommon/pull/122
Bugfixes
--------
- Allow setting `host_key_checking` through a play/task var for `network_cli`.
- Ensure passed-in terminal_initial_prompt and terminal_initial_answer values are cast to bytes before using
- Update valid documentation for net_ping module.
- ncclient - catch and handle exception to prevent stack trace when running in FIPS mode
- net_put - Remove temp file created when file already exist on destination when mode is 'text'.
v2.0.0
======
Major Changes
-------------
- Remove deprecated connection arguments from netconf_config
Minor Changes
-------------
- Add SCP support when using ssh_type libssh
- Add `single_user_mode` option for command output caching.
- Move cli_config idempotent warning message with the task response under `warnings` key if `changed` is `True`
- Reduce CPU usage and network module run time when using `ansible_network_import_modules`
- Support any() and all() filters in Jinja2.
Breaking Changes / Porting Guide
--------------------------------
- Removed vendored ipaddress package from collection. If you use ansible_collections.ansible.netcommon.plugins.module_utils.compat.ipaddress in your collection, you will need to change this to import ipaddress instead. If your content using ipaddress supports Python 2.7, you will additionally need to make sure that the user has the ipaddress package installed. Please refer to https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_best_practices.html#importing-and-using-shared-code to see how to safely import external packages that may be missing from the user's system A backport of ipaddress for Python 2.7 is available at https://pypi.org/project/ipaddress/
Deprecated Features
-------------------
- Deprecate cli_parse module and textfsm, ttp, xml, json parser plugins as they are moved to ansible.utils collection (https://github.com/ansible-collections/ansible.netcommon/pull/182 https://github.com/ansible-collections/ansible.utils/pull/28)
Bugfixes
--------
- Expose connection class object to rm_template (https://github.com/ansible-collections/ansible.netcommon/pull/180)
- network_cli - When using ssh_type libssh, handle closed connection gracefully instead of throwing an exception
New Plugins
-----------
Cache
~~~~~
- memory - RAM backed, non persistent cache.
v1.5.0
======
Minor Changes
-------------
- Add 'purged' to ACTION_STATES.
Bugfixes
--------
- Add netconf_config integration tests for nxos (https://github.com/ansible-collections/ansible.netcommon/pull/185)
- Fix GetReply object has no attribute strip() (https://github.com/ansible-collections/cisco.iosxr/issues/97)
- Fix config diff logic if parent configuration is present more than once in the candidate config and update docs (https://github.com/ansible-collections/ansible.netcommon/pull/189)
- Fix missing changed from net_get (https://github.com/ansible-collections/ansible.netcommon/issues/198)
- Fix netconf_config module integration test issuea (https://github.com/ansible-collections/ansible.netcommon/pull/177)
- Fix restconf_config incorrectly spoofs HTTP 409 codes (https://github.com/ansible-collections/ansible.netcommon/issues/191)
- Split checks for prompt and errors in network_cli so that detected errors are not lost if the prompt is in a later chunk.
v1.4.1
======
Release Summary
---------------
Change how black config is specified to avoid issues with Automation Hub release process
v1.4.0
======
Minor Changes
-------------
- 'prefix' added to NetworkTemplate class, inorder to handle the negate operation for vyos config commands.
- Add support for json format input format for netconf modules using ``xmltodict``
- Update docs for netconf_get and netconf_config examples using display=native
Bugfixes
--------
- Added support for private key based authentication with libssh transport (https://github.com/ansible-collections/ansible.netcommon/issues/168)
- Fixed ipaddr filter plugins in ansible.netcommon collections is not working with latest Ansible (https://github.com/ansible-collections/ansible.netcommon/issues/157)
- Fixed netconf_rpc task fails due to encoding issue in the response (https://github.com/ansible-collections/ansible.netcommon/issues/151)
- Fixed ssh_type none issue while using net_put and net_get module (https://github.com/ansible-collections/ansible.netcommon/issues/153)
- Fixed unit tests under python3.5
- ipaddr filter - query "address/prefix" (also: "gateway", "gw", "host/prefix", "hostnet", and "router") now handles addresses with /32 prefix or /255.255.255.255 netmask
- network_cli - Update underlying ssh connection's play_context in update_play_context, so that the username or password can be updated
v1.3.0
======
Minor Changes
-------------
- Confirmed commit fails with TypeError in IOS XR netconf plugin (https://github.com/ansible-collections/cisco.iosxr/issues/74)
- The netconf_config module now allows root tag with namespace prefix.
- cli_config: Add new return value diff which is returned when the cliconf plugin supports onbox diff
- cli_config: Clarify when commands is returned when the module is run
Bugfixes
--------
- cli_parse - Ensure only native types are returned to the control node from the parser.
- netconf - Changed log level for message of using default netconf plugin to match the level used when a platform-specific netconf plugin is found
v1.2.1
======
Bugfixes
--------
- Fixed "Object of type Capabilities is not JSON serializable" when using default netconf plugin.
v1.2.0
======
Minor Changes
-------------
- Added description to collection galaxy.yml file.
- NetworkConfig objects now have an optional `comment_tokens` parameter which takes a list of strings which will override the DEFAULT_COMMENT_TOKENS list.
- New cli_parse module for parsing structured text using a variety of parsers. The initial implemetation of cli_parse can be used with json, native, ntc_templates, pyats, textfsm, ttp, and xml.
- The httpapi connection plugin now works with `wait_for_connection`. This will periodically request the root page of the server described by the plugin's options until the request succeeds. This can only test that the server is reachable, the correctness or usability of the API is not guaranteed.
Bugfixes
--------
- cli_config fixes issue when rollback_id = 0 evalutes to False
- sort_list will sort a list of dicts using the sorted method with key as an argument.
v1.1.2
======
Release Summary
---------------
Rereleased 1.1.1 with updated changelog.
v1.1.1
======
Release Summary
---------------
Rereleased 1.1.0 with regenerated documentation.
v1.1.0
======
Major Changes
-------------
- Add libssh connection plugin and refactor network_cli (https://github.com/ansible-collections/ansible.netcommon/pull/30)
Minor Changes
-------------
- Add content option validation for netconf_config module (https://github.com/ansible-collections/ansible.netcommon/pull/66)
- Documentation of module arguments updated to match expected types where missing.
- Resource Modules: changed flag is set to true in check_mode for all ACTION_STATES (https://github.com/ansible-collections/ansible.netcommon/pull/82)
Removed Features (previously deprecated)
----------------------------------------
- module_utils.network.common.utils.ComplexDict has been removed
Bugfixes
--------
- Replace deprecated `getiterator` call with `iter`
- ipaddr - "host" query supports /31 subnets properly
- ipaddr filter - Fixed issue where the first IPv6 address in a subnet was not being considered a valid address.
- ipaddr filter now returns empty list instead of False on empty list input
- net_put - Restore missing function removed when action plugin stopped inheriting NetworkActionBase
- nthhost filter now returns str instead of IPAddress object
- slaac filter now returns str instead of IPAddress object
v1.0.0
======
New Plugins
-----------
Become
~~~~~~
- enable - Switch to elevated permissions on a network device
Connection
~~~~~~~~~~
- httpapi - Use httpapi to run command on network appliances
- netconf - Provides a persistent connection using the netconf protocol
- network_cli - Use network_cli to run command on network appliances
- persistent - Use a persistent unix socket for connection
Httpapi
~~~~~~~
- restconf - HttpApi Plugin for devices supporting Restconf API
Netconf
~~~~~~~
- default - Use default netconf plugin to run standard netconf commands as per RFC
New Modules
-----------
- cli_command - Run a cli command on cli-based network devices
- cli_config - Push text based configuration to network devices over network_cli
- net_get - Copy a file from a network device to Ansible Controller
- net_ping - Tests reachability using ping from a network device
- net_put - Copy a file from Ansible Controller to a network device
- netconf_config - netconf device configuration
- netconf_get - Fetch configuration/state data from NETCONF enabled network devices.
- netconf_rpc - Execute operations on NETCONF enabled network devices.
- restconf_config - Handles create, update, read and delete of configuration data on RESTCONF enabled devices.
- restconf_get - Fetch configuration/state data from RESTCONF enabled devices.
- telnet - Executes a low-down and dirty telnet command

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -0,0 +1,7 @@
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1 @@
../LICENSE

View File

@@ -0,0 +1,48 @@
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------
1. This LICENSE AGREEMENT is between the Python Software Foundation
("PSF"), and the Individual or Organization ("Licensee") accessing and
otherwise using this software ("Python") in source or binary form and
its associated documentation.
2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Python Software Foundation;
All Rights Reserved" are retained in Python alone or in any derivative version
prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python.
4. PSF is making Python available to Licensee on an "AS IS"
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. Nothing in this License Agreement shall be deemed to create any
relationship of agency, partnership, or joint venture between PSF and
Licensee. This License Agreement does not grant permission to use PSF
trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.
8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.

View File

@@ -0,0 +1,38 @@
{
"collection_info": {
"namespace": "ansible",
"name": "netcommon",
"version": "6.0.0",
"authors": [
"Ansible Network Community (ansible-network)"
],
"readme": "README.md",
"tags": [
"networking",
"security",
"cloud",
"network_cli",
"netconf",
"httpapi",
"grpc"
],
"description": "Ansible Collection with common content to help automate the management of network, security, and cloud devices.",
"license": [],
"license_file": "LICENSE",
"dependencies": {
"ansible.utils": ">=3.0.0"
},
"repository": "https://github.com/ansible-collections/ansible.netcommon",
"documentation": null,
"homepage": null,
"issues": "https://github.com/ansible-collections/ansible.netcommon/issues"
},
"file_manifest_file": {
"name": "FILES.json",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "b0c86e07b3c71fcba92378a549243c5ddc0d647e848127a364bf517d6bc1a9d1",
"format": 1
},
"format": 1
}

View File

@@ -0,0 +1,152 @@
# Ansible Network Collection for Common Code (netcommon)
[![CI](https://zuul-ci.org/gated.svg)](https://ansible.softwarefactory-project.io/zuul/builds?project=ansible-collections%2Fansible.netcommon) <!--[![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/ansible.netcommon)](https://codecov.io/gh/ansible-collections/ansible.netcommon)-->
[![Codecov](https://codecov.io/gh/ansible-collections/ansible.netcommon/branch/main/graph/badge.svg)](https://codecov.io/gh/ansible-collections/ansible.netcommon)
[![CI](https://github.com/ansible-collections/ansible.netcommon/actions/workflows/tests.yml/badge.svg?branch=main&event=schedule)](https://github.com/ansible-collections/ansible.netcommon/actions/workflows/tests.yml)
The Ansible ``ansible.netcommon`` collection includes common content to help automate the management of network, security, and cloud devices.
This includes connection plugins, such as ``network_cli``, ``httpapi``, and ``netconf``.
<!--start requires_ansible-->
## Ansible version compatibility
This collection has been tested against following Ansible versions: **>=2.14.0**.
For collections that support Ansible 2.9, please ensure you update your `network_os` to use the
fully qualified collection name (for example, `cisco.ios.ios`).
Plugins and modules within a collection may be tested with only specific Ansible versions.
A collection may contain metadata that identifies these versions.
PEP440 is the schema used to describe the versions of Ansible.
<!--end requires_ansible-->
## Included content
<!--start collection content-->
### Become plugins
Name | Description
--- | ---
[ansible.netcommon.enable](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.enable_become.rst)|Switch to elevated permissions on a network device
### Cliconf plugins
Name | Description
--- | ---
[ansible.netcommon.default](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.default_cliconf.rst)|General purpose cliconf plugin for new platforms
### Connection plugins
Name | Description
--- | ---
[ansible.netcommon.grpc](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.grpc_connection.rst)|Provides a persistent connection using the gRPC protocol
[ansible.netcommon.httpapi](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.httpapi_connection.rst)|Use httpapi to run command on network appliances
[ansible.netcommon.libssh](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.libssh_connection.rst)|Run tasks using libssh for ssh connection
[ansible.netcommon.netconf](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.netconf_connection.rst)|Provides a persistent connection using the netconf protocol
[ansible.netcommon.network_cli](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.network_cli_connection.rst)|Use network_cli to run command on network appliances
[ansible.netcommon.persistent](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.persistent_connection.rst)|Use a persistent unix socket for connection
### Filter plugins
Name | Description
--- | ---
[ansible.netcommon.comp_type5](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.comp_type5_filter.rst)|The comp_type5 filter plugin.
[ansible.netcommon.hash_salt](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.hash_salt_filter.rst)|The hash_salt filter plugin.
[ansible.netcommon.parse_cli](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.parse_cli_filter.rst)|parse_cli filter plugin.
[ansible.netcommon.parse_cli_textfsm](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.parse_cli_textfsm_filter.rst)|parse_cli_textfsm filter plugin.
[ansible.netcommon.parse_xml](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.parse_xml_filter.rst)|The parse_xml filter plugin.
[ansible.netcommon.pop_ace](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.pop_ace_filter.rst)|Remove ace entries from a acl source of truth.
[ansible.netcommon.type5_pw](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.type5_pw_filter.rst)|The type5_pw filter plugin.
[ansible.netcommon.vlan_expander](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.vlan_expander_filter.rst)|The vlan_expander filter plugin.
[ansible.netcommon.vlan_parser](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.vlan_parser_filter.rst)|The vlan_parser filter plugin.
### Httpapi plugins
Name | Description
--- | ---
[ansible.netcommon.restconf](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.restconf_httpapi.rst)|HttpApi Plugin for devices supporting Restconf API
### Netconf plugins
Name | Description
--- | ---
[ansible.netcommon.default](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.default_netconf.rst)|Use default netconf plugin to run standard netconf commands as per RFC
### Modules
Name | Description
--- | ---
[ansible.netcommon.cli_backup](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.cli_backup_module.rst)|Back up device configuration from network devices over network_cli
[ansible.netcommon.cli_command](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.cli_command_module.rst)|Run a cli command on cli-based network devices
[ansible.netcommon.cli_config](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.cli_config_module.rst)|Push text based configuration to network devices over network_cli
[ansible.netcommon.grpc_config](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.grpc_config_module.rst)|Fetch configuration/state data from gRPC enabled target hosts.
[ansible.netcommon.grpc_get](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.grpc_get_module.rst)|Fetch configuration/state data from gRPC enabled target hosts.
[ansible.netcommon.net_get](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.net_get_module.rst)|Copy a file from a network device to Ansible Controller
[ansible.netcommon.net_ping](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.net_ping_module.rst)|Tests reachability using ping from a network device
[ansible.netcommon.net_put](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.net_put_module.rst)|Copy a file from Ansible Controller to a network device
[ansible.netcommon.netconf_config](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.netconf_config_module.rst)|netconf device configuration
[ansible.netcommon.netconf_get](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.netconf_get_module.rst)|Fetch configuration/state data from NETCONF enabled network devices.
[ansible.netcommon.netconf_rpc](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.netconf_rpc_module.rst)|Execute operations on NETCONF enabled network devices.
[ansible.netcommon.network_resource](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.network_resource_module.rst)|Manage resource modules
[ansible.netcommon.restconf_config](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.restconf_config_module.rst)|Handles create, update, read and delete of configuration data on RESTCONF enabled devices.
[ansible.netcommon.restconf_get](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.restconf_get_module.rst)|Fetch configuration/state data from RESTCONF enabled devices.
[ansible.netcommon.telnet](https://github.com/ansible-collections/ansible.netcommon/blob/main/docs/ansible.netcommon.telnet_module.rst)|Executes a low-down and dirty telnet command
<!--end collection content-->
## Installing this collection
You can install the ``ansible.netcommon`` collection with the Ansible Galaxy CLI:
ansible-galaxy collection install ansible.netcommon
You can also include it in a `requirements.yml` file and install it with `ansible-galaxy collection install -r requirements.yml`, using the format:
```yaml
---
collections:
- name: ansible.netcommon
```
## Using this collection
The most common use case for this collection is to include it as a dependency in a network device-specific collection. Use the Fully Qualified Collection Name (FQCN) when referring to content in this collection (for example, `ansible.netcommon.network_cli`).
See the [Vyos collection](https://github.com/ansible-collections/vyos) for an example of this.
### See Also:
* [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details.
## Contributing to this collection
We welcome community contributions to this collection. If you find problems, please open an issue or create a PR against the [ansible.netcommon collection repository](https://github.com/ansible-collections/ansible.netcommon). See [Contributing to Ansible-maintained collections](https://docs.ansible.com/ansible/devel/community/contributing_maintained_collections.html#contributing-maintained-collections) for complete details.
You can also join us on:
- IRC - ``#ansible-network`` [irc.libera.chat](https://libera.chat/) channel
- Slack - https://ansiblenetwork.slack.com
See the [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html) for details on contributing to Ansible.
### Code of Conduct
This collection follows the Ansible project's
[Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html).
Please read and familiarize yourself with this document.
## Release notes
<!--Add a link to a changelog.md file or an external docsite to cover this information. -->
Release notes are available [here](https://github.com/ansible-collections/ansible.netcommon/blob/main/CHANGELOG.rst)
## Roadmap
<!-- Optional. Include the roadmap for this collection, and the proposed release/versioning strategy so users can anticipate the upgrade/update cycle. -->
## More information
- [Developing network resource modules](https://docs.ansible.com/ansible/latest/network/dev_guide/developing_resource_modules_network.html#developing-resource-modules)
- [Ansible network resources](https://docs.ansible.com/ansible/latest/network/getting_started/network_resources.html)
- [Ansible Collection overview](https://github.com/ansible-collections/overview)
- [Ansible User guide](https://docs.ansible.com/ansible/latest/user_guide/index.html)
- [Ansible Developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html)
- [Ansible Community code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html)
## Licensing
GNU General Public License v3.0 or later.
See [LICENSE](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text.

View File

@@ -0,0 +1,36 @@
# This is a cross-platform list tracking distribution packages needed by tests;
# see https://docs.openstack.org/infra/bindep/ for additional information.
gcc-c++ [doc test platform:rpm]
libyaml-devel [test platform:rpm]
libyaml-dev [test platform:dpkg]
python3-devel [test platform:rpm]
python3 [test platform:rpm]
# ansible-pylibssh
gcc [compile platform:rpm]
libssh-dev [compile platform:dpkg]
libssh-devel [compile platform:rpm]
python3-Cython [compile platform:fedora-35 platform:rhel-9]
# 3.9 Cython doesn't seem to be available on our centos-8 images
# But I'm not sure why we would need it anyway?
# python39-Cython [compile platform:centos-8 platform:rhel-8]
# ncclient
python3-six [platform:centos-9 platform:rhel-9]
python39-six [platform:centos-8 platform:rhel-8]
python3-lxml [platform:centos-9 platform:rhel-9]
python39-lxml [platform:centos-8 platform:rhel-8]
# paramiko
findutils [compile platform:centos-8 platform:rhel-8]
gcc [compile platform:centos-8 platform:rhel-8]
make [compile platform:centos-8 platform:rhel-8]
python3-devel [compile platform:centos-9 platform:rhel-9]
python39-devel [compile platform:centos-8 platform:rhel-8]
python3-cffi [platform:centos-9 platform:rhel-9]
python39-cffi [platform:centos-8 platform:rhel-8]
python3-cryptography [platform:centos-9 platform:rhel-9]
python39-cryptography [platform:centos-8 platform:rhel-8]
python3-pycparser [platform:centos-9 platform:rhel-9]
python39-pycparser [platform:centos-8 platform:rhel-8]

View File

@@ -0,0 +1 @@
The changelog has moved `here <https://github.com/ansible-collections/ansible.netcommon/blob/main/CHANGELOG.rst>`_

View File

@@ -0,0 +1,733 @@
ancestor: null
releases:
1.0.0:
modules:
- description: Run a cli command on cli-based network devices
name: cli_command
namespace: ""
- description: Push text based configuration to network devices over network_cli
name: cli_config
namespace: ""
- description: Copy a file from a network device to Ansible Controller
name: net_get
namespace: ""
- description: Tests reachability using ping from a network device
name: net_ping
namespace: ""
- description: Copy a file from Ansible Controller to a network device
name: net_put
namespace: ""
- description: netconf device configuration
name: netconf_config
namespace: ""
- description: Fetch configuration/state data from NETCONF enabled network devices.
name: netconf_get
namespace: ""
- description: Execute operations on NETCONF enabled network devices.
name: netconf_rpc
namespace: ""
- description:
Handles create, update, read and delete of configuration data on
RESTCONF enabled devices.
name: restconf_config
namespace: ""
- description: Fetch configuration/state data from RESTCONF enabled devices.
name: restconf_get
namespace: ""
- description: Executes a low-down and dirty telnet command
name: telnet
namespace: ""
plugins:
become:
- description: Switch to elevated permissions on a network device
name: enable
namespace: null
connection:
- description: Use httpapi to run command on network appliances
name: httpapi
namespace: null
- description: Provides a persistent connection using the netconf protocol
name: netconf
namespace: null
- description: Use network_cli to run command on network appliances
name: network_cli
namespace: null
- description: Use a persistent unix socket for connection
name: persistent
namespace: null
httpapi:
- description: HttpApi Plugin for devices supporting Restconf API
name: restconf
namespace: null
netconf:
- description:
Use default netconf plugin to run standard netconf commands as
per RFC
name: default
namespace: null
release_date: "2020-06-23"
1.1.0:
changes:
bugfixes:
- Replace deprecated `getiterator` call with `iter`
- ipaddr - "host" query supports /31 subnets properly
- ipaddr filter - Fixed issue where the first IPv6 address in a subnet was not
being considered a valid address.
- ipaddr filter now returns empty list instead of False on empty list input
- net_put - Restore missing function removed when action plugin stopped inheriting
NetworkActionBase
- nthhost filter now returns str instead of IPAddress object
- slaac filter now returns str instead of IPAddress object
major_changes:
- Add libssh connection plugin and refactor network_cli (https://github.com/ansible-collections/ansible.netcommon/pull/30)
minor_changes:
- Add content option validation for netconf_config module (https://github.com/ansible-collections/ansible.netcommon/pull/66)
- Documentation of module arguments updated to match expected types where missing.
- "Resource Modules: changed flag is set to true in check_mode for all ACTION_STATES
(https://github.com/ansible-collections/ansible.netcommon/pull/82)"
removed_features:
- module_utils.network.common.utils.ComplexDict has been removed
fragments:
- 103-net-put-handle-src.yaml
- 30-add-libssh-connection-support.yaml
- 34-ipaddr-empty-list.yaml
- 66-netconf-config-vaildation.yml
- 72-ipv6-first-address-fix.yaml
- 74-remove-getiterator.yaml
- 75-unit-tests.yaml
- 78-sanity-cleanup.yaml
- 82-changed_true_action_states_check_mode_yes.yml
- 95-ipaddr.yaml
release_date: "2020-07-30"
1.1.1:
changes:
release_summary: Rereleased 1.1.0 with regenerated documentation.
fragments:
- 1.1.1.yaml
release_date: "2020-07-31"
1.1.2:
changes:
release_summary: Rereleased 1.1.1 with updated changelog.
fragments:
- 1.1.2.yaml
release_date: "2020-08-06"
1.2.0:
changes:
bugfixes:
- cli_config fixes issue when rollback_id = 0 evalutes to False
- sort_list will sort a list of dicts using the sorted method with key as an
argument.
minor_changes:
- Added description to collection galaxy.yml file.
- NetworkConfig objects now have an optional `comment_tokens` parameter which
takes a list of strings which will override the DEFAULT_COMMENT_TOKENS list.
- New cli_parse module for parsing structured text using a variety of parsers.
The initial implemetation of cli_parse can be used with json, native, ntc_templates,
pyats, textfsm, ttp, and xml.
- The httpapi connection plugin now works with `wait_for_connection`. This will
periodically request the root page of the server described by the plugin's
options until the request succeeds. This can only test that the server is
reachable, the correctness or usability of the API is not guaranteed.
fragments:
- 105-wait_for_conn-httpapi.yaml
- 109-cli_parse_module_addition.yaml
- 110-NetworkConfig-comments.yaml
- 114-sort_list_listofdicts.yaml
- 118-cli_config.yaml
- 127-galaxy-fragment.yaml
release_date: "2020-08-25"
1.2.1:
changes:
bugfixes:
- Fixed "Object of type Capabilities is not JSON serializable" when using default
netconf plugin.
fragments:
- netconf-capabilites-fix.yaml
release_date: "2020-09-04"
1.3.0:
changes:
bugfixes:
- cli_parse - Ensure only native types are returned to the control node from
the parser.
- netconf - Changed log level for message of using default netconf plugin to
match the level used when a platform-specific netconf plugin is found
minor_changes:
- Confirmed commit fails with TypeError in IOS XR netconf plugin (https://github.com/ansible-collections/cisco.iosxr/issues/74)
- The netconf_config module now allows root tag with namespace prefix.
- "cli_config: Add new return value diff which is returned when the cliconf
plugin supports onbox diff"
- "cli_config: Clarify when commands is returned when the module is run"
fragments:
- 134-cli-config-diff.yaml
- allow_root_tag_with_prefix.yaml
- cli_parse_fix.yaml
- iosxr_netconf_config_commit_testcase.yaml
- netconf-default.yaml
release_date: "2020-09-29"
1.4.0:
changes:
bugfixes:
- Added support for private key based authentication with libssh transport (https://github.com/ansible-collections/ansible.netcommon/issues/168)
- Fixed ipaddr filter plugins in ansible.netcommon collections is not working
with latest Ansible (https://github.com/ansible-collections/ansible.netcommon/issues/157)
- Fixed netconf_rpc task fails due to encoding issue in the response (https://github.com/ansible-collections/ansible.netcommon/issues/151)
- Fixed ssh_type none issue while using net_put and net_get module (https://github.com/ansible-collections/ansible.netcommon/issues/153)
- Fixed unit tests under python3.5
- 'ipaddr filter - query "address/prefix" (also: "gateway", "gw", "host/prefix",
"hostnet", and "router") now handles addresses with /32 prefix or /255.255.255.255
netmask'
- network_cli - Update underlying ssh connection's play_context in update_play_context,
so that the username or password can be updated
minor_changes:
- "'prefix' added to NetworkTemplate class, inorder to handle the negate operation
for vyos config commands."
- Add support for json format input format for netconf modules using ``xmltodict``
- Update docs for netconf_get and netconf_config examples using display=native
fragments:
- 135-network-cli-change-password.yaml
- 144-test-fixes.yaml
- 151-netconf_rpc_fix.yaml
- 153-part1-fix_ssh_type_none_issue.yaml
- 157-ipaddr-fix.yaml
- 168-libssh-privatekey-support.yaml
- ipaddr-host-prefix-32.yaml
- negate-command-vyos.yaml
- netconf_get_config_doc_updates.yaml
- netconf_xmltodict_support.yaml
release_date: "2020-10-29"
1.4.1:
changes:
release_summary:
Change how black config is specified to avoid issues with Automation
Hub release process
fragments:
- revert_pyproject.yaml
release_date: "2020-10-29"
1.5.0:
changes:
bugfixes:
- Add netconf_config integration tests for nxos (https://github.com/ansible-collections/ansible.netcommon/pull/185)
- Fix GetReply object has no attribute strip() (https://github.com/ansible-collections/cisco.iosxr/issues/97)
- Fix config diff logic if parent configuration is present more than once in
the candidate config and update docs (https://github.com/ansible-collections/ansible.netcommon/pull/189)
- Fix missing changed from net_get (https://github.com/ansible-collections/ansible.netcommon/issues/198)
- Fix netconf_config module integration test issuea (https://github.com/ansible-collections/ansible.netcommon/pull/177)
- Fix restconf_config incorrectly spoofs HTTP 409 codes (https://github.com/ansible-collections/ansible.netcommon/issues/191)
- Split checks for prompt and errors in network_cli so that detected errors
are not lost if the prompt is in a later chunk.
minor_changes:
- Add 'purged' to ACTION_STATES.
fragments:
- 177_netconf_config_test_issue.yaml
- 189_config_diff_fix.yaml
- 191_restconf_config_fix.yaml
- 198_net_get_missing_changed.yaml
- 97_getReplyobject_has_no_attribute_strip_issue.yaml
- add_purged_action_state.yaml
- error-independently.yaml
- netconf_nxos_tests.yaml
release_date: "2021-01-27"
2.0.0:
changes:
breaking_changes:
- Removed vendored ipaddress package from collection. If you use ansible_collections.ansible.netcommon.plugins.module_utils.compat.ipaddress
in your collection, you will need to change this to import ipaddress instead.
If your content using ipaddress supports Python 2.7, you will additionally
need to make sure that the user has the ipaddress package installed. Please
refer to https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_best_practices.html#importing-and-using-shared-code
to see how to safely import external packages that may be missing from the
user's system A backport of ipaddress for Python 2.7 is available at https://pypi.org/project/ipaddress/
bugfixes:
- Expose connection class object to rm_template (https://github.com/ansible-collections/ansible.netcommon/pull/180)
- network_cli - When using ssh_type libssh, handle closed connection gracefully
instead of throwing an exception
deprecated_features:
- Deprecate cli_parse module and textfsm, ttp, xml, json parser plugins as they
are moved to ansible.utils collection (https://github.com/ansible-collections/ansible.netcommon/pull/182
https://github.com/ansible-collections/ansible.utils/pull/28)
major_changes:
- Remove deprecated connection arguments from netconf_config
minor_changes:
- Add SCP support when using ssh_type libssh
- Add `single_user_mode` option for command output caching.
- Move cli_config idempotent warning message with the task response under `warnings`
key if `changed` is `True`
- Reduce CPU usage and network module run time when using `ansible_network_import_modules`
- Support any() and all() filters in Jinja2.
fragments:
- 180_RMbase_engine.yaml
- 182-cli_parse_deprecate.yaml
- 212-update-documentation.yaml
- 213-docs-updates.yaml
- 217-pylibssh-conn-closed.yaml
- 226-libssh-scp.yaml
- 93-remove-ipaddress.yaml
- ansible_network_direct_execution.yaml
- config_module_warning_msg.yaml
- remove-netconf_config-args.yaml
- support_caching.yaml
- support_custom_filters.yaml
- update_requires_ansible.yaml
- yamllint.yaml
plugins:
cache:
- description: RAM backed, non persistent cache.
name: memory
namespace: null
release_date: "2021-03-01"
2.0.1:
changes:
bugfixes:
- Allow setting `host_key_checking` through a play/task var for `network_cli`.
- Ensure passed-in terminal_initial_prompt and terminal_initial_answer values
are cast to bytes before using
- Update valid documentation for net_ping module.
- ncclient - catch and handle exception to prevent stack trace when running
in FIPS mode
- net_put - Remove temp file created when file already exist on destination
when mode is 'text'.
minor_changes:
- Several module_utils files were intended to be licensed BSD, but missing a
license preamble in the files. The preamble has been added, and all authors
for the files have given their assent to the intended license https://github.com/ansible-collections/ansible.netcommon/pull/122
fragments:
- 100-bugfix-net-ping-docs.yaml
- 122-add-license.yaml
- 220-initial-prompt-bytes.yaml
- 227-remove_tests_sanity_requirements.yml
- 231-unit-tests.yaml
- 235-fix-net-put-issue.yaml
- 240-document-libssh-requirement.yaml
- fips-ncclient-import-error.yaml
- new_action_state.yaml
- no_log_fix.yaml
- set_host_key_checking.yaml
release_date: "2021-03-30"
2.0.2:
changes:
bugfixes:
- Fix cli_parse issue with parsers in utils collection (https://github.com/ansible-collections/ansible.netcommon/pull/270)
- Support single_user_mode with Ansible 2.9.
fragments:
- 254-add_ignore_txt.yml
- cli_parse_fix.yaml
- single_user_mode.yaml
release_date: "2021-04-28"
2.1.0:
changes:
bugfixes:
- Variables in play_context will now be updated for netconf connections on each
task run.
- fix SCP/SFTP when using network_cli with libssh
minor_changes:
- Add support for ProxyCommand with netconf connection.
fragments:
- 259-netconf-play-context.yaml
- drop-base-cache.yaml
- libssh-get-put.yaml
- support_proxycommand_netconf.yaml
release_date: "2021-05-17"
2.2.0:
changes:
bugfixes:
- libssh - Fix fromatting of authenticity error message when not prompting for
input (https://github.com/ansible-collections/ansible.netcommon/issues/283)
- netconf - Fix connection with ncclient versions < 0.6.10
- network_cli - Fix for execution failing when ansible_ssh_password is used
to specify password (https://github.com/ansible-collections/ansible.netcommon/issues/288)
minor_changes:
- Add variable to control ProxyCommand with libssh connection.
- "NetworkTemplate and ResouceModule base classes have been moved under module_utils.network.common.rm_base.
Stubs have been kept for backwards compatibility. These will be removed after
2023-01-01. Please update imports for existing modules that subclass them.
The `cli_rm_builder <https://github.com/ansible-network/cli_rm_builder>`_
has been updated to use the new imports.
"
fragments:
- 257-libssh-proxy-var.yaml
- 288-netcli-password.yaml
- libssh-auth-msg.yaml
- ncclient-sock-arg.yaml
- update_rmbase.yaml
release_date: "2021-06-23"
2.3.0:
changes:
minor_changes:
- Add vlan_expander filter
- Persistent connection options (persistent_command_timeout, persistent_log_messages,
etc.) have been unified across all persistent connections. New persistent
connections may also now get these options by extending the connection_persistent
documentation fragment.
fragments:
- 280-vlan_expander.yaml
- 295-connection-tests.yaml
- 308-unify-persistent.yaml
- fix_integration_test_iosxr_7.0.2.yaml
release_date: "2021-07-27"
2.4.0:
changes:
bugfixes:
- network_cli - Add ability to set options inherited from paramiko/libssh in
ansible >= 2.11 (https://github.com/ansible-collections/ansible.netcommon/pull/271).
deprecated_features:
- network_cli - The paramiko_ssh setting ``look_for_keys`` was set automatically
based on the values of the ``password`` and ``private_key_file`` options passed
to network_cli. This option can now be set explicitly, and the automatic setting
of ``look_for_keys`` will be removed after 2024-01-01 (https://github.com/ansible-collections/ansible.netcommon/pull/271).
minor_changes:
- Add network_resource plugin to manage and provide single entry point for all
resource modules for higher oder roles.
fragments:
- 271-net-cli-options.yaml
- 318-netcli-tests.yaml
- backup-without-copy.yaml
- disable-look_for_keys-warning.yaml
- network_resource-version_added.yaml
- network_resource_plugin.yaml
modules:
- description: Manage resource modules
name: network_resource
namespace: ""
release_date: "2021-08-27"
2.5.0:
changes:
bugfixes:
- network_cli - Provide clearer error message when a prompt regex fails to compile
- network_cli - fix issue when multiple terminal_initial_(prompt|answer) values
are given (https://github.com/ansible-collections/ansible.netcommon/issues/331).
minor_changes:
- Copied the cliconf, httpapi, netconf, and terminal base plugins and NetworkConnectionBase
into netcommon. These base plugins may now be imported from netcommmon instead
of ansible if a collection depends on netcommon versions newer than this version,
allowing features and bugfixes to flow to those collections without upgrading
ansible.
- Make ansible_network_os as optional param for httpapi connection plugin.
- Support removal of non-config lines from running config while taking backup.
- "`network_cli` - added new option 'become_errors' to determine how privilege
escalation failures are handled."
fragments:
- 0-copy_ignore_txt.yml
- 334-base-plugins.yaml
- httpapi_make_ansible_network_os_optional_param.yaml
- initial_prompt-bytes-fix.yaml
- non_config.yaml
- on_become_errors.yaml
- prompt-regex.yaml
release_date: "2021-12-07"
2.5.1:
changes:
bugfixes:
- Fixed plugins inheriting from netcommon's base plugins (for example httpapi/restconf
or netconf/default) so that they can be properly loaded (https://github.com/ansible-collections/ansible.netcommon/issues/356).
fragments:
- 358-pluginloader.yaml
- pre-commit.yaml
release_date: "2022-02-09"
2.6.0:
changes:
bugfixes:
- Fix issue with cli_parse native_parser plugin when input is empty (https://github.com/ansible-collections/ansible.netcommon/issues/347).
- No activity on the transport's channel was triggering a socket.timeout() after
30 secs, even if persistent_command_timeout is set to a higher value. This
patch fixes it.
minor_changes:
- Redirected ipaddr filters to ansible.utils (https://github.com/ansible-collections/ansible.netcommon/pull/359).
- httpapi - new parameter retries in send() method limits the number of times
a request is retried when a HTTP error that can be worked around is encountered.
The default is to retry indefinitely to maintain old behavior, but this default
may change in a later breaking release.
fragments:
- 364-pre-commit-ci.yaml
- add_remove_prompt.yaml
- bugfix_cli_parse_native_parser.yaml
- deprecate_ipaddr_filters.yaml
- httpapi-retries.yaml
- shell_timeout.yaml
release_date: "2022-03-01"
2.6.1:
changes:
bugfixes:
- Fix validate-module sanity test.
release_summary: Rereleased 2.6.0 with updated utils dependancy.
fragments:
- 2.6.0.yaml
- fix_sanity.yaml
release_date: "2022-03-10"
3.0.0:
changes:
breaking_changes:
- httpapi - Change default value of ``import_modules`` option from ``no`` to
``yes``
- netconf - Change default value of ``import_modules`` option from ``no`` to
``yes``
- network_cli - Change default value of ``import_modules`` option from ``no``
to ``yes``
known_issues:
- "eos - When using eos modules on Ansible 2.9, tasks will occasionally fail
with ``import_modules`` enabled. This can be avoided by setting ``import_modules:
no``"
major_changes:
- cli_parse - this module has been moved to the ansible.utils collection. ``ansible.netcommon.cli_parse``
will continue to work to reference the module in its new location, but this
redirect will be removed in a future release
- "network_cli - Change default value of `ssh_type` option from `paramiko` to
`auto`. This value will use libssh if the ansible-pylibssh module is installed,
otherwise will fallback to paramiko.
"
fragments:
- 364-pre-commit-ci.yaml
- 384-cli_parse-move.yaml
- 387-change-defaults.yaml
- 390-sanity.yaml
- 394-change-defaults.yaml
- pre-commit-add-docs.yaml
- update-linter-config.yaml
release_date: "2022-04-26"
3.0.1:
changes:
bugfixes:
- httpapi - Fix for improperly set hostname in url
- libssh - Fix for improperly set hostname in connect
- restconf - When non-JSON data is encountered, return the bytes found instead
of nothing.
fragments:
- 412-unit-updates.yaml
- 419-prettier.yaml
- 428.yaml
- 432.yaml
- fix-changelog-location.yaml
- import_modules-logging.yaml
- libssh-tests.yaml
- remote_addr.yaml
- restconf-not-json.yaml
- update-pre-commit.yaml
release_date: "2022-05-31"
3.1.0:
changes:
minor_changes:
- Add grpc connection plugin support.
- Adds a new option `terminal_errors` in network_cli, that determines how terminal
setting failures are handled.
- libssh - Added `password_prompt` option to override default "password:" prompt
used by pylibssh
fragments:
- add-grpc-connection-plugin.yaml
- libssh-password-prompt.yaml
- terminal_errors.yaml
modules:
- description: Fetch configuration/state data from gRPC enabled target hosts.
name: grpc_config
namespace: ""
- description: Fetch configuration/state data from gRPC enabled target hosts.
name: grpc_get
namespace: ""
plugins:
connection:
- description: Provides a persistent connection using the gRPC protocol
name: grpc
namespace: null
release_date: "2022-08-02"
3.1.1:
changes:
bugfixes:
- Fix a small number of potential use-before-assignment issues.
- Fix to set connection plugin options correctly.
- libssh - Removed the wording "Tech preview". From version 3.0.0 the default
if installed.
- libssh - add ssh_args, ssh_common_args, and ssh_extra_args options. These
options are exclusively for collecting proxy information from as an alternative
to the proxy_command option.
fragments:
- 441-pre-commit.yaml
- 448-set_options.yaml
- 451-libssh-remove-tech-preview.yaml
- 454-legacy_cleanup.yaml
- pylint.yaml
release_date: "2022-09-06"
3.1.2:
changes:
bugfixes:
- libssh - check for minimum ansible-pylibssh version before using password_prompt
option. (https://github.com/ansible-collections/ansible.netcommon/pull/467)
fragments:
- 2.15-ignores.yaml
- libssh_check.yaml
release_date: "2022-09-30"
3.1.3:
changes:
release_summary:
The v3.1.2 is unavailable on Ansible Automation Hub because
a technical issue. Please download and use v3.1.3 from Automation Hub.
fragments:
- prepare_312.yaml
release_date: "2022-10-04"
4.0.0:
changes:
removed_features:
- napalm - Removed unused connection plugin.
- net_banner - Use <network_os>_banner instead.
- net_interface - Use <network_os>_interfaces instead.
- net_l2_interface - Use <network_os>_l2_interfaces instead.
- net_l3_interface - Use <network_os>_l3_interfaces instead.
- net_linkagg - Use <network_os>_lag_interfaces instead.
- net_lldp - Use <network_os>_lldp_global instead.
- net_lldp_interface - Use <network_os>_lldp_interfaces instead.
- net_logging - Use <network_os>_logging_global instead.
- net_static_route - Use <network_os>_static_routes instead.
- net_system - Use <network_os>_system instead.
- net_user - Use <network_os>_user instead.
- net_vlan - Use <network_os>_vlans instead.
- net_vrf - Use <network_os>_vrf instead.
fragments:
- 2H22_removal.yaml
- license.yaml
release_date: "2022-10-13"
4.1.0:
changes:
bugfixes:
- restconf_get - fix direction of XML deserialization when ``output == 'xml'``
minor_changes:
- Add implementation for content_templates_parser.
fragments:
- add_content_template_parser.yaml
- fix_wrong_xml_direction.yaml
release_date: "2022-11-02"
5.0.0:
changes:
breaking_changes:
- NetworkConnectionBase now inherits from PersistentConnectionBase in ansible.utils.
As a result, the minimum ansible.utils version has increased to 2.7.0.
- NetworkTemplate is no longer importable from ansible_collections.ansible.netcommon.plugins.module_utils.network.common
and should now be found at its proper location ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template
- ResourceModule is no longer importable from ansible_collections.ansible.netcommon.plugins.module_utils.network.common
and should now be found at its proper location ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module
- VALID_MASKS, is_masklen, is_netmask, to_bits, to_ipv6_network, to_masklen,
to_netmask, and to_subnet are no longer importable from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils
and should now be found at their proper location ansible.module_utils.common.network
bugfixes:
- Cast AnsibleUnsafeText to str in convert_doc_to_ansible_module_kwargs() to
keep CSafeLoader happy. This fixes issues with content scaffolding tools.
minor_changes:
- httpapi - Add option netcommon_httpapi_ciphers to allow overriding default
SSL/TLS ciphers. (https://github.com/ansible-collections/ansible.netcommon/pull/494)
removed_features:
- cli_parse - This plugin was moved to ansible.utils in version 1.0.0, and the
redirect to that collection has now been removed.
fragments:
- 23H1_breaking.yaml
- flake8.yaml
- netcommon_httpapi_ciphers.yaml
- persistentbase.yaml
- telnet.yaml
release_date: "2023-02-27"
5.1.0:
changes:
bugfixes:
- httpapi - ``send()`` method no longer applied leftover kwargs to ``open_url()``.
Fix applies those arguments as intended (https://github.com/ansible-collections/ansible.netcommon/pull/524).
- network_cli - network cli connection avoids traceback when using invalid user
- network_cli - when receiving longer responses with libssh, parts of the response
were sometimes repeated. The response is now returned as it is received (https://github.com/ansible-collections/community.routeros/issues/132).
- network_resource - fix a potential UnboundLocalError if the module fails to
import a Resource Module. (https://github.com/ansible-collections/ansible.netcommon/pull/513)
- restconf - creation of new resources is no longer erroneously forced to use
POST. (https://github.com/ansible-collections/ansible.netcommon/issues/502)
minor_changes:
- libssh - add ``config_file`` option to specify an alternate SSH config file
to use.
- parse_cli - add support for multiple matches inside a block by adding new
dictionary key to result
- telnet - add ``stdout`` and ``stdout_lines`` to module output.
- telnet - add support for regexes to ``login_prompt`` and ``password_prompt``.
- telnet - apply ``timeout`` to command prompts.
fragments:
- 530-parse_cli.yaml
- httpapi-kwargs.yaml
- libssh-repeated-text.yaml
- libssh_config_file.yaml
- lint.yaml
- network_cli_bad_user.yaml
- restconf_put.yaml
- telnet-refactoring.yml
- ule-docs.yaml
release_date: "2023-04-03"
5.1.1:
changes:
bugfixes:
- network_resource - do not append network_os to module names when building
supported resources list. This fix is only valid for cases where FACTS_RESOURCE_SUBSETS
is undefined.
fragments:
- resource_manager.yaml
release_date: "2023-05-09"
5.1.2:
changes:
bugfixes:
- Ensure that all connection plugin options that should be strings are actually
strings (https://github.com/ansible-collections/ansible.netcommon/pull/549).
fragments:
- 549-connection-strings.yml
- 550-ansible-lint.yml
- gha_release.yaml
- line-length.yaml
release_date: "2023-07-05"
5.1.3:
changes:
bugfixes:
- Vendor telnetlib from cpython (https://github.com/ansible-collections/ansible.netcommon/pull/546)
fragments:
- telnet.yaml
release_date: "2023-07-24"
5.2.0:
changes:
bugfixes:
- Ensure that all connection plugin options that should be strings are actually
strings (https://github.com/ansible-collections/ansible.netcommon/pull/549).
deprecated_features:
- libssh - the ssh_*_args options are now marked that they will be removed after
2026-01-01.
minor_changes:
- Add a new cliconf plugin ``default`` that can be used when no cliconf plugin
is found for a given network_os. This plugin only supports ``get()``. (https://github.com/ansible-collections/ansible.netcommon/pull/569)
- httpapi - Add additional option ``ca_path``, ``client_cert``, ``client_key``,
and ``http_agent`` that are available in open_url but not to httpapi. (https://github.com/ansible-collections/ansible.netcommon/issues/528)
- telnet - add crlf option to send CRLF instead of just LF (https://github.com/ansible-collections/ansible.netcommon/pull/440).
fragments:
- 440-telnet-add-crlf-option.yml
- 558-load_provider.yml
- default-cliconf.yaml
- httpapi_options.yaml
- ssh_args.yaml
- vlan_extender.yaml
plugins:
cliconf:
- description: General purpose cliconf plugin for new platforms
name: default
namespace: null
release_date: "2023-09-07"
5.3.0:
changes:
bugfixes:
- Fix attribute types from string to str in filter plugins.
minor_changes:
- Add new module cli_backup that exclusively handles configuration backup.
fragments:
- cli_backup.yaml
- fix_attribute_type.yaml
- sanity_ignores.yaml
- trivial_lint.yaml
release_date: "2023-10-17"
6.0.0:
changes:
major_changes:
- Bumping `requires_ansible` to `>=2.14.0`, since previous ansible-core versions
are EoL now.
release_summary:
Starting from this release, the minimum `ansible-core` version
this collection requires is `2.14.0`. That last known version compatible with
ansible-core<2.14 is `v5.3.0`.
fragments:
- major_600.yml
release_date: "2023-11-30"

View File

@@ -0,0 +1,32 @@
changelog_filename_template: ../CHANGELOG.rst
changelog_filename_version_depth: 0
changes_file: changelog.yaml
changes_format: combined
keep_fragments: false
mention_ancestor: true
new_plugins_after_name: removed_features
notesdir: fragments
prelude_section_name: release_summary
prelude_section_title: Release Summary
flatmap: true
sections:
- - major_changes
- Major Changes
- - minor_changes
- Minor Changes
- - breaking_changes
- Breaking Changes / Porting Guide
- - deprecated_features
- Deprecated Features
- - removed_features
- Removed Features (previously deprecated)
- - security_fixes
- Security Fixes
- - bugfixes
- Bugfixes
- - known_issues
- Known Issues
- - doc_changes
- Documentation Changes
title: Ansible Netcommon Collection
trivial_section_name: trivial

View File

@@ -0,0 +1,12 @@
---
codecov:
require_ci_to_pass: true
comment: false
coverage:
status:
patch: false
project:
default:
threshold: 0.3%
fixes:
- "source/::"

View File

@@ -0,0 +1,149 @@
.. _ansible.netcommon.cli_backup_module:
****************************
ansible.netcommon.cli_backup
****************************
**Back up device configuration from network devices over network_cli**
Version added: 4.2.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This module provides platform agnostic way of backing up text based configuration from network devices over network_cli connection plugin.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>defaults</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>The <em>defaults</em> argument will influence how the running-config is collected from the device. When the value is set to true, the command used to collect the running-config is append with the all keyword. When the value is set to false, the command is issued without the all keyword.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>dir_path</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">path</span>
</div>
</td>
<td>
</td>
<td>
<div>This option provides the path ending with directory name in which the backup configuration file will be stored. If the directory does not exist it will be first created and the filename is either the value of <code>filename</code> or default filename as described in <code>filename</code> options description. If the path value is not given in that case a <em>backup</em> directory will be created in the current working directory and backup configuration will be copied in <code>filename</code> within <em>backup</em> directory.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>filename</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>The filename to be used to store the backup configuration. If the filename is not given it will be generated based on the hostname, current time and date in format defined by &lt;hostname&gt;_config.&lt;current-date&gt;@&lt;current-time&gt;</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- This module is supported on ``ansible_network_os`` network platforms. See the :ref:`Network Platform Options <platform_options>` for details.
Examples
--------
.. code-block:: yaml
- name: configurable backup path
ansible.netcommon.cli_backup:
filename: backup.cfg
dir_path: /home/user
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>backup_path</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>always</td>
<td>
<div>The full path to the backup file</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">/playbooks/ansible/backup/hostname_config.2016-07-16@22:28:34</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Kate Case (@Qalthos)

View File

@@ -0,0 +1,268 @@
.. _ansible.netcommon.cli_command_module:
*****************************
ansible.netcommon.cli_command
*****************************
**Run a cli command on cli-based network devices**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- Sends a command to a network device and returns the result read from the device.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>answer</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
/ <span style="color: purple">elements=string</span>
</div>
</td>
<td>
</td>
<td>
<div>The answer to reply with if <em>prompt</em> is matched. The value can be a single answer or a list of answer for multiple prompts. In case the command execution results in multiple prompts the sequence of the prompt and excepted answer should be in same order.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>check_all</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>By default if any one of the prompts mentioned in <code>prompt</code> option is matched it won&#x27;t check for other prompts. This boolean flag, that when set to <em>True</em> will check for all the prompts mentioned in <code>prompt</code> option in the given order. If the option is set to <em>True</em> all the prompts should be received from remote host if not it will result in timeout.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>command</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
<div>The command to send to the remote network device. The resulting output from the command is returned, unless <em>sendonly</em> is set.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>newline</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>no</li>
<li><div style="color: blue"><b>yes</b>&nbsp;&larr;</div></li>
</ul>
</td>
<td>
<div>The boolean value, that when set to false will send <em>answer</em> to the device without a trailing newline.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>prompt</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
/ <span style="color: purple">elements=string</span>
</div>
</td>
<td>
</td>
<td>
<div>A single regex pattern or a sequence of patterns to evaluate the expected prompt from <em>command</em>.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>sendonly</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>The boolean value, that when set to true will send <em>command</em> to the device but not wait for a result.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- This module is supported on ``ansible_network_os`` network platforms. See the :ref:`Network Platform Options <platform_options>` for details.
Examples
--------
.. code-block:: yaml
- name: run show version on remote devices
ansible.netcommon.cli_command:
command: show version
- name: run command with json formatted output
ansible.netcommon.cli_command:
command: show version | json
- name: run command expecting user confirmation
ansible.netcommon.cli_command:
command: commit replace
prompt: This commit will replace or remove the entire running configuration
answer: "yes"
- name: run command expecting user confirmation
ansible.netcommon.cli_command:
command: show interface summary
prompt: Press any key to continue
answer: y
newline: false
- name: run config mode command and handle prompt/answer
ansible.netcommon.cli_command:
command: "{{ item }}"
prompt:
- Exit with uncommitted changes
answer: y
loop:
- configure
- set system syslog file test any any
- exit
- name: multiple prompt, multiple answer (mandatory check for all prompts)
ansible.netcommon.cli_command:
command: copy sftp sftp://user@host//user/test.img
check_all: true
prompt:
- Confirm download operation
- Password
- Do you want to change that to the standby image
answer:
- y
- <password>
- y
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>json</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
</td>
<td>when the device response is valid JSON</td>
<td>
<div>A dictionary representing a JSON-formatted response</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">{
&quot;architecture&quot;: &quot;i386&quot;,
&quot;bootupTimestamp&quot;: 1532649700.56,
&quot;modelName&quot;: &quot;vEOS&quot;,
&quot;version&quot;: &quot;4.15.9M&quot;
[...]
}</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>stdout</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>when sendonly is false</td>
<td>
<div>The response from the command</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">Version: VyOS 1.1.7[...]</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Nathaniel Case (@Qalthos)

View File

@@ -0,0 +1,418 @@
.. _ansible.netcommon.cli_config_module:
****************************
ansible.netcommon.cli_config
****************************
**Push text based configuration to network devices over network_cli**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This module provides platform agnostic way of pushing text based configuration to network devices over network_cli connection plugin.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="2">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>backup</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>This argument will cause the module to create a full backup of the current running config from the remote device before any changes are made. If the <code>backup_options</code> value is not given, the backup file is written to the <code>backup</code> folder in the playbook root directory or role root directory, if playbook is part of an ansible role. If the directory does not exist, it is created.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>backup_options</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
</td>
<td>
</td>
<td>
<div>This is a dict object containing configurable options related to backup file path. The value of this option is read only when <code>backup</code> is set to <em>yes</em>, if <code>backup</code> is set to <em>no</em> this option will be silently ignored.</div>
</td>
</tr>
<tr>
<td class="elbow-placeholder"></td>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>dir_path</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">path</span>
</div>
</td>
<td>
</td>
<td>
<div>This option provides the path ending with directory name in which the backup configuration file will be stored. If the directory does not exist it will be first created and the filename is either the value of <code>filename</code> or default filename as described in <code>filename</code> options description. If the path value is not given in that case a <em>backup</em> directory will be created in the current working directory and backup configuration will be copied in <code>filename</code> within <em>backup</em> directory.</div>
</td>
</tr>
<tr>
<td class="elbow-placeholder"></td>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>filename</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>The filename to be used to store the backup configuration. If the filename is not given it will be generated based on the hostname, current time and date in format defined by &lt;hostname&gt;_config.&lt;current-date&gt;@&lt;current-time&gt;</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>commit</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>no</li>
<li>yes</li>
</ul>
</td>
<td>
<div>The <code>commit</code> argument instructs the module to push the configuration to the device. This is mapped to module check mode.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>commit_comment</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>The <code>commit_comment</code> argument specifies a text string to be used when committing the configuration. If the <code>commit</code> argument is set to False, this argument is silently ignored. This argument is only valid for the platforms that support commit operation with comment.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>config</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>The config to be pushed to the network device. This argument is mutually exclusive with <code>rollback</code> and either one of the option should be given as input. To ensure idempotency and correct diff the configuration lines should be similar to how they appear if present in the running configuration on device including the indentation.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>defaults</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>The <em>defaults</em> argument will influence how the running-config is collected from the device. When the value is set to true, the command used to collect the running-config is append with the all keyword. When the value is set to false, the command is issued without the all keyword.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>diff_ignore_lines</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
/ <span style="color: purple">elements=string</span>
</div>
</td>
<td>
</td>
<td>
<div>Use this argument to specify one or more lines that should be ignored during the diff. This is used for lines in the configuration that are automatically updated by the system. This argument takes a list of regular expressions or exact line matches. Note that this parameter will be ignored if the platform has onbox diff support.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>diff_match</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>line</li>
<li>strict</li>
<li>exact</li>
<li>none</li>
</ul>
</td>
<td>
<div>Instructs the module on the way to perform the matching of the set of commands against the current device config. If <code>diff_match</code> is set to <em>line</em>, commands are matched line by line. If <code>diff_match</code> is set to <em>strict</em>, command lines are matched with respect to position. If <code>diff_match</code> is set to <em>exact</em>, command lines must be an equal match. Finally, if <code>diff_match</code> is set to <em>none</em>, the module will not attempt to compare the source configuration with the running configuration on the remote device. Note that this parameter will be ignored if the platform has onbox diff support.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>diff_replace</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>line</li>
<li>block</li>
<li>config</li>
</ul>
</td>
<td>
<div>Instructs the module on the way to perform the configuration on the device. If the <code>diff_replace</code> argument is set to <em>line</em> then the modified lines are pushed to the device in configuration mode. If the argument is set to <em>block</em> then the entire command block is pushed to the device in configuration mode if any line is not correct. Note that this parameter will be ignored if the platform has onbox diff support.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>multiline_delimiter</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>This argument is used when pushing a multiline configuration element to the device. It specifies the character to use as the delimiting character. This only applies to the configuration action.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>replace</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>If the <code>replace</code> argument is set to <code>yes</code>, it will replace the entire running-config of the device with the <code>config</code> argument value. For devices that support replacing running configuration from file on device like NXOS/JUNOS, the <code>replace</code> argument takes path to the file on the device that will be used for replacing the entire running-config. The value of <code>config</code> option should be <em>None</em> for such devices. Nexus 9K devices only support replace. Use <em>net_put</em> or <em>nxos_file_copy</em> in case of NXOS module to copy the flat file to remote device and then use set the fullpath to this argument.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>rollback</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
</td>
<td>
<div>The <code>rollback</code> argument instructs the module to rollback the current configuration to the identifier specified in the argument. If the specified rollback identifier does not exist on the remote device, the module will fail. To rollback to the most recent commit, set the <code>rollback</code> argument to 0. This option is mutually exclusive with <code>config</code>.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- The commands will be returned only for platforms that do not support onbox diff. The ``--diff`` option with the playbook will return the difference in configuration for devices that has support for onbox diff
- To ensure idempotency and correct diff the configuration lines in the relevant module options should be similar to how they appear if present in the running configuration on device including the indentation.
- This module is supported on ``ansible_network_os`` network platforms. See the :ref:`Network Platform Options <platform_options>` for details.
Examples
--------
.. code-block:: yaml
- name: configure device with config
ansible.netcommon.cli_config:
config: "{{ lookup('template', 'basic/config.j2') }}"
- name: multiline config
ansible.netcommon.cli_config:
config: |
hostname foo
feature nxapi
- name: configure device with config with defaults enabled
ansible.netcommon.cli_config:
config: "{{ lookup('template', 'basic/config.j2') }}"
defaults: "yes"
- name: Use diff_match
ansible.netcommon.cli_config:
config: "{{ lookup('file', 'interface_config') }}"
diff_match: none
- name: nxos replace config
ansible.netcommon.cli_config:
replace: bootflash:nxoscfg
- name: junos replace config
ansible.netcommon.cli_config:
replace: /var/home/ansible/junos01.cfg
- name: commit with comment
ansible.netcommon.cli_config:
config: set system host-name foo
commit_comment: this is a test
- name: configurable backup path
ansible.netcommon.cli_config:
config: "{{ lookup('template', 'basic/config.j2') }}"
backup: "yes"
backup_options:
filename: backup.cfg
dir_path: /home/user
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>backup_path</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>when backup is yes</td>
<td>
<div>The full path to the backup file</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">/playbooks/ansible/backup/hostname_config.2016-07-16@22:28:34</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>commands</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>When <em>supports_generated_diff=True</em> and <em>supports_onbox_diff=False</em> in the platform&#x27;s cliconf plugin</td>
<td>
<div>The set of commands that will be pushed to the remote device</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[&#x27;interface Loopback999&#x27;, &#x27;no shutdown&#x27;]</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>diff</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>When <em>supports_onbox_diff=True</em> in the platform&#x27;s cliconf plugin</td>
<td>
<div>The diff generated on the device when the commands were applied</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">--- system:/running-config
+++ session:/ansible_1599745461-session-config
@@ -4,7 +4,7 @@
!
transceiver qsfp default-mode 4x10G
!
-hostname veos
+hostname veos3
!
spanning-tree mode mstp</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Trishna Guha (@trishnaguha)

View File

@@ -0,0 +1,152 @@
.. _ansible.netcommon.comp_type5_filter:
****************************
ansible.netcommon.comp_type5
****************************
**The comp_type5 filter plugin.**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- The filter confirms configuration idempotency on use of type5_pw.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>encrypted_password</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>The encrypted text.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>return_original</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>no</li>
<li>yes</li>
</ul>
</td>
<td>
</td>
<td>
<div>Return the original text.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>unencrypted_password</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>The unencrypted text.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- The filter confirms configuration idempotency on use of type5_pw.
- Can be used to validate password post hashing username cisco secret 5 {{ ansible_ssh_pass | ansible.netcommon.comp_type5(encrypted, True) }}
Examples
--------
.. code-block:: yaml
# Using comp_type5
# playbook
- name: Set the facts
ansible.builtin.set_fact:
unencrypted_password: "cisco@123"
encrypted_password: "$1$avs$uSTOEMh65ADDBREAKqzvpb9yBMpzd/"
- name: Invoke comp_type5
ansible.builtin.debug:
msg: "{{ unencrypted_password | ansible.netcommon.comp_type5(encrypted_password, False) }}"
# Task Output
# -----------
#
# TASK [Set the facts]
# ok: [35.155.113.92] => changed=false
# ansible_facts:
# encrypted_password: $1$avs$uSTOEMh65ADDBREAKqzvpb9yBMpzd/
# unencrypted_password: cisco@123
# TASK [Invoke comp_type5]
# ok: [35.155.113.92] =>
# msg: true
Status
------
Authors
~~~~~~~
- Ken Celenza (@itdependsnetworks)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,43 @@
.. _ansible.netcommon.default_cliconf:
*************************
ansible.netcommon.default
*************************
**General purpose cliconf plugin for new platforms**
Version added: 5.2.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This plugin attemts to provide low level abstraction apis for sending and receiving CLI commands from arbitrary network devices.
Status
------
Authors
~~~~~~~
- Ansible Networking Team (@ansible-network)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,76 @@
.. _ansible.netcommon.default_netconf:
*************************
ansible.netcommon.default
*************************
**Use default netconf plugin to run standard netconf commands as per RFC**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This default plugin provides low level abstraction apis for sending and receiving netconf commands as per Netconf RFC specification.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>ncclient_device_handler</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"default"</div>
</td>
<td>
</td>
<td>
<div>Specifies the ncclient device handler name for network os that support default netconf implementation as per Netconf RFC specification. To identify the ncclient device handler name refer ncclient library documentation.</div>
</td>
</tr>
</table>
<br/>
Status
------
Authors
~~~~~~~
- Ansible Networking Team (@ansible-network)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,90 @@
.. _ansible.netcommon.enable_become:
************************
ansible.netcommon.enable
************************
**Switch to elevated permissions on a network device**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This become plugins allows elevated permissions on a remote network device.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>become_pass</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[enable_become_plugin]<br>password = VALUE</p>
</div>
<div>env:ANSIBLE_BECOME_PASS</div>
<div>env:ANSIBLE_ENABLE_PASS</div>
<div>var: ansible_become_password</div>
<div>var: ansible_become_pass</div>
<div>var: ansible_enable_pass</div>
</td>
<td>
<div>password</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- enable is really implemented in the network connection handler and as such can only be used with network connections.
- This plugin ignores the 'become_exe' and 'become_user' settings as it uses an API and not an executable.
Status
------
Authors
~~~~~~~
- Ansible Networking Team (@ansible-network)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,285 @@
.. _ansible.netcommon.grpc_config_module:
*****************************
ansible.netcommon.grpc_config
*****************************
**Fetch configuration/state data from gRPC enabled target hosts.**
Version added: 3.1.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- gRPC is a high performance, open-source universal RPC framework.
- This module allows the user to append configs to an existing configuration in a gRPC enabled devices.
Requirements
------------
The below requirements are needed on the host that executes this module.
- grpcio
- protobuf
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="2">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>backup</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>This argument will cause the module to create a full backup of the current <code>running-config</code> from the remote device before any changes are made. If the <code>backup_options</code> value is not given, the backup file is written to the <code>backup</code> folder in the playbook root directory or role root directory, if playbook is part of an ansible role. If the directory does not exist, it is created.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>backup_options</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
</td>
<td>
</td>
<td>
<div>This is a dict object containing configurable options related to backup file path. The value of this option is read only when <code>backup</code> is set to <em>yes</em>, if <code>backup</code> is set to <em>no</em> this option will be silently ignored.</div>
</td>
</tr>
<tr>
<td class="elbow-placeholder"></td>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>dir_path</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">path</span>
</div>
</td>
<td>
</td>
<td>
<div>This option provides the path ending with directory name in which the backup configuration file will be stored. If the directory does not exist it will be first created and the filename is either the value of <code>filename</code> or default filename as described in <code>filename</code> options description. If the path value is not given in that case a <em>backup</em> directory will be created in the current working directory and backup configuration will be copied in <code>filename</code> within <em>backup</em> directory.</div>
</td>
</tr>
<tr>
<td class="elbow-placeholder"></td>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>filename</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>The filename to be used to store the backup configuration. If the filename is not given it will be generated based on the hostname, current time and date in format defined by &lt;hostname&gt;_config.&lt;current-date&gt;@&lt;current-time&gt;</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>config</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>This option specifies the string which acts as a filter to restrict the portions of the data to be retrieved from the target host device. If this option is not specified the entire configuration or state data is returned in response provided it is supported by target host.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>state</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>action to be performed</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- This module requires the gRPC system service be enabled on the target host being managed.
- This module supports the use of connection=connection=ansible.netcommon.grpc
- This module requires the value of 'ansible_network_os' or 'grpc_type' configuration option (refer ansible.netcommon.grpc connection plugin documentation) be defined as an inventory variable.
- Tested against iosxrv 9k version 6.1.2.
Examples
--------
.. code-block:: yaml
- name: Merge static route config
ansible.netcommon.grpc_config:
config:
Cisco-IOS-XR-ip-static-cfg:router-static:
default-vrf:
address-family:
vrfipv4:
vrf-unicast:
vrf-prefixes:
vrf-prefix:
- prefix: "1.2.3.6"
prefix-length: 32
vrf-route:
vrf-next-hop-table:
vrf-next-hop-next-hop-address:
- next-hop-address: "10.0.2.2"
state: merged
- name: Merge bgp config
ansible.netcommon.grpc_config:
config: "{{ lookup('file', 'bgp.json') }}"
state: merged
- name: Find diff
diff: true
ansible.netcommon.grpc_config:
config: "{{ lookup('file', 'bgp_start.yml') }}"
state: merged
- name: Backup running config
ansible.netcommon.grpc_config:
backup: true
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>backup_path</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>when backup is yes</td>
<td>
<div>The full path to the backup file</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">/playbooks/ansible/backup/config.2022-07-16@22:28:34</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>diff</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
</td>
<td>when diff is enabled</td>
<td>
<div>If --diff option in enabled while running, the before and after configuration change are returned as part of before and after key.</div>
<br/>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>stdout</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>error mesage, when failure happens. empty , when the operation is successful</td>
<td>
<div>The raw string containing response object received from the gRPC server.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">...</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>stdout_lines</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>always apart from low-level errors (such as action plugin)</td>
<td>
<div>The value of stdout split into a list</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[&#x27;...&#x27;, &#x27;...&#x27;]</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Gomathi Selvi S (@GomathiselviS)

View File

@@ -0,0 +1,371 @@
.. _ansible.netcommon.grpc_connection:
**********************
ansible.netcommon.grpc
**********************
**Provides a persistent connection using the gRPC protocol**
Version added: 3.1.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This connection plugin provides a connection to remote devices over gRPC and is typically used with devices for sending and receiving RPC calls over gRPC framework.
- Note this connection plugin requires the grpcio python library to be installed on the local Ansible controller.
Requirements
------------
The below requirements are needed on the local Ansible controller node that executes this connection.
- grpcio
- protobuf
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>certificate_chain_file</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[grpc_connection]<br>certificate_chain_file = VALUE</p>
</div>
<div>env:ANSIBLE_CERTIFICATE_CHAIN_FILE</div>
<div>var: ansible_certificate_chain_file</div>
</td>
<td>
<div>The PEM encoded certificate chain file used to create a SSL-enabled channel. If the value is None, no certificate chain is used.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>grpc_type</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div> ini entries:
<p>[grpc_connection]<br>type = no</p>
</div>
<div>env:ANSIBLE_GRPC_CONNECTION_TYPE</div>
<div>var: ansible_grpc_connection_type</div>
</td>
<td>
<div>This option indicates the grpc type and it can be used in place of network_os. (example cisco.iosxr.iosxr)</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>host</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"inventory_hostname"</div>
</td>
<td>
<div>var: ansible_host</div>
</td>
<td>
<div>Specifies the remote device FQDN or IP address to establish the gRPC connection to.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>import_modules</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div> ini entries:
<p>[ansible_network]<br>import_modules = yes</p>
</div>
<div>env:ANSIBLE_NETWORK_IMPORT_MODULES</div>
<div>var: ansible_network_import_modules</div>
</td>
<td>
<div>Reduce CPU usage and network module execution time by enabling direct execution. Instead of the module being packaged and executed by the shell, it will be directly executed by the Ansible control node using the same python interpreter as the Ansible process. Note- Incompatible with <code>asynchronous mode</code>. Note- Python 3 and Ansible 2.9.16 or greater required. Note- With Ansible 2.9.x fully qualified modules names are required in tasks.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>network_os</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_network_os</div>
</td>
<td>
<div>Configures the device platform network operating system. This value is used to load a device specific grpc plugin to communicate with the remote device.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>password</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_password</div>
<div>var: ansible_ssh_pass</div>
</td>
<td>
<div>Configures the user password used to authenticate to the remote device when first establishing the gRPC connection.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_command_timeout</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">30</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>command_timeout = 30</p>
</div>
<div>env:ANSIBLE_PERSISTENT_COMMAND_TIMEOUT</div>
<div>var: ansible_command_timeout</div>
</td>
<td>
<div>Configures, in seconds, the amount of time to wait for a command to return from the remote device. If this timer is exceeded before the command returns, the connection plugin will raise an exception and close.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_connect_timeout</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">30</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>connect_timeout = 30</p>
</div>
<div>env:ANSIBLE_PERSISTENT_CONNECT_TIMEOUT</div>
<div>var: ansible_connect_timeout</div>
</td>
<td>
<div>Configures, in seconds, the amount of time to wait when trying to initially establish a persistent connection. If this value expires before the connection to the remote device is completed, the connection will fail.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_log_messages</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>log_messages = no</p>
</div>
<div>env:ANSIBLE_PERSISTENT_LOG_MESSAGES</div>
<div>var: ansible_persistent_log_messages</div>
</td>
<td>
<div>This flag will enable logging the command executed and response received from target device in the ansible log file. For this option to work &#x27;log_path&#x27; ansible configuration option is required to be set to a file path with write access.</div>
<div>Be sure to fully understand the security implications of enabling this option as it could create a security vulnerability by logging sensitive information in log file.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>port</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>remote_port = VALUE</p>
</div>
<div>env:ANSIBLE_REMOTE_PORT</div>
<div>var: ansible_port</div>
</td>
<td>
<div>Specifies the port on the remote device that listens for connections when establishing the gRPC connection. If None only the <code>host</code> part will be used.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>private_key_file</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[grpc_connection]<br>private_key_file = VALUE</p>
</div>
<div>env:ANSIBLE_PRIVATE_KEY_FILE</div>
<div>var: ansible_private_key_file</div>
</td>
<td>
<div>The PEM encoded private key file used to authenticate to the remote device when first establishing the grpc connection.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>remote_user</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>remote_user = VALUE</p>
</div>
<div>env:ANSIBLE_REMOTE_USER</div>
<div>var: ansible_user</div>
</td>
<td>
<div>The username used to authenticate to the remote device when the gRPC connection is first established. If the remote_user is not specified, the connection will use the username of the logged in user.</div>
<div>Can be configured from the CLI via the <code>--user</code> or <code>-u</code> options.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>root_certificates_file</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[grpc_connection]<br>root_certificates_file = VALUE</p>
</div>
<div>env:ANSIBLE_ROOT_CERTIFICATES_FILE</div>
<div>var: ansible_root_certificates_file</div>
</td>
<td>
<div>The PEM encoded root certificate file used to create a SSL-enabled channel, if the value is None it reads the root certificates from a default location chosen by gRPC at runtime.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>ssl_target_name_override</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[grpc_connection]<br>ssl_target_name_override = VALUE</p>
</div>
<div>env:ANSIBLE_GPRC_SSL_TARGET_NAME_OVERRIDE</div>
<div>var: ansible_grpc_ssl_target_name_override</div>
</td>
<td>
<div>The option overrides SSL target name used for SSL host name checking. The name used for SSL host name checking will be the target parameter (assuming that the secure channel is an SSL channel). If this parameter is specified and the underlying is not an SSL channel, it will just be ignored.</div>
</td>
</tr>
</table>
<br/>
Status
------
Authors
~~~~~~~
- Ansible Networking Team (@ansible-network)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,241 @@
.. _ansible.netcommon.grpc_get_module:
**************************
ansible.netcommon.grpc_get
**************************
**Fetch configuration/state data from gRPC enabled target hosts.**
Version added: 3.1.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- gRPC is a high performance, open-source universal RPC framework.
- This module allows the user to fetch configuration and state data from gRPC enabled devices.
Requirements
------------
The below requirements are needed on the host that executes this module.
- grpcio
- protobuf
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>command</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>The option specifies the command to be executed on the target host and return the response in result. This option is supported if the gRPC target host supports executing CLI command over the gRPC connection.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>data_type</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>The type of data that should be fetched from the target host. The value depends on the capability of the gRPC server running on target host. The values can be <em>config</em>, <em>oper</em> etc. based on what is supported by the gRPC server. By default it will return both configuration and operational state data in response.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>display</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>Encoding scheme to use when serializing output from the device. The encoding scheme value depends on the capability of the gRPC server running on the target host. The values can be <em>json</em>, <em>text</em> etc.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>section</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>This option specifies the string which acts as a filter to restrict the portions of the data to be retrieved from the target host device. If this option is not specified the entire configuration or state data is returned in response provided it is supported by target host.</div>
<div style="font-size: small; color: darkgreen"><br/>aliases: filter</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- This module requires the gRPC system service be enabled on the target host being managed.
- This module supports the use of connection=ansible.netcommon.grpc.
- This module requires the value of 'ansible_network_os or grpc_type' configuration option (refer ansible.netcommon.grpc connection plugin documentation) be defined as an inventory variable.
- Tested against iosxrv 9k version 6.1.2.
Examples
--------
.. code-block:: yaml
- name: Get bgp configuration data
grpc_get:
section:
Cisco-IOS-XR-ip-static-cfg:router-static:
- null
- name: run cli command
grpc_get:
command: "show version"
display: text
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>output</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>when the device response is valid JSON</td>
<td>
<div>A dictionary representing a JSON-formatted response, if the response is a valid json string</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[{
&quot;Cisco-IOS-XR-ip-static-cfg:router-static&quot;: {
&quot;default-vrf&quot;: {
&quot;address-family&quot;: {
&quot;vrfipv4&quot;: {
&quot;vrf-unicast&quot;: {
&quot;vrf-prefixes&quot;: {
&quot;vrf-prefix&quot;: [
{
&quot;prefix&quot;: &quot;0.0.0.0&quot;,
&quot;prefix-length&quot;: 0,
&quot;vrf-route&quot;: {
&quot;vrf-next-hop-table&quot;: {
&quot;vrf-next-hop-interface-name-next-hop-address&quot;: [
{
&quot;interface-name&quot;: &quot;MgmtEth0/RP0/CPU0/0&quot;,
&quot;next-hop-address&quot;: &quot;10.0.2.2&quot;
}
]
}
}
}
]
}
}
}
}
}
}
}]</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>stdout</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>always apart from low-level errors (such as action plugin)</td>
<td>
<div>The raw string containing configuration or state data received from the gRPC server.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">...</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>stdout_lines</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>always apart from low-level errors (such as action plugin)</td>
<td>
<div>The value of stdout split into a list</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[&#x27;...&#x27;, &#x27;...&#x27;]</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Ganesh Nalawade (@ganeshrn)
- Gomathi Selvi S (@GomathiselviS)

View File

@@ -0,0 +1,113 @@
.. _ansible.netcommon.hash_salt_filter:
***************************
ansible.netcommon.hash_salt
***************************
**The hash_salt filter plugin.**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- The filter plugin produces the salt from a hashed password.
- Using the parameters below - ``password | ansible.netcommon.hash_salt(template.yml``)
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>password</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>This source data on which hash_salt invokes.</div>
<div>For example <code>password | ansible.netcommon.hash_salt</code>, in this case <code>password</code> represents the hashed password.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- The filter plugin produces the salt from a hashed password.
Examples
--------
.. code-block:: yaml
# Using hash_salt
# playbook
- name: Set the facts
ansible.builtin.set_fact:
password: "$1$avs$uSTOEMh65ADDBREAKqzvpb9yBMpzd/"
- name: Invoke hash_salt
ansible.builtin.debug:
msg: "{{ password | ansible.netcommon.hash_salt() }}"
# Task Output
# -----------
#
# TASK [Set the facts]
# ok: [host] => changed=false
# ansible_facts:
# password: $1$avs$uSTOEMh65ADDBREAKqzvpb9yBMpzd/
# TASK [Invoke hash_salt]
# ok: [host] =>
# msg: avs
Status
------
Authors
~~~~~~~
- Ken Celenza (@itdependsnetworks)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,498 @@
.. _ansible.netcommon.httpapi_connection:
*************************
ansible.netcommon.httpapi
*************************
**Use httpapi to run command on network appliances**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This connection plugin provides a connection to remote devices over a HTTP(S)-based api.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>become</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div> ini entries:
<p>[privilege_escalation]<br>become = no</p>
</div>
<div>env:ANSIBLE_BECOME</div>
<div>var: ansible_become</div>
</td>
<td>
<div>The become option will instruct the CLI session to attempt privilege escalation on platforms that support it. Normally this means transitioning from user mode to <code>enable</code> mode in the CLI session. If become is set to True and the remote device does not support privilege escalation or the privilege has already been elevated, then this option is silently ignored.</div>
<div>Can be configured from the CLI via the <code>--become</code> or <code>-b</code> options.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>become_method</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"sudo"</div>
</td>
<td>
<div> ini entries:
<p>[privilege_escalation]<br>become_method = sudo</p>
</div>
<div>env:ANSIBLE_BECOME_METHOD</div>
<div>var: ansible_become_method</div>
</td>
<td>
<div>This option allows the become method to be specified in for handling privilege escalation. Typically the become_method value is set to <code>enable</code> but could be defined as other values.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>ca_path</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">path</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.2.0</div>
</td>
<td>
</td>
<td>
<div>var: ansible_httpapi_ca_path</div>
</td>
<td>
<div>Path to CA cert bundle to use.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>ciphers</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
/ <span style="color: purple">elements=string</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.0.0</div>
</td>
<td>
</td>
<td>
<div>var: ansible_httpapi_ciphers</div>
</td>
<td>
<div>SSL/TLS Ciphers to use for requests</div>
<div>When a list is provided, all ciphers are joined in order with <code>:</code></div>
<div>See the <a href='https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html#CIPHER-LIST-FORMAT'>OpenSSL Cipher List Format</a> for more details.</div>
<div>The available ciphers is dependent on the Python and OpenSSL/LibreSSL versions.</div>
<div>This option will have no effect on ansible-core&lt;2.14 but a warning will be emitted.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>client_cert</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.2.0</div>
</td>
<td>
</td>
<td>
<div>var: ansible_httpapi_client_cert</div>
</td>
<td>
<div>PEM formatted certificate chain file to be used for SSL client authentication. This file can also include the key as well, and if the key is included, <em>client_key</em> is not required</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>client_key</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.2.0</div>
</td>
<td>
</td>
<td>
<div>var: ansible_httpapi_client_key</div>
</td>
<td>
<div>PEM formatted file that contains the private key to be used for SSL client authentication. If <em>client_cert</em> contains both the certificate and key, this option is not required.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>host</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"inventory_hostname"</div>
</td>
<td>
<div>var: inventory_hostname</div>
<div>var: ansible_host</div>
</td>
<td>
<div>Specifies the remote device FQDN or IP address to establish the HTTP(S) connection to.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>http_agent</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.2.0</div>
</td>
<td>
</td>
<td>
<div>var: ansible_httpapi_http_agent</div>
</td>
<td>
<div>User-Agent to use in the request.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>import_modules</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div> ini entries:
<p>[ansible_network]<br>import_modules = yes</p>
</div>
<div>env:ANSIBLE_NETWORK_IMPORT_MODULES</div>
<div>var: ansible_network_import_modules</div>
</td>
<td>
<div>Reduce CPU usage and network module execution time by enabling direct execution. Instead of the module being packaged and executed by the shell, it will be directly executed by the Ansible control node using the same python interpreter as the Ansible process. Note- Incompatible with <code>asynchronous mode</code>. Note- Python 3 and Ansible 2.9.16 or greater required. Note- With Ansible 2.9.x fully qualified modules names are required in tasks.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>network_os</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_network_os</div>
</td>
<td>
<div>Configures the device platform network operating system. This value is used to load the correct httpapi plugin to communicate with the remote device</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>password</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_password</div>
<div>var: ansible_httpapi_pass</div>
<div>var: ansible_httpapi_password</div>
</td>
<td>
<div>Configures the user password used to authenticate to the remote device when needed for the device API.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_command_timeout</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">30</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>command_timeout = 30</p>
</div>
<div>env:ANSIBLE_PERSISTENT_COMMAND_TIMEOUT</div>
<div>var: ansible_command_timeout</div>
</td>
<td>
<div>Configures, in seconds, the amount of time to wait for a command to return from the remote device. If this timer is exceeded before the command returns, the connection plugin will raise an exception and close.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_connect_timeout</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">30</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>connect_timeout = 30</p>
</div>
<div>env:ANSIBLE_PERSISTENT_CONNECT_TIMEOUT</div>
<div>var: ansible_connect_timeout</div>
</td>
<td>
<div>Configures, in seconds, the amount of time to wait when trying to initially establish a persistent connection. If this value expires before the connection to the remote device is completed, the connection will fail.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_log_messages</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>log_messages = no</p>
</div>
<div>env:ANSIBLE_PERSISTENT_LOG_MESSAGES</div>
<div>var: ansible_persistent_log_messages</div>
</td>
<td>
<div>This flag will enable logging the command executed and response received from target device in the ansible log file. For this option to work &#x27;log_path&#x27; ansible configuration option is required to be set to a file path with write access.</div>
<div>Be sure to fully understand the security implications of enabling this option as it could create a security vulnerability by logging sensitive information in log file.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>platform_type</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>env:ANSIBLE_PLATFORM_TYPE</div>
<div>var: ansible_platform_type</div>
</td>
<td>
<div>Set type of platform.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>port</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>remote_port = VALUE</p>
</div>
<div>env:ANSIBLE_REMOTE_PORT</div>
<div>var: ansible_httpapi_port</div>
</td>
<td>
<div>Specifies the port on the remote device that listens for connections when establishing the HTTP(S) connection.</div>
<div>When unspecified, will pick 80 or 443 based on the value of use_ssl.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>remote_user</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>remote_user = VALUE</p>
</div>
<div>env:ANSIBLE_REMOTE_USER</div>
<div>var: ansible_user</div>
</td>
<td>
<div>The username used to authenticate to the remote device when the API connection is first established. If the remote_user is not specified, the connection will use the username of the logged in user.</div>
<div>Can be configured from the CLI via the <code>--user</code> or <code>-u</code> options.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>session_key</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_httpapi_session_key</div>
</td>
<td>
<div>Configures the session key to be used to authenticate to the remote device when needed for the device API.</div>
<div>This should contain a dictionary representing the key name and value for the token.</div>
<div>When specified, <em>password</em> is ignored.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>use_proxy</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div>var: ansible_httpapi_use_proxy</div>
</td>
<td>
<div>Whether to use https_proxy for requests.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>use_ssl</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div>var: ansible_httpapi_use_ssl</div>
</td>
<td>
<div>Whether to connect using SSL (HTTPS) or not (HTTP).</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>validate_certs</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div>var: ansible_httpapi_validate_certs</div>
</td>
<td>
<div>Whether to validate SSL certificates</div>
</td>
</tr>
</table>
<br/>
Status
------
Authors
~~~~~~~
- Ansible Networking Team (@ansible-network)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,390 @@
.. _ansible.netcommon.libssh_connection:
************************
ansible.netcommon.libssh
************************
**Run tasks using libssh for ssh connection**
Version added: 1.1.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- Use the ansible-pylibssh python bindings to connect to targets
- The python bindings use libssh C library (https://www.libssh.org/) to connect to targets
- This plugin borrows a lot of settings from the ssh plugin as they both cover the same protocol.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>config_file</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">path</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.1.0</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[libssh_connection]<br>config_file = VALUE</p>
</div>
<div>env:ANSIBLE_LIBSSH_CONFIG_FILE</div>
<div>var: ansible_libssh_config_file</div>
</td>
<td>
<div>Alternate SSH config file location</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>host_key_auto_add</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[libssh_connection]<br>host_key_auto_add = VALUE</p>
</div>
<div>env:ANSIBLE_LIBSSH_HOST_KEY_AUTO_ADD</div>
</td>
<td>
<div>TODO: write it</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>host_key_checking</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>host_key_checking = yes</p>
<p>[libssh_connection]<br>host_key_checking = yes</p>
</div>
<div>env:ANSIBLE_HOST_KEY_CHECKING</div>
<div>env:ANSIBLE_SSH_HOST_KEY_CHECKING</div>
<div>env:ANSIBLE_LIBSSH_HOST_KEY_CHECKING</div>
<div>var: ansible_host_key_checking</div>
<div>var: ansible_ssh_host_key_checking</div>
<div>var: ansible_libssh_host_key_checking</div>
</td>
<td>
<div>Set this to &quot;False&quot; if you want to avoid host key checking by the underlying tools Ansible uses to connect to the host</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>look_for_keys</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div> ini entries:
<p>[libssh_connection]<br>look_for_keys = yes</p>
</div>
<div>env:ANSIBLE_LIBSSH_LOOK_FOR_KEYS</div>
</td>
<td>
<div>TODO: write it</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>password</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_password</div>
<div>var: ansible_ssh_pass</div>
<div>var: ansible_ssh_password</div>
<div>var: ansible_libssh_pass</div>
<div>var: ansible_libssh_password</div>
</td>
<td>
<div>Secret used to either login the ssh server or as a passphrase for ssh keys that require it</div>
<div>Can be set from the CLI via the <code>--ask-pass</code> option.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>password_prompt</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.1.0</div>
</td>
<td>
</td>
<td>
<div>var: ansible_libssh_password_prompt</div>
</td>
<td>
<div>Text to match when using keyboard-interactive authentication to determine if the prompt is for the password.</div>
<div>Requires ansible-pylibssh version &gt;= 1.0.0</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>proxy_command</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">""</div>
</td>
<td>
<div> ini entries:
<p>[libssh_connection]<br>proxy_command = </p>
</div>
<div>env:ANSIBLE_LIBSSH_PROXY_COMMAND</div>
<div>var: ansible_paramiko_proxy_command</div>
<div>var: ansible_libssh_proxy_command</div>
</td>
<td>
<div>Proxy information for running the connection via a jumphost.</div>
<div>Also this plugin will scan &#x27;ssh_args&#x27;, &#x27;ssh_extra_args&#x27; and &#x27;ssh_common_args&#x27; from the &#x27;ssh&#x27; plugin settings for proxy information if set.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>pty</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div> ini entries:
<p>[libssh_connection]<br>pty = yes</p>
</div>
<div>env:ANSIBLE_LIBSSH_PTY</div>
</td>
<td>
<div>TODO: write it</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>remote_addr</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"inventory_hostname"</div>
</td>
<td>
<div>var: inventory_hostname</div>
<div>var: ansible_host</div>
<div>var: ansible_ssh_host</div>
<div>var: ansible_libssh_host</div>
</td>
<td>
<div>Address of the remote target</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>remote_user</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>remote_user = VALUE</p>
<p>[libssh_connection]<br>remote_user = VALUE</p>
</div>
<div>env:ANSIBLE_REMOTE_USER</div>
<div>env:ANSIBLE_LIBSSH_REMOTE_USER</div>
<div>var: ansible_user</div>
<div>var: ansible_ssh_user</div>
<div>var: ansible_libssh_user</div>
</td>
<td>
<div>User to login/authenticate as</div>
<div>Can be set from the CLI via the <code>--user</code> or <code>-u</code> options.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>ssh_args</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.2.0</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[ssh_connection]<br>ssh_args = VALUE</p>
</div>
<div>env:ANSIBLE_SSH_ARGS</div>
<div>var: ansible_ssh_args</div>
</td>
<td>
<div>Arguments to pass to all ssh CLI tools.</div>
<div>ProxyCommand is the only supported argument.</div>
<div>This option is deprecated in favor of <em>proxy_command</em> and will be removed in a release after 2026-01-01.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>ssh_common_args</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.2.0</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[ssh_connection]<br>ssh_common_args = VALUE</p>
</div>
<div>env:ANSIBLE_SSH_COMMON_ARGS</div>
<div>var: ansible_ssh_common_args</div>
</td>
<td>
<div>Common extra arguments for all ssh CLI tools.</div>
<div>ProxyCommand is the only supported argument.</div>
<div>This option is deprecated in favor of <em>proxy_command</em> and will be removed in a release after 2026-01-01.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>ssh_extra_args</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.2.0</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[ssh_connection]<br>ssh_extra_args = VALUE</p>
</div>
<div>env:ANSIBLE_SSH_EXTRA_ARGS</div>
<div>var: ansible_ssh_extra_args</div>
</td>
<td>
<div>Extra arguments exclusive to the &#x27;ssh&#x27; CLI tool.</div>
<div>ProxyCommand is the only supported argument.</div>
<div>This option is deprecated in favor of <em>proxy_command</em> and will be removed in a release after 2026-01-01.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>use_persistent_connections</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>use_persistent_connections = no</p>
</div>
<div>env:ANSIBLE_USE_PERSISTENT_CONNECTIONS</div>
</td>
<td>
<div>Toggles the use of persistence for connections</div>
</td>
</tr>
</table>
<br/>
Status
------
Authors
~~~~~~~
- Ansible Networking Team (@ansible-network)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,132 @@
.. _ansible.netcommon.net_get_module:
*************************
ansible.netcommon.net_get
*************************
**Copy a file from a network device to Ansible Controller**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This module provides functionality to copy file from network device to ansible controller.
Requirements
------------
The below requirements are needed on the host that executes this module.
- scp if using protocol=scp with paramiko
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>dest</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">["Same filename as specified in I(src). The path will be playbook root or role root directory if playbook is part of a role."]</div>
</td>
<td>
<div>Specifies the destination file. The path to the destination file can either be the full path on the Ansible control host or a relative path from the playbook or role root directory.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>protocol</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>scp</b>&nbsp;&larr;</div></li>
<li>sftp</li>
</ul>
</td>
<td>
<div>Protocol used to transfer file.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>src</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
<div>Specifies the source file. The path to the source file can either be the full path on the network device or a relative path as per path supported by destination network device.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- Some devices need specific configurations to be enabled before scp can work These configuration should be pre-configured before using this module e.g ios - ``ip scp server enable``.
- User privilege to do scp on network device should be pre-configured e.g. ios - need user privilege 15 by default for allowing scp.
- Default destination of source file.
- This module is supported on ``ansible_network_os`` network platforms. See the :ref:`Network Platform Options <platform_options>` for details.
Examples
--------
.. code-block:: yaml
- name: copy file from the network device to Ansible controller
ansible.netcommon.net_get:
src: running_cfg_ios1.txt
- name: copy file from ios to common location at /tmp
ansible.netcommon.net_get:
src: running_cfg_sw1.txt
dest: /tmp/ios1.txt
Status
------
Authors
~~~~~~~
- Deepak Agrawal (@dagrawal)

View File

@@ -0,0 +1,273 @@
.. _ansible.netcommon.net_ping_module:
**************************
ansible.netcommon.net_ping
**************************
**Tests reachability using ping from a network device**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- Tests reachability using ping from network device to a remote destination.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>count</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">5</div>
</td>
<td>
<div>Number of packets to send.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>dest</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
<div>The IP Address or hostname (resolvable by switch) of the remote node.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>source</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
</td>
<td>
<div>The source IP Address.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>state</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>absent</li>
<li><div style="color: blue"><b>present</b>&nbsp;&larr;</div></li>
</ul>
</td>
<td>
<div>Determines if the expected result is success or fail.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>vrf</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"default"</div>
</td>
<td>
<div>The VRF to use for forwarding.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- For targets running Python, use the :ref:`ansible.builtin.shell <ansible.builtin.shell_module>` module along with ping command instead.
- This module is supported on ``ansible_network_os`` network platforms. See the :ref:`Network Platform Options <platform_options>` for details.
Examples
--------
.. code-block:: yaml
- name: Test reachability to 10.10.10.10 using default vrf
ansible.netcommon.net_ping:
dest: 10.10.10.10
- name: Test reachability to 10.20.20.20 using prod vrf
ansible.netcommon.net_ping:
dest: 10.20.20.20
vrf: prod
- name: Test unreachability to 10.30.30.30 using default vrf
ansible.netcommon.net_ping:
dest: 10.30.30.30
state: absent
- name: Test reachability to 10.40.40.40 using prod vrf and setting count and source
ansible.netcommon.net_ping:
dest: 10.40.40.40
source: loopback0
vrf: prod
count: 20
- Note:
- For targets running Python, use the M(ansible.builtin.shell) module along with ping command instead.
- Example:
name: ping
shell: ping -c 1 <remote-ip>
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>commands</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>always</td>
<td>
<div>Show the command sent.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[&#x27;ping vrf prod 10.40.40.40 count 20 source loopback0&#x27;]</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>packet_loss</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>always</td>
<td>
<div>Percentage of packets lost.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">0%</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>packets_rx</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>always</td>
<td>
<div>Packets successfully received.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">20</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>packets_tx</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>always</td>
<td>
<div>Packets successfully transmitted.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">20</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>rtt</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
</td>
<td>always</td>
<td>
<div>Show RTT stats.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">{&#x27;avg&#x27;: 2, &#x27;max&#x27;: 8, &#x27;min&#x27;: 1}</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Jacob McGill (@jmcgill298)

View File

@@ -0,0 +1,152 @@
.. _ansible.netcommon.net_put_module:
*************************
ansible.netcommon.net_put
*************************
**Copy a file from Ansible Controller to a network device**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This module provides functionality to copy file from Ansible controller to network devices.
Requirements
------------
The below requirements are needed on the host that executes this module.
- scp if using protocol=scp with paramiko
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>dest</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">["Filename from src and at default directory of user shell on network_os."]</div>
</td>
<td>
<div>Specifies the destination file. The path to destination file can either be the full path or relative path as supported by network_os.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>mode</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>binary</b>&nbsp;&larr;</div></li>
<li>text</li>
</ul>
</td>
<td>
<div>Set the file transfer mode. If mode is set to <em>text</em> then <em>src</em> file will go through Jinja2 template engine to replace any vars if present in the src file. If mode is set to <em>binary</em> then file will be copied as it is to destination device.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>protocol</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>scp</b>&nbsp;&larr;</div></li>
<li>sftp</li>
</ul>
</td>
<td>
<div>Protocol used to transfer file.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>src</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
<div>Specifies the source file. The path to the source file can either be the full path on the Ansible control host or a relative path from the playbook or role root directory.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- Some devices need specific configurations to be enabled before scp can work These configuration should be pre-configured before using this module e.g ios - ``ip scp server enable``.
- User privilege to do scp on network device should be pre-configured e.g. ios - need user privilege 15 by default for allowing scp.
- Default destination of source file.
- This module is supported on ``ansible_network_os`` network platforms. See the :ref:`Network Platform Options <platform_options>` for details.
Examples
--------
.. code-block:: yaml
- name: copy file from ansible controller to a network device
ansible.netcommon.net_put:
src: running_cfg_ios1.txt
- name: copy file at root dir of flash in slot 3 of sw1(ios)
ansible.netcommon.net_put:
src: running_cfg_sw1.txt
protocol: sftp
dest: flash3:/running_cfg_sw1.txt
Status
------
Authors
~~~~~~~
- Deepak Agrawal (@dagrawal)

View File

@@ -0,0 +1,636 @@
.. _ansible.netcommon.netconf_config_module:
********************************
ansible.netcommon.netconf_config
********************************
**netconf device configuration**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- Netconf is a network management protocol developed and standardized by the IETF. It is documented in RFC 6241.
- This module allows the user to send a configuration XML file to a netconf device, and detects if there was a configuration change.
Requirements
------------
The below requirements are needed on the host that executes this module.
- ncclient
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="2">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>backup</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>This argument will cause the module to create a full backup of the current <code>running-config</code> from the remote device before any changes are made. If the <code>backup_options</code> value is not given, the backup file is written to the <code>backup</code> folder in the playbook root directory or role root directory, if playbook is part of an ansible role. If the directory does not exist, it is created.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>backup_options</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
</td>
<td>
</td>
<td>
<div>This is a dict object containing configurable options related to backup file path. The value of this option is read only when <code>backup</code> is set to <em>yes</em>, if <code>backup</code> is set to <em>no</em> this option will be silently ignored.</div>
</td>
</tr>
<tr>
<td class="elbow-placeholder"></td>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>dir_path</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">path</span>
</div>
</td>
<td>
</td>
<td>
<div>This option provides the path ending with directory name in which the backup configuration file will be stored. If the directory does not exist it will be first created and the filename is either the value of <code>filename</code> or default filename as described in <code>filename</code> options description. If the path value is not given in that case a <em>backup</em> directory will be created in the current working directory and backup configuration will be copied in <code>filename</code> within <em>backup</em> directory.</div>
</td>
</tr>
<tr>
<td class="elbow-placeholder"></td>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>filename</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>The filename to be used to store the backup configuration. If the filename is not given it will be generated based on the hostname, current time and date in format defined by &lt;hostname&gt;_config.&lt;current-date&gt;@&lt;current-time&gt;</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>commit</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>no</li>
<li><div style="color: blue"><b>yes</b>&nbsp;&larr;</div></li>
</ul>
</td>
<td>
<div>This boolean flag controls if the configuration changes should be committed or not after editing the candidate datastore. This option is supported only if remote Netconf server supports :candidate capability. If the value is set to <em>False</em> commit won&#x27;t be issued after edit-config operation and user needs to handle commit or discard-changes explicitly.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>confirm</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">0</div>
</td>
<td>
<div>This argument will configure a timeout value for the commit to be confirmed before it is automatically rolled back. If the <code>confirm_commit</code> argument is set to False, this argument is silently ignored. If the value of this argument is set to 0, the commit is confirmed immediately. The remote host MUST support :candidate and :confirmed-commit capability for this option to .</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>confirm_commit</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>This argument will execute commit operation on remote device. It can be used to confirm a previous commit.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>content</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">raw</span>
</div>
</td>
<td>
</td>
<td>
<div>The configuration data as defined by the device&#x27;s data models, the value can be either in xml string format or text format or python dictionary representation of JSON format.</div>
<div>In case of json string format it will be converted to the corresponding xml string using xmltodict library before pushing onto the remote host.</div>
<div>In case the value of this option isn <em>text</em> format the format should be supported by remote Netconf server.</div>
<div>If the value of <code>content</code> option is in <em>xml</em> format in that case the xml value should have <em>config</em> as root tag.</div>
<div style="font-size: small; color: darkgreen"><br/>aliases: xml</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>default_operation</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>merge</li>
<li>replace</li>
<li>none</li>
</ul>
</td>
<td>
<div>The default operation for &lt;edit-config&gt; rpc, valid values are <em>merge</em>, <em>replace</em> and <em>none</em>. If the default value is merge, the configuration data in the <code>content</code> option is merged at the corresponding level in the <code>target</code> datastore. If the value is replace the data in the <code>content</code> option completely replaces the configuration in the <code>target</code> datastore. If the value is none the <code>target</code> datastore is unaffected by the configuration in the config option, unless and until the incoming configuration data uses the <code>operation</code> operation to request a different operation.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>delete</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>It instructs the module to delete the configuration from value mentioned in <code>target</code> datastore.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>error_option</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>stop-on-error</b>&nbsp;&larr;</div></li>
<li>continue-on-error</li>
<li>rollback-on-error</li>
</ul>
</td>
<td>
<div>This option controls the netconf server action after an error occurs while editing the configuration.</div>
<div>If <em>error_option=stop-on-error</em>, abort the config edit on first error.</div>
<div>If <em>error_option=continue-on-error</em>, continue to process configuration data on error. The error is recorded and negative response is generated if any errors occur.</div>
<div>If <em>error_option=rollback-on-error</em>, rollback to the original configuration if any error occurs. This requires the remote Netconf server to support the <em>error_option=rollback-on-error</em> capability.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>format</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>xml</li>
<li>text</li>
<li>json</li>
</ul>
</td>
<td>
<div>The format of the configuration provided as value of <code>content</code>.</div>
<div>In case of json string format it will be converted to the corresponding xml string using xmltodict library before pushing onto the remote host.</div>
<div>In case of <em>text</em> format of the configuration should be supported by remote Netconf server.</div>
<div>If the value of <code>format</code> options is not given it tries to guess the data format of <code>content</code> option as one of <em>xml</em> or <em>json</em> or <em>text</em>.</div>
<div>If the data format is not identified it is set to <em>xml</em> by default.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>get_filter</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">raw</span>
</div>
</td>
<td>
</td>
<td>
<div>This argument specifies the XML string which acts as a filter to restrict the portions of the data retrieved from the remote device when comparing the before and after state of the device following calls to edit_config. When not specified, the entire configuration or state data is returned for comparison depending on the value of <code>source</code> option. The <code>get_filter</code> value can be either XML string or XPath or JSON string or native python dictionary, if the filter is in XPath format the NETCONF server running on remote host should support xpath capability else it will result in an error.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>lock</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>never</li>
<li><div style="color: blue"><b>always</b>&nbsp;&larr;</div></li>
<li>if-supported</li>
</ul>
</td>
<td>
<div>Instructs the module to explicitly lock the datastore specified as <code>target</code>. By setting the option value <em>always</em> is will explicitly lock the datastore mentioned in <code>target</code> option. It the value is <em>never</em> it will not lock the <code>target</code> datastore. The value <em>if-supported</em> lock the <code>target</code> datastore only if it is supported by the remote Netconf server.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>save</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>The <code>save</code> argument instructs the module to save the configuration in <code>target</code> datastore to the startup-config if changed and if :startup capability is supported by Netconf server.</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>source_datastore</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>Name of the configuration datastore to use as the source to copy the configuration to the datastore mentioned by <code>target</code> option. The values can be either <em>running</em>, <em>candidate</em>, <em>startup</em> or a remote URL</div>
<div style="font-size: small; color: darkgreen"><br/>aliases: source</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>target</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>auto</b>&nbsp;&larr;</div></li>
<li>candidate</li>
<li>running</li>
</ul>
</td>
<td>
<div>Name of the configuration datastore to be edited. - auto, uses candidate and fallback to running - candidate, edit &lt;candidate/&gt; datastore and then commit - running, edit &lt;running/&gt; datastore directly</div>
<div style="font-size: small; color: darkgreen"><br/>aliases: datastore</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>validate</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>This boolean flag if set validates the content of datastore given in <code>target</code> option. For this option to work remote Netconf server should support :validate capability.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- This module requires the netconf system service be enabled on the remote device being managed.
- This module supports devices with and without the candidate and confirmed-commit capabilities. It will always use the safer feature.
- This module supports the use of connection=netconf
- This module is supported on ``ansible_network_os`` network platforms. See the :ref:`Network Platform Options <platform_options>` for details.
Examples
--------
.. code-block:: yaml
- name: use lookup filter to provide xml configuration
ansible.netcommon.netconf_config:
content: "{{ lookup('file', './config.xml') }}"
- name: set ntp server in the device
ansible.netcommon.netconf_config:
content: |
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<system xmlns="urn:ietf:params:xml:ns:yang:ietf-system">
<ntp>
<enabled>true</enabled>
<server>
<name>ntp1</name>
<udp><address>127.0.0.1</address></udp>
</server>
</ntp>
</system>
</config>
- name: wipe ntp configuration
ansible.netcommon.netconf_config:
content: |
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<system xmlns="urn:ietf:params:xml:ns:yang:ietf-system">
<ntp>
<enabled>false</enabled>
<server operation="remove">
<name>ntp1</name>
</server>
</ntp>
</system>
</config>
- name: configure interface while providing different private key file path (for connection=netconf)
ansible.netcommon.netconf_config:
backup: true
register: backup_junos_location
vars:
ansible_private_key_file: /home/admin/.ssh/newprivatekeyfile
- name: configurable backup path
ansible.netcommon.netconf_config:
backup: true
backup_options:
filename: backup.cfg
dir_path: /home/user
- name: "configure using direct native format configuration (cisco iosxr)"
ansible.netcommon.netconf_config:
format: json
content:
{
"config":
{
"interface-configurations":
{
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
"interface-configuration":
{
"active": "act",
"description": "test for ansible Loopback999",
"interface-name": "Loopback999",
},
},
},
}
get_filter:
{
"interface-configurations":
{
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
"interface-configuration": null,
},
}
- name: "configure using json string format configuration (cisco iosxr)"
ansible.netcommon.netconf_config:
format: json
content: |
{
"config": {
"interface-configurations": {
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
"interface-configuration": {
"active": "act",
"description": "test for ansible Loopback999",
"interface-name": "Loopback999"
}
}
}
}
get_filter: |
{
"interface-configurations": {
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
"interface-configuration": null
}
}
# Make a round-trip interface description change, diff the before and after
# this demonstrates the use of the native display format and several utilities
# from the ansible.utils collection
- name: Define the openconfig interface filter
set_fact:
filter:
interfaces:
"@xmlns": "http://openconfig.net/yang/interfaces"
interface:
name: Ethernet2
- name: Get the pre-change config using the filter
ansible.netcommon.netconf_get:
source: running
filter: "{{ filter }}"
display: native
register: pre
- name: Update the description
ansible.utils.update_fact:
updates:
- path: pre.output.data.interfaces.interface.config.description
value: "Configured by ansible {{ 100 | random }}"
register: updated
- name: Apply the new configuration
ansible.netcommon.netconf_config:
content:
config:
interfaces: "{{ updated.pre.output.data.interfaces }}"
- name: Get the post-change config using the filter
ansible.netcommon.netconf_get:
source: running
filter: "{{ filter }}"
display: native
register: post
- name: Show the differences between the pre and post configurations
ansible.utils.fact_diff:
before: "{{ pre.output.data|ansible.utils.to_paths }}"
after: "{{ post.output.data|ansible.utils.to_paths }}"
# TASK [Show the differences between the pre and post configurations] ********
# --- before
# +++ after
# @@ -1,11 +1,11 @@
# {
# - "@time-modified": "2020-10-23T12:27:17.462332477Z",
# + "@time-modified": "2020-10-23T12:27:21.744541708Z",
# "@xmlns": "urn:ietf:params:xml:ns:netconf:base:1.0",
# "interfaces.interface.aggregation.config['fallback-timeout']['#text']": "90",
# "interfaces.interface.aggregation.config['fallback-timeout']['@xmlns']": "http://arista.com/yang/openconfig/interfaces/augments",
# "interfaces.interface.aggregation.config['min-links']": "0",
# "interfaces.interface.aggregation['@xmlns']": "http://openconfig.net/yang/interfaces/aggregate",
# - "interfaces.interface.config.description": "Configured by ansible 56",
# + "interfaces.interface.config.description": "Configured by ansible 67",
# "interfaces.interface.config.enabled": "true",
# "interfaces.interface.config.mtu": "0",
# "interfaces.interface.config.name": "Ethernet2",
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>backup_path</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>when backup is yes</td>
<td>
<div>The full path to the backup file</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">/playbooks/ansible/backup/config.2016-07-16@22:28:34</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>diff</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
</td>
<td>when diff is enabled</td>
<td>
<div>If --diff option in enabled while running, the before and after configuration change are returned as part of before and after key.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">{&#x27;after&#x27;: &#x27;&lt;rpc-reply&gt; &lt;data&gt; &lt;configuration&gt; &lt;version&gt;17.3R1.10&lt;/version&gt;...&lt;--snip--&gt;&#x27;, &#x27;before&#x27;: &#x27;&lt;rpc-reply&gt; &lt;data&gt; &lt;configuration&gt; &lt;version&gt;17.3R1.10&lt;/version&gt;...&lt;--snip--&gt;&#x27;}</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>server_capabilities</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>success</td>
<td>
<div>list of capabilities of the server</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[&#x27;urn:ietf:params:netconf:base:1.1&#x27;, &#x27;urn:ietf:params:netconf:capability:confirmed-commit:1.0&#x27;, &#x27;urn:ietf:params:netconf:capability:candidate:1.0&#x27;]</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Leandro Lisboa Penz (@lpenz)
- Ganesh Nalawade (@ganeshrn)

View File

@@ -0,0 +1,382 @@
.. _ansible.netcommon.netconf_connection:
*************************
ansible.netcommon.netconf
*************************
**Provides a persistent connection using the netconf protocol**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This connection plugin provides a connection to remote devices over the SSH NETCONF subsystem. This connection plugin is typically used by network devices for sending and receiving RPC calls over NETCONF.
- Note this connection plugin requires ncclient to be installed on the local Ansible controller.
Requirements
------------
The below requirements are needed on the local Ansible controller node that executes this connection.
- ncclient
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>host</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"inventory_hostname"</div>
</td>
<td>
<div>var: inventory_hostname</div>
<div>var: ansible_host</div>
</td>
<td>
<div>Specifies the remote device FQDN or IP address to establish the SSH connection to.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>host_key_checking</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>host_key_checking = yes</p>
<p>[paramiko_connection]<br>host_key_checking = yes</p>
</div>
<div>env:ANSIBLE_HOST_KEY_CHECKING</div>
<div>env:ANSIBLE_SSH_HOST_KEY_CHECKING</div>
<div>env:ANSIBLE_NETCONF_HOST_KEY_CHECKING</div>
<div>var: ansible_host_key_checking</div>
<div>var: ansible_ssh_host_key_checking</div>
<div>var: ansible_netconf_host_key_checking</div>
</td>
<td>
<div>Set this to &quot;False&quot; if you want to avoid host key checking by the underlying tools Ansible uses to connect to the host</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>import_modules</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div> ini entries:
<p>[ansible_network]<br>import_modules = yes</p>
</div>
<div>env:ANSIBLE_NETWORK_IMPORT_MODULES</div>
<div>var: ansible_network_import_modules</div>
</td>
<td>
<div>Reduce CPU usage and network module execution time by enabling direct execution. Instead of the module being packaged and executed by the shell, it will be directly executed by the Ansible control node using the same python interpreter as the Ansible process. Note- Incompatible with <code>asynchronous mode</code>. Note- Python 3 and Ansible 2.9.16 or greater required. Note- With Ansible 2.9.x fully qualified modules names are required in tasks.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>look_for_keys</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div> ini entries:
<p>[paramiko_connection]<br>look_for_keys = yes</p>
</div>
<div>env:ANSIBLE_PARAMIKO_LOOK_FOR_KEYS</div>
</td>
<td>
<div>Enables looking for ssh keys in the usual locations for ssh keys (e.g. :file:`~/.ssh/id_*`).</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>netconf_ssh_config</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[netconf_connection]<br>ssh_config = VALUE</p>
</div>
<div>env:ANSIBLE_NETCONF_SSH_CONFIG</div>
<div>var: ansible_netconf_ssh_config</div>
</td>
<td>
<div>This variable is used to enable bastion/jump host with netconf connection. If set to True the bastion/jump host ssh settings should be present in ~/.ssh/config file, alternatively it can be set to custom ssh configuration file path to read the bastion/jump host settings.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>network_os</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_network_os</div>
</td>
<td>
<div>Configures the device platform network operating system. This value is used to load a device specific netconf plugin. If this option is not configured (or set to <code>auto</code>), then Ansible will attempt to guess the correct network_os to use. If it can not guess a network_os correctly it will use <code>default</code>.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>password</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_password</div>
<div>var: ansible_ssh_pass</div>
<div>var: ansible_ssh_password</div>
<div>var: ansible_netconf_password</div>
</td>
<td>
<div>Configures the user password used to authenticate to the remote device when first establishing the SSH connection.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_command_timeout</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">30</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>command_timeout = 30</p>
</div>
<div>env:ANSIBLE_PERSISTENT_COMMAND_TIMEOUT</div>
<div>var: ansible_command_timeout</div>
</td>
<td>
<div>Configures, in seconds, the amount of time to wait for a command to return from the remote device. If this timer is exceeded before the command returns, the connection plugin will raise an exception and close.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_connect_timeout</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">30</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>connect_timeout = 30</p>
</div>
<div>env:ANSIBLE_PERSISTENT_CONNECT_TIMEOUT</div>
<div>var: ansible_connect_timeout</div>
</td>
<td>
<div>Configures, in seconds, the amount of time to wait when trying to initially establish a persistent connection. If this value expires before the connection to the remote device is completed, the connection will fail.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_log_messages</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>log_messages = no</p>
</div>
<div>env:ANSIBLE_PERSISTENT_LOG_MESSAGES</div>
<div>var: ansible_persistent_log_messages</div>
</td>
<td>
<div>This flag will enable logging the command executed and response received from target device in the ansible log file. For this option to work &#x27;log_path&#x27; ansible configuration option is required to be set to a file path with write access.</div>
<div>Be sure to fully understand the security implications of enabling this option as it could create a security vulnerability by logging sensitive information in log file.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>port</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">830</div>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>remote_port = 830</p>
</div>
<div>env:ANSIBLE_REMOTE_PORT</div>
<div>var: ansible_port</div>
</td>
<td>
<div>Specifies the port on the remote device that listens for connections when establishing the SSH connection.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>private_key_file</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>private_key_file = VALUE</p>
</div>
<div>env:ANSIBLE_PRIVATE_KEY_FILE</div>
<div>var: ansible_private_key_file</div>
</td>
<td>
<div>The private SSH key or certificate file used to authenticate to the remote device when first establishing the SSH connection.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>proxy_command</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">""</div>
</td>
<td>
<div> ini entries:
<p>[paramiko_connection]<br>proxy_command = </p>
</div>
<div>env:ANSIBLE_NETCONF_PROXY_COMMAND</div>
<div>var: ansible_paramiko_proxy_command</div>
<div>var: ansible_netconf_proxy_command</div>
</td>
<td>
<div>Proxy information for running the connection via a jumphost.</div>
<div>This requires ncclient &gt;= 0.6.10 to be installed on the controller.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>remote_user</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>remote_user = VALUE</p>
</div>
<div>env:ANSIBLE_REMOTE_USER</div>
<div>var: ansible_user</div>
</td>
<td>
<div>The username used to authenticate to the remote device when the SSH connection is first established. If the remote_user is not specified, the connection will use the username of the logged in user.</div>
<div>Can be configured from the CLI via the <code>--user</code> or <code>-u</code> options.</div>
</td>
</tr>
</table>
<br/>
Status
------
Authors
~~~~~~~
- Ansible Networking Team (@ansible-network)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,378 @@
.. _ansible.netcommon.netconf_get_module:
*****************************
ansible.netcommon.netconf_get
*****************************
**Fetch configuration/state data from NETCONF enabled network devices.**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- NETCONF is a network management protocol developed and standardized by the IETF. It is documented in RFC 6241.
- This module allows the user to fetch configuration and state data from NETCONF enabled network devices.
Requirements
------------
The below requirements are needed on the host that executes this module.
- ncclient (>=v0.5.2)
- jxmlease (for display=json)
- xmltodict (for display=native)
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>display</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>json</li>
<li>pretty</li>
<li>xml</li>
<li>native</li>
</ul>
</td>
<td>
<div>Encoding scheme to use when serializing output from the device. The option <em>json</em> will serialize the output as JSON data. If the option value is <em>json</em> it requires jxmlease to be installed on control node. The option <em>pretty</em> is similar to received XML response but is using human readable format (spaces, new lines). The option value <em>xml</em> is similar to received XML response but removes all XML namespaces.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>filter</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">raw</span>
</div>
</td>
<td>
</td>
<td>
<div>This argument specifies the string which acts as a filter to restrict the portions of the data to be are retrieved from the remote device. If this option is not specified entire configuration or state data is returned in result depending on the value of <code>source</code> option. The <code>filter</code> value can be either XML string or XPath or JSON string or native python dictionary, if the filter is in XPath format the NETCONF server running on remote host should support xpath capability else it will result in an error. If the filter is in JSON format the xmltodict library should be installed on the control node for JSON to XML conversion.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>lock</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>never</b>&nbsp;&larr;</div></li>
<li>always</li>
<li>if-supported</li>
</ul>
</td>
<td>
<div>Instructs the module to explicitly lock the datastore specified as <code>source</code>. If no <em>source</em> is defined, the <em>running</em> datastore will be locked. By setting the option value <em>always</em> is will explicitly lock the datastore mentioned in <code>source</code> option. By setting the option value <em>never</em> it will not lock the <code>source</code> datastore. The value <em>if-supported</em> allows better interworking with NETCONF servers, which do not support the (un)lock operation for all supported datastores.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>source</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>running</li>
<li>candidate</li>
<li>startup</li>
</ul>
</td>
<td>
<div>This argument specifies the datastore from which configuration data should be fetched. Valid values are <em>running</em>, <em>candidate</em> and <em>startup</em>. If the <code>source</code> value is not set both configuration and state information are returned in response from running datastore.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- This module requires the NETCONF system service be enabled on the remote device being managed.
- This module supports the use of connection=netconf
- This module is supported on ``ansible_network_os`` network platforms. See the :ref:`Network Platform Options <platform_options>` for details.
Examples
--------
.. code-block:: yaml
- name: Get running configuration and state data
ansible.netcommon.netconf_get:
- name: Get configuration and state data from startup datastore
ansible.netcommon.netconf_get:
source: startup
- name: Get system configuration data from running datastore state (junos)
ansible.netcommon.netconf_get:
source: running
filter: <configuration><system></system></configuration>
- name: Get configuration and state data in JSON format
ansible.netcommon.netconf_get:
display: json
- name: get schema list using subtree w/ namespaces
ansible.netcommon.netconf_get:
display: json
filter: <netconf-state xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"><schemas><schema/></schemas></netconf-state>
lock: never
- name: get schema list using xpath
ansible.netcommon.netconf_get:
display: xml
filter: /netconf-state/schemas/schema
- name: get interface configuration with filter (iosxr)
ansible.netcommon.netconf_get:
display: pretty
filter: <interface-configurations xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"></interface-configurations>
lock: if-supported
- name: Get system configuration data from running datastore state (junos)
ansible.netcommon.netconf_get:
source: running
filter: <configuration><system></system></configuration>
lock: if-supported
- name: Get complete configuration data from running datastore (SROS)
ansible.netcommon.netconf_get:
source: running
filter: <configure xmlns="urn:nokia.com:sros:ns:yang:sr:conf"/>
- name: Get complete state data (SROS)
ansible.netcommon.netconf_get:
filter: <state xmlns="urn:nokia.com:sros:ns:yang:sr:state"/>
- name: "get configuration with json filter string and native output (using xmltodict)"
netconf_get:
filter: |
{
"interface-configurations": {
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
"interface-configuration": null
}
}
display: native
- name: Define the Cisco IOSXR interface filter
set_fact:
filter:
interface-configurations:
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
interface-configuration: null
- name: "get configuration with native filter type using set_facts"
ansible.netcommon.netconf_get:
filter: "{{ filter }}"
display: native
register: result
- name: "get configuration with direct native filter type"
ansible.netcommon.netconf_get:
filter:
{
"interface-configurations":
{
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg",
"interface-configuration": null,
},
}
display: native
register: result
# Make a round-trip interface description change, diff the before and after
# this demonstrates the use of the native display format and several utilities
# from the ansible.utils collection
- name: Define the openconfig interface filter
set_fact:
filter:
interfaces:
"@xmlns": "http://openconfig.net/yang/interfaces"
interface:
name: Ethernet2
- name: Get the pre-change config using the filter
ansible.netcommon.netconf_get:
source: running
filter: "{{ filter }}"
display: native
register: pre
- name: Update the description
ansible.utils.update_fact:
updates:
- path: pre.output.data.interfaces.interface.config.description
value: "Configured by ansible {{ 100 | random }}"
register: updated
- name: Apply the new configuration
ansible.netcommon.netconf_config:
content:
config:
interfaces: "{{ updated.pre.output.data.interfaces }}"
- name: Get the post-change config using the filter
ansible.netcommon.netconf_get:
source: running
filter: "{{ filter }}"
display: native
register: post
- name: Show the differences between the pre and post configurations
ansible.utils.fact_diff:
before: "{{ pre.output.data|ansible.utils.to_paths }}"
after: "{{ post.output.data|ansible.utils.to_paths }}"
# TASK [Show the differences between the pre and post configurations] ********
# --- before
# +++ after
# @@ -1,11 +1,11 @@
# {
# - "@time-modified": "2020-10-23T12:27:17.462332477Z",
# + "@time-modified": "2020-10-23T12:27:21.744541708Z",
# "@xmlns": "urn:ietf:params:xml:ns:netconf:base:1.0",
# "interfaces.interface.aggregation.config['fallback-timeout']['#text']": "90",
# "interfaces.interface.aggregation.config['fallback-timeout']['@xmlns']": "http://arista.com/yang/openconfig/interfaces/augments",
# "interfaces.interface.aggregation.config['min-links']": "0",
# "interfaces.interface.aggregation['@xmlns']": "http://openconfig.net/yang/interfaces/aggregate",
# - "interfaces.interface.config.description": "Configured by ansible 56",
# + "interfaces.interface.config.description": "Configured by ansible 67",
# "interfaces.interface.config.enabled": "true",
# "interfaces.interface.config.mtu": "0",
# "interfaces.interface.config.name": "Ethernet2",
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="2">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>output</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">complex</span>
</div>
</td>
<td>If the display format is selected as <em>json</em> it is returned as dict type and the conversion is done using jxmlease python library. If the display format is selected as <em>native</em> it is returned as dict type and the conversion is done using xmltodict python library. If the display format is xml or pretty it is returned as a string apart from low-level errors (such as action plugin).</td>
<td>
<div>Based on the value of display option will return either the set of transformed XML to JSON format from the RPC response with type dict or pretty XML string response (human-readable) or response with namespace removed from XML string.</div>
<br/>
</td>
</tr>
<tr>
<td class="elbow-placeholder">&nbsp;</td>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>formatted_output</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td></td>
<td>
<div>Contains formatted response received from remote host as per the value in display format.</div>
<br/>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>stdout</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>always apart from low-level errors (such as action plugin)</td>
<td>
<div>The raw XML string containing configuration or state data received from the underlying ncclient library.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">...</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>stdout_lines</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>always apart from low-level errors (such as action plugin)</td>
<td>
<div>The value of stdout split into a list</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[&#x27;...&#x27;, &#x27;...&#x27;]</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Ganesh Nalawade (@ganeshrn)
- Sven Wisotzky (@wisotzky)

View File

@@ -0,0 +1,276 @@
.. _ansible.netcommon.netconf_rpc_module:
*****************************
ansible.netcommon.netconf_rpc
*****************************
**Execute operations on NETCONF enabled network devices.**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- NETCONF is a network management protocol developed and standardized by the IETF. It is documented in RFC 6241.
- This module allows the user to execute NETCONF RPC requests as defined by IETF RFC standards as well as proprietary requests.
Requirements
------------
The below requirements are needed on the host that executes this module.
- ncclient (>=v0.5.2)
- jxmlease
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>content</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>This argument specifies the optional request content (all RPC attributes). The <em>content</em> value can either be provided as XML formatted string or as dictionary.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>display</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>json</li>
<li>pretty</li>
<li>xml</li>
</ul>
</td>
<td>
<div>Encoding scheme to use when serializing output from the device. The option <em>json</em> will serialize the output as JSON data. If the option value is <em>json</em> it requires jxmlease to be installed on control node. The option <em>pretty</em> is similar to received XML response but is using human readable format (spaces, new lines). The option value <em>xml</em> is similar to received XML response but removes all XML namespaces.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>rpc</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
<div>This argument specifies the request (name of the operation) to be executed on the remote NETCONF enabled device.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>xmlns</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>NETCONF operations not defined in rfc6241 typically require the appropriate XML namespace to be set. In the case the <em>request</em> option is not already provided in XML format, the namespace can be defined by the <em>xmlns</em> option.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- This module requires the NETCONF system service be enabled on the remote device being managed.
- This module supports the use of connection=netconf
- To execute ``get-config``, ``get`` or ``edit-config`` requests it is recommended to use the Ansible *netconf_get* and *netconf_config* modules.
- This module is supported on ``ansible_network_os`` network platforms. See the :ref:`Network Platform Options <platform_options>` for details.
Examples
--------
.. code-block:: yaml
- name: lock candidate
ansible.netcommon.netconf_rpc:
rpc: lock
content:
target:
candidate:
- name: unlock candidate
ansible.netcommon.netconf_rpc:
rpc: unlock
xmlns: urn:ietf:params:xml:ns:netconf:base:1.0
content: "{'target': {'candidate': None}}"
- name: discard changes
ansible.netcommon.netconf_rpc:
rpc: discard-changes
- name: get-schema
ansible.netcommon.netconf_rpc:
rpc: get-schema
xmlns: urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring
content:
identifier: ietf-netconf
version: '2011-06-01'
- name: copy running to startup
ansible.netcommon.netconf_rpc:
rpc: copy-config
content:
source:
running:
target:
startup:
- name: get schema list with JSON output
ansible.netcommon.netconf_rpc:
rpc: get
content: |
<filter>
<netconf-state xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring">
<schemas/>
</netconf-state>
</filter>
display: json
- name: get schema using XML request
ansible.netcommon.netconf_rpc:
rpc: get-schema
xmlns: urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring
content: |
<identifier>ietf-netconf-monitoring</identifier>
<version>2010-10-04</version>
display: json
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="2">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>output</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">complex</span>
</div>
</td>
<td>when the display format is selected as JSON it is returned as dict type, if the display format is xml or pretty pretty it is returned as a string apart from low-level errors (such as action plugin).</td>
<td>
<div>Based on the value of display option will return either the set of transformed XML to JSON format from the RPC response with type dict or pretty XML string response (human-readable) or response with namespace removed from XML string.</div>
<br/>
</td>
</tr>
<tr>
<td class="elbow-placeholder">&nbsp;</td>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>formatted_output</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td></td>
<td>
<div>Contains formatted response received from remote host as per the value in display format.</div>
<br/>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>stdout</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>always apart from low-level errors (such as action plugin)</td>
<td>
<div>The raw XML string containing configuration or state data received from the underlying ncclient library.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">...</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>stdout_lines</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>always apart from low-level errors (such as action plugin)</td>
<td>
<div>The value of stdout split into a list</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[&#x27;...&#x27;, &#x27;...&#x27;]</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Ganesh Nalawade (@ganeshrn)
- Sven Wisotzky (@wisotzky)

View File

@@ -0,0 +1,640 @@
.. _ansible.netcommon.network_cli_connection:
*****************************
ansible.netcommon.network_cli
*****************************
**Use network_cli to run command on network appliances**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This connection plugin provides a connection to remote devices over the SSH and implements a CLI shell. This connection plugin is typically used by network devices for sending and receiving CLi commands to network devices.
Requirements
------------
The below requirements are needed on the local Ansible controller node that executes this connection.
- ansible-pylibssh if using *ssh_type=libssh*
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>become</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div> ini entries:
<p>[privilege_escalation]<br>become = no</p>
</div>
<div>env:ANSIBLE_BECOME</div>
<div>var: ansible_become</div>
</td>
<td>
<div>The become option will instruct the CLI session to attempt privilege escalation on platforms that support it. Normally this means transitioning from user mode to <code>enable</code> mode in the CLI session. If become is set to True and the remote device does not support privilege escalation or the privilege has already been elevated, then this option is silently ignored.</div>
<div>Can be configured from the CLI via the <code>--become</code> or <code>-b</code> options.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>become_errors</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>ignore</li>
<li>warn</li>
<li><div style="color: blue"><b>fail</b>&nbsp;&larr;</div></li>
</ul>
</td>
<td>
<div>var: ansible_network_become_errors</div>
</td>
<td>
<div>This option determines how privilege escalation failures are handled when <em>become</em> is enabled.</div>
<div>When set to <code>ignore</code>, the errors are silently ignored. When set to <code>warn</code>, a warning message is displayed. The default option <code>fail</code>, triggers a failure and halts execution.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>become_method</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"sudo"</div>
</td>
<td>
<div> ini entries:
<p>[privilege_escalation]<br>become_method = sudo</p>
</div>
<div>env:ANSIBLE_BECOME_METHOD</div>
<div>var: ansible_become_method</div>
</td>
<td>
<div>This option allows the become method to be specified in for handling privilege escalation. Typically the become_method value is set to <code>enable</code> but could be defined as other values.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>host</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"inventory_hostname"</div>
</td>
<td>
<div>var: inventory_hostname</div>
<div>var: ansible_host</div>
</td>
<td>
<div>Specifies the remote device FQDN or IP address to establish the SSH connection to.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>host_key_auto_add</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div> ini entries:
<p>[paramiko_connection]<br>host_key_auto_add = no</p>
</div>
<div>env:ANSIBLE_HOST_KEY_AUTO_ADD</div>
</td>
<td>
<div>By default, Ansible will prompt the user before adding SSH keys to the known hosts file. Since persistent connections such as network_cli run in background processes, the user will never be prompted. By enabling this option, unknown host keys will automatically be added to the known hosts file.</div>
<div>Be sure to fully understand the security implications of enabling this option on production systems as it could create a security vulnerability.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>host_key_checking</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>host_key_checking = yes</p>
<p>[persistent_connection]<br>host_key_checking = yes</p>
</div>
<div>env:ANSIBLE_HOST_KEY_CHECKING</div>
<div>env:ANSIBLE_SSH_HOST_KEY_CHECKING</div>
<div>var: ansible_host_key_checking</div>
<div>var: ansible_ssh_host_key_checking</div>
</td>
<td>
<div>Set this to &quot;False&quot; if you want to avoid host key checking by the underlying tools Ansible uses to connect to the host</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>import_modules</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div> ini entries:
<p>[ansible_network]<br>import_modules = yes</p>
</div>
<div>env:ANSIBLE_NETWORK_IMPORT_MODULES</div>
<div>var: ansible_network_import_modules</div>
</td>
<td>
<div>Reduce CPU usage and network module execution time by enabling direct execution. Instead of the module being packaged and executed by the shell, it will be directly executed by the Ansible control node using the same python interpreter as the Ansible process. Note- Incompatible with <code>asynchronous mode</code>. Note- Python 3 and Ansible 2.9.16 or greater required. Note- With Ansible 2.9.x fully qualified modules names are required in tasks.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>network_cli_retries</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">3</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>network_cli_retries = 3</p>
</div>
<div>env:ANSIBLE_NETWORK_CLI_RETRIES</div>
<div>var: ansible_network_cli_retries</div>
</td>
<td>
<div>Number of attempts to connect to remote host. The delay time between the retires increases after every attempt by power of 2 in seconds till either the maximum attempts are exhausted or any of the <code>persistent_command_timeout</code> or <code>persistent_connect_timeout</code> timers are triggered.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>network_os</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_network_os</div>
</td>
<td>
<div>Configures the device platform network operating system. This value is used to load the correct terminal and cliconf plugins to communicate with the remote device.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>password</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_password</div>
<div>var: ansible_ssh_pass</div>
<div>var: ansible_ssh_password</div>
</td>
<td>
<div>Configures the user password used to authenticate to the remote device when first establishing the SSH connection.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_buffer_read_timeout</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">float</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">0.1</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>buffer_read_timeout = 0.1</p>
</div>
<div>env:ANSIBLE_PERSISTENT_BUFFER_READ_TIMEOUT</div>
<div>var: ansible_buffer_read_timeout</div>
</td>
<td>
<div>Configures, in seconds, the amount of time to wait for the data to be read from Paramiko channel after the command prompt is matched. This timeout value ensures that command prompt matched is correct and there is no more data left to be received from remote host.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_command_timeout</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">30</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>command_timeout = 30</p>
</div>
<div>env:ANSIBLE_PERSISTENT_COMMAND_TIMEOUT</div>
<div>var: ansible_command_timeout</div>
</td>
<td>
<div>Configures, in seconds, the amount of time to wait for a command to return from the remote device. If this timer is exceeded before the command returns, the connection plugin will raise an exception and close.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_connect_timeout</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">30</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>connect_timeout = 30</p>
</div>
<div>env:ANSIBLE_PERSISTENT_CONNECT_TIMEOUT</div>
<div>var: ansible_connect_timeout</div>
</td>
<td>
<div>Configures, in seconds, the amount of time to wait when trying to initially establish a persistent connection. If this value expires before the connection to the remote device is completed, the connection will fail.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_log_messages</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>log_messages = no</p>
</div>
<div>env:ANSIBLE_PERSISTENT_LOG_MESSAGES</div>
<div>var: ansible_persistent_log_messages</div>
</td>
<td>
<div>This flag will enable logging the command executed and response received from target device in the ansible log file. For this option to work &#x27;log_path&#x27; ansible configuration option is required to be set to a file path with write access.</div>
<div>Be sure to fully understand the security implications of enabling this option as it could create a security vulnerability by logging sensitive information in log file.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>port</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">22</div>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>remote_port = 22</p>
</div>
<div>env:ANSIBLE_REMOTE_PORT</div>
<div>var: ansible_port</div>
</td>
<td>
<div>Specifies the port on the remote device that listens for connections when establishing the SSH connection.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>private_key_file</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>private_key_file = VALUE</p>
</div>
<div>env:ANSIBLE_PRIVATE_KEY_FILE</div>
<div>var: ansible_private_key_file</div>
</td>
<td>
<div>The private SSH key or certificate file used to authenticate to the remote device when first establishing the SSH connection.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>remote_user</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div> ini entries:
<p>[defaults]<br>remote_user = VALUE</p>
</div>
<div>env:ANSIBLE_REMOTE_USER</div>
<div>var: ansible_user</div>
</td>
<td>
<div>The username used to authenticate to the remote device when the SSH connection is first established. If the remote_user is not specified, the connection will use the username of the logged in user.</div>
<div>Can be configured from the CLI via the <code>--user</code> or <code>-u</code> options.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>single_user_mode</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.0.0</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div>env:ANSIBLE_NETWORK_SINGLE_USER_MODE</div>
<div>var: ansible_network_single_user_mode</div>
</td>
<td>
<div>This option enables caching of data fetched from the target for re-use. The cache is invalidated when the target device enters configuration mode.</div>
<div>Applicable only for platforms where this has been implemented.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>ssh_type</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>libssh</li>
<li>paramiko</li>
<li><div style="color: blue"><b>auto</b>&nbsp;&larr;</div></li>
</ul>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>ssh_type = auto</p>
</div>
<div>env:ANSIBLE_NETWORK_CLI_SSH_TYPE</div>
<div>var: ansible_network_cli_ssh_type</div>
</td>
<td>
<div>The python package that will be used by the <code>network_cli</code> connection plugin to create a SSH connection to remote host.</div>
<div><em>libssh</em> will use the ansible-pylibssh package, which needs to be installed in order to work.</div>
<div><em>paramiko</em> will instead use the paramiko package to manage the SSH connection.</div>
<div><em>auto</em> will use ansible-pylibssh if that package is installed, otherwise will fallback to paramiko.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>terminal_errors</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.1.0</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>ignore</li>
<li>warn</li>
<li><div style="color: blue"><b>fail</b>&nbsp;&larr;</div></li>
</ul>
</td>
<td>
<div>var: ansible_network_terminal_errors</div>
</td>
<td>
<div>This option determines how failures while setting terminal parameters are handled.</div>
<div>When set to <code>ignore</code>, the errors are silently ignored. When set to <code>warn</code>, a warning message is displayed. The default option <code>fail</code>, triggers a failure and halts execution.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>terminal_inital_prompt_newline</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div>var: ansible_terminal_initial_prompt_newline</div>
</td>
<td>
<div>This boolean flag, that when set to <em>True</em> will send newline in the response if any of values in <em>terminal_initial_prompt</em> is matched.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>terminal_initial_answer</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
/ <span style="color: purple">elements=string</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_terminal_initial_answer</div>
</td>
<td>
<div>The answer to reply with if the <code>terminal_initial_prompt</code> is matched. The value can be a single answer or a list of answers for multiple terminal_initial_prompt. In case the login menu has multiple prompts the sequence of the prompt and excepted answer should be in same order and the value of <em>terminal_prompt_checkall</em> should be set to <em>True</em> if all the values in <code>terminal_initial_prompt</code> are expected to be matched and set to <em>False</em> if any one login prompt is to be matched.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>terminal_initial_prompt</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
/ <span style="color: purple">elements=string</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_terminal_initial_prompt</div>
</td>
<td>
<div>A single regex pattern or a sequence of patterns to evaluate the expected prompt at the time of initial login to the remote host.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>terminal_initial_prompt_checkall</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div>var: ansible_terminal_initial_prompt_checkall</div>
</td>
<td>
<div>By default the value is set to <em>False</em> and any one of the prompts mentioned in <code>terminal_initial_prompt</code> option is matched it won&#x27;t check for other prompts. When set to <em>True</em> it will check for all the prompts mentioned in <code>terminal_initial_prompt</code> option in the given order and all the prompts should be received from remote host if not it will result in timeout.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>terminal_stderr_re</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
/ <span style="color: purple">elements=dictionary</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_terminal_stderr_re</div>
</td>
<td>
<div>This option provides the regex pattern and optional flags to match the error string from the received response chunk. This option accepts <code>pattern</code> and <code>flags</code> keys. The value of <code>pattern</code> is a python regex pattern to match the response and the value of <code>flags</code> is the value accepted by <em>flags</em> argument of <em>re.compile</em> python method to control the way regex is matched with the response, for example <em>&#x27;re.I&#x27;</em>.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>terminal_stdout_re</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
/ <span style="color: purple">elements=dictionary</span>
</div>
</td>
<td>
</td>
<td>
<div>var: ansible_terminal_stdout_re</div>
</td>
<td>
<div>A single regex pattern or a sequence of patterns along with optional flags to match the command prompt from the received response chunk. This option accepts <code>pattern</code> and <code>flags</code> keys. The value of <code>pattern</code> is a python regex pattern to match the response and the value of <code>flags</code> is the value accepted by <em>flags</em> argument of <em>re.compile</em> python method to control the way regex is matched with the response, for example <em>&#x27;re.I&#x27;</em>.</div>
</td>
</tr>
</table>
<br/>
Status
------
Authors
~~~~~~~
- Ansible Networking Team (@ansible-network)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,267 @@
.. _ansible.netcommon.network_resource_module:
**********************************
ansible.netcommon.network_resource
**********************************
**Manage resource modules**
Version added: 2.4.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- Get list of available resource modules for given os name
- Retrieve given resource module configuration facts
- Push given resource module configuration
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>config</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">raw</span>
</div>
</td>
<td>
</td>
<td>
<div>The resource module configuration. For details on the type and structure of this option refer the individual resource module platform documentation.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>name</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>The name of the resource module to manage.</div>
<div>The resource module should be supported for given <em>os_name</em>, if not supported it will result in error.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>os_name</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>The name of the os to manage the resource modules.</div>
<div>The name should be fully qualified collection name format, that is <em>&lt;namespace&gt;.&lt;collection-name&gt;.&lt;plugin-name&gt;</em>.</div>
<div>If value of this option is not set the os value will be read from <em>ansible_network_os</em> variable.</div>
<div>If value of both <em>os_name</em> and <em>ansible_network_os</em> is not set it will result in error.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>running_config</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
</td>
<td>
<div>This option is used only with state <em>parsed</em>.</div>
<div>The value of this option should be the output received from the host device by executing the cli command to get the resource configuration on host.</div>
<div>The state <em>parsed</em> reads the configuration from <code>running_config</code> option and transforms it into Ansible structured data as per the resource module&#x27;s argspec and the value is then returned in the <em>parsed</em> key within the result.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>state</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
</td>
<td>
<div>The state the configuration should be left in.</div>
<div>For supported values refer the individual resource module platform documentation.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- Refer the individual module documentation for the valid inputs of *state* and *config* modules.
Examples
--------
.. code-block:: yaml
- name: get list of resource modules for given network_os
ansible.netcommon.network_resource:
register: result
- name: fetch acl config for
ansible.netcommon.network_resource:
os_name: cisco.ios.ios
name: acls
state: gathered
- name: manage acl config for cisco.ios.ios network os.
ansible.netcommon.network_resource:
name: acls
config:
- afi: ipv4
acls:
- name: test_acl
acl_type: extended
aces:
- grant: deny
protocol_options:
tcp:
fin: true
source:
address: 192.0.2.0
wildcard_bits: 0.0.0.255
destination:
address: 192.0.3.0
wildcard_bits: 0.0.0.255
port_protocol:
eq: www
option:
traceroute: true
ttl:
eq: 10
state: merged
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>after</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>when changed and when <em>state</em> and/or <em>config</em> option is set</td>
<td>
<div>The configuration as structured data after module completion.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">The configuration returned will always be in the same format of the parameters above.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>before</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>When <em>state</em> and/or <em>config</em> option is set</td>
<td>
<div>The configuration as structured data prior to module invocation.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">The configuration returned will always be in the same format of the parameters above.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>commands</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>When <em>state</em> and/or <em>config</em> option is set</td>
<td>
<div>The set of commands pushed to the remote device</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[&#x27;ip access-list extended 110&#x27;]</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>modules</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>When only <em>os_name</em> or <em>ansible_network_os</em> is set</td>
<td>
<div>List of resource modules supported for given OS.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[&#x27;acl_interfaces&#x27;, &#x27;acls&#x27;, &#x27;bgp_global&#x27;]</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Ganesh B. Nalawade (@ganeshrn)

View File

@@ -0,0 +1,191 @@
.. _ansible.netcommon.parse_cli_filter:
***************************
ansible.netcommon.parse_cli
***************************
**parse_cli filter plugin.**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- The filter plugins converts the output of a network device CLI command into structured JSON output.
- Using the parameters below - ``xml_data | ansible.netcommon.parse_cli(template.yml``)
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>output</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">raw</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>This source data on which parse_cli invokes.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>tmpl</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>The spec file should be valid formatted YAML. It defines how to parse the CLI output and return JSON data.</div>
<div>For example <code>cli_data | ansible.netcommon.parse_cli(template.yml</code>), in this case <code>cli_data</code> represents cli output.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- The parse_cli filter will load the spec file and pass the command output through it, returning JSON output. The YAML spec file defines how to parse the CLI output
Examples
--------
.. code-block:: yaml
# Using parse_cli
# outputConfig
# ip dhcp pool Data
# import all
# network 192.168.1.0 255.255.255.0
# update dns
# default-router 192.168.1.1
# dns-server 192.168.1.1 8.8.8.8
# option 42 ip 192.168.1.1
# domain-name test.local
# lease 8
# pconnection.yml
# ---
# vars:
# dhcp_pool:
# name: "{{ item.name }}"
# network: "{{ item.network_ip }}"
# subnet: "{{ item.network_subnet }}"
# dns_servers: "{{ item.dns_servers_1 }}{{ item.dns_servers_2 }}"
# domain_name: "{{ item.domain_name_0 }}{{ item.domain_name_1 }}{{ item.domain_name_2 }}{{ item.domain_name_3 }}"
# options: "{{ item.options_1 }}{{ item.options_2 }}"
# lease_days: "{{ item.lease_days }}"
# lease_hours: "{{ item.lease_hours }}"
# lease_minutes: "{{ item.lease_minutes }}"
# keys:
# dhcp_pools:
# value: "{{ dhcp_pool }}"
# items: "^ip dhcp pool (
# ?P<name>[^\\n]+)\\s+(?:import (?P<import_all>all)\\s*)?(?:network (?P<network_ip>[\\d.]+)
# (?P<network_subnet>[\\d.]+)?\\s*)?(?:update dns\\s*)?(?:host (?P<host_ip>[\\d.]+)
# (?P<host_subnet>[\\d.]+)\\s*)?(?:domain-name (?P<domain_name_0>[\\w._-]+)\\s+)?
# (?:default-router (?P<default_router>[\\d.]+)\\s*)?(?:dns-server
# (?P<dns_servers_1>(?:[\\d.]+ ?)+ ?)+\\s*)?(?:domain-name (?P<domain_name_1>[\\w._-]+)\\s+)?
# (?P<options_1>(?:option [^\\n]+\\n*\\s*)*)?(?:domain-name (?P<domain_name_2>[\\w._-]+)\\s+)?(?P<options_2>(?:option [^\\n]+\\n*\\s*)*)?
# (?:dns-server (?P<dns_servers_2>(?:[\\d.]+ ?)+ ?)+\\s*)?(?:domain-name
# (?P<domain_name_3>[\\w._-]+)\\s*)?(lease (?P<lease_days>\\d+)(?: (?P<lease_hours>\\d+))?(?: (?P<lease_minutes>\\d+))?\\s*)?(?:update arp)?"
# playbook
- name: Add config data
ansible.builtin.set_fact:
opconfig: "{{lookup('ansible.builtin.file', 'outputConfig') }}"
- name: Parse Data
ansible.builtin.set_fact:
output: "{{ opconfig | parse_cli('pconnection.yml') }}"
# Task Output
# -----------
#
# TASK [Add config data]
# ok: [host] => changed=false
# ansible_facts:
# xml: |-
# ip dhcp pool Data
# import all
# network 192.168.1.0 255.255.255.0
# update dns
# default-router 192.168.1.1
# dns-server 192.168.1.1 8.8.8.8
# option 42 ip 192.168.1.1
# domain-name test.local
# lease 8
# TASK [Parse Data]
# ok: [host] => changed=false
# ansible_facts:
# output:
# dhcp_pools:
# - dns_servers: 192.168.1.1 8.8.8.8
# domain_name: test.local
# lease_days: 8
# lease_hours: null
# lease_minutes: null
# name: Data
# network: 192.168.1.0
# options: |-
# option 42 ip 192.168.1.1
# subnet: 255.255.255.0
Status
------
Authors
~~~~~~~
- Peter Sprygada (@privateip)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,148 @@
.. _ansible.netcommon.parse_cli_textfsm_filter:
***********************************
ansible.netcommon.parse_cli_textfsm
***********************************
**parse_cli_textfsm filter plugin.**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- The network filters also support parsing the output of a CLI command using the TextFSM library. To parse the CLI output with TextFSM use this filter.
- Using the parameters below - ``data | ansible.netcommon.parse_cli_textfsm(template.yml``)
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>template</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>The template to compare it with.</div>
<div>For example <code>data | ansible.netcommon.parse_cli_textfsm(template.yml</code>), in this case <code>data</code> represents this option.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>value</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">raw</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>This source data on which parse_cli_textfsm invokes.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- Use of the TextFSM filter requires the TextFSM library to be installed.
Examples
--------
.. code-block:: yaml
# Using parse_cli_textfsm
- name: "Fetch command output"
cisco.ios.ios_command:
commands:
- show lldp neighbors
register: lldp_output
- name: "Invoke parse_cli_textfsm"
ansible.builtin.set_fact:
device_neighbors: "{{ lldp_output.stdout[0] | parse_cli_textfsm('~/ntc-templates/templates/cisco_ios_show_lldp_neighbors.textfsm') }}"
- name: "Debug"
ansible.builtindebug:
msg: "{{ device_neighbors }}"
# Task Output
# -----------
#
# TASK [Fetch command output]
# ok: [rtr-2]
# TASK [Invoke parse_cli_textfsm]
# ok: [rtr-1]
# TASK [Debug]
# ok: [rtr-1] => {
# "msg": [
# {
# "CAPABILITIES": "R",
# "LOCAL_INTERFACE": "Gi0/0",
# "NEIGHBOR": "rtr-3",
# "NEIGHBOR_INTERFACE": "Gi0/0"
# },
# {
# "CAPABILITIES": "R",
# "LOCAL_INTERFACE": "Gi0/1",
# "NEIGHBOR": "rtr-1",
# "NEIGHBOR_INTERFACE": "Gi0/1"
# }
# ]
# }
Status
------
Authors
~~~~~~~
- Peter Sprygada (@privateip)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,223 @@
.. _ansible.netcommon.parse_xml_filter:
***************************
ansible.netcommon.parse_xml
***************************
**The parse_xml filter plugin.**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This filter will load the spec file and pass the command output through it, returning JSON output.
- The YAML spec file defines how to parse the CLI output.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>output</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">raw</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>This source xml on which parse_xml invokes.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>tmpl</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>The spec file should be valid formatted YAML. It defines how to parse the XML output and return JSON data.</div>
<div>For example <code>xml_data | ansible.netcommon.parse_xml(template.yml</code>), in this case <code>xml_data</code> represents xml data option.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- To convert the XML output of a network device command into structured JSON output.
Examples
--------
.. code-block:: yaml
# Using parse_xml
# example_output.xml
# <?xml version="1.0" encoding="UTF-8"?>
# <rpc-reply message-id="urn:uuid:0cadb4e8-5bba-47f4-986e-72906227007f">
# <data>
# <ntp>
# <nodes>
# <node>
# <node>0/0/CPU0</node>
# <associations>
# <is-ntp-enabled>true</is-ntp-enabled>
# <sys-leap>ntp-leap-no-warning</sys-leap>
# <peer-summary-info>
# <peer-info-common>
# <host-mode>ntp-mode-client</host-mode>
# <is-configured>true</is-configured>
# <address>10.1.1.1</address>
# <reachability>0</reachability>
# </peer-info-common>
# <time-since>-1</time-since>
# </peer-summary-info>
# <peer-summary-info>
# <peer-info-common>
# <host-mode>ntp-mode-client</host-mode>
# <is-configured>true</is-configured>
# <address>172.16.252.29</address>
# <reachability>255</reachability>
# </peer-info-common>
# <time-since>991</time-since>
# </peer-summary-info>
# </associations>
# </node>
# </nodes>
# </ntp>
# </data>
# </rpc-reply>
# parse_xml.yml
# ---
# vars:
# ntp_peers:
# address: "{{ item.address }}"
# reachability: "{{ item.reachability}}"
# keys:
# result:
# value: "{{ ntp_peers }}"
# top: data/ntp/nodes/node/associations
# items:
# address: peer-summary-info/peer-info-common/address
# reachability: peer-summary-info/peer-info-common/reachability
- name: Facts setup
ansible.builtin.set_fact:
xml: "{{ lookup('file', 'example_output.xml') }}"
- name: Parse xml invocation
ansible.builtin.debug:
msg: "{{ xml | ansible.netcommon.parse_xml('parse_xml.yml') }}"
# Task Output
# -----------
#
# TASK [set xml Data]
# ok: [host] => changed=false
# ansible_facts:
# xml: |-
# <?xml version="1.0" encoding="UTF-8"?>
# <rpc-reply message-id="urn:uuid:0cadb4e8-5bba-47f4-986e-72906227007f">
# <data>
# <ntp>
# <nodes>
# <node>
# <node>0/0/CPU0</node>
# <associations>
# <is-ntp-enabled>true</is-ntp-enabled>
# <sys-leap>ntp-leap-no-warning</sys-leap>
# <peer-summary-info>
# <peer-info-common>
# <host-mode>ntp-mode-client</host-mode>
# <is-configured>true</is-configured>
# <address>10.1.1.1</address>
# <reachability>0</reachability>
# </peer-info-common>
# <time-since>-1</time-since>
# </peer-summary-info>
# <peer-summary-info>
# <peer-info-common>
# <host-mode>ntp-mode-client</host-mode>
# <is-configured>true</is-configured>
# <address>172.16.252.29</address>
# <reachability>255</reachability>
# </peer-info-common>
# <time-since>991</time-since>
# </peer-summary-info>
# </associations>
# </node>
# </nodes>
# </ntp>
# </data>
# </rpc-reply>
# TASK [Parse Data]
# ok: [host] => changed=false
# ansible_facts:
# output:
# result:
# - address:
# - 10.1.1.1
# - 172.16.252.29
# reachability:
# - '0'
# - '255'
Status
------
Authors
~~~~~~~
- Ganesh Nalawade (@ganeshrn)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,151 @@
.. _ansible.netcommon.persistent_connection:
****************************
ansible.netcommon.persistent
****************************
**Use a persistent unix socket for connection**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This is a helper plugin to allow making other connections persistent.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>import_modules</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"yes"</div>
</td>
<td>
<div> ini entries:
<p>[ansible_network]<br>import_modules = yes</p>
</div>
<div>env:ANSIBLE_NETWORK_IMPORT_MODULES</div>
<div>var: ansible_network_import_modules</div>
</td>
<td>
<div>Reduce CPU usage and network module execution time by enabling direct execution. Instead of the module being packaged and executed by the shell, it will be directly executed by the Ansible control node using the same python interpreter as the Ansible process. Note- Incompatible with <code>asynchronous mode</code>. Note- Python 3 and Ansible 2.9.16 or greater required. Note- With Ansible 2.9.x fully qualified modules names are required in tasks.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_command_timeout</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">30</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>command_timeout = 30</p>
</div>
<div>env:ANSIBLE_PERSISTENT_COMMAND_TIMEOUT</div>
<div>var: ansible_command_timeout</div>
</td>
<td>
<div>Configures, in seconds, the amount of time to wait for a command to return from the remote device. If this timer is exceeded before the command returns, the connection plugin will raise an exception and close.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_connect_timeout</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">30</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>connect_timeout = 30</p>
</div>
<div>env:ANSIBLE_PERSISTENT_CONNECT_TIMEOUT</div>
<div>var: ansible_connect_timeout</div>
</td>
<td>
<div>Configures, in seconds, the amount of time to wait when trying to initially establish a persistent connection. If this value expires before the connection to the remote device is completed, the connection will fail.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>persistent_log_messages</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"no"</div>
</td>
<td>
<div> ini entries:
<p>[persistent_connection]<br>log_messages = no</p>
</div>
<div>env:ANSIBLE_PERSISTENT_LOG_MESSAGES</div>
<div>var: ansible_persistent_log_messages</div>
</td>
<td>
<div>This flag will enable logging the command executed and response received from target device in the ansible log file. For this option to work &#x27;log_path&#x27; ansible configuration option is required to be set to a file path with write access.</div>
<div>Be sure to fully understand the security implications of enabling this option as it could create a security vulnerability by logging sensitive information in log file.</div>
</td>
</tr>
</table>
<br/>
Status
------
Authors
~~~~~~~
- Ansible Networking Team (@ansible-network)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,226 @@
.. _ansible.netcommon.restconf_config_module:
*********************************
ansible.netcommon.restconf_config
*********************************
**Handles create, update, read and delete of configuration data on RESTCONF enabled devices.**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- RESTCONF is a standard mechanisms to allow web applications to configure and manage data. RESTCONF is a IETF standard and documented on RFC 8040.
- This module allows the user to configure data on RESTCONF enabled devices.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>content</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>The configuration data in format as specififed in <code>format</code> option. Required unless <code>method</code> is <em>delete</em>.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>format</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>json</b>&nbsp;&larr;</div></li>
<li>xml</li>
</ul>
</td>
<td>
<div>The format of the configuration provided as value of <code>content</code>. Accepted values are <em>xml</em> and <em>json</em> and the given configuration format should be supported by remote RESTCONF server.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>method</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>post</b>&nbsp;&larr;</div></li>
<li>put</li>
<li>patch</li>
<li>delete</li>
</ul>
</td>
<td>
<div>The RESTCONF method to manage the configuration change on device. The value <em>post</em> is used to create a data resource or invoke an operation resource, <em>put</em> is used to replace the target data resource, <em>patch</em> is used to modify the target resource, and <em>delete</em> is used to delete the target resource.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>path</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
<div>URI being used to execute API calls.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- This module requires the RESTCONF system service be enabled on the remote device being managed.
- This module is supported with *ansible_connection* value of *ansible.netcommon.httpapi* and *ansible_network_os* value of *ansible.netcommon.restconf*.
- This module is tested against Cisco IOSXE 16.12.02 version.
Examples
--------
.. code-block:: yaml
- name: create l3vpn services
ansible.netcommon.restconf_config:
path: /config/ietf-l3vpn-svc:l3vpn-svc/vpn-services
content: |
{
"vpn-service":[
{
"vpn-id": "red_vpn2",
"customer-name": "blue",
"vpn-service-topology": "ietf-l3vpn-svc:any-to-any"
},
{
"vpn-id": "blue_vpn1",
"customer-name": "red",
"vpn-service-topology": "ietf-l3vpn-svc:any-to-any"
}
]
}
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>candidate</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
</td>
<td>When the method is not delete</td>
<td>
<div>The configuration sent to the device.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">{
&quot;vpn-service&quot;: [
{
&quot;customer-name&quot;: &quot;red&quot;,
&quot;vpn-id&quot;: &quot;blue_vpn1&quot;,
&quot;vpn-service-topology&quot;: &quot;ietf-l3vpn-svc:any-to-any&quot;
}
]
}</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>running</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
</td>
<td>When the method is not delete</td>
<td>
<div>The current running configuration on the device.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">{
&quot;vpn-service&quot;: [
{
&quot;vpn-id&quot;: &quot;red_vpn2&quot;,
&quot;customer-name&quot;: &quot;blue&quot;,
&quot;vpn-service-topology&quot;: &quot;ietf-l3vpn-svc:any-to-any&quot;
},
{
&quot;vpn-id&quot;: &quot;blue_vpn1&quot;,
&quot;customer-name&quot;: &quot;red&quot;,
&quot;vpn-service-topology&quot;: &quot;ietf-l3vpn-svc:any-to-any&quot;
}
]
}</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Ganesh Nalawade (@ganeshrn)

View File

@@ -0,0 +1,167 @@
.. _ansible.netcommon.restconf_get_module:
******************************
ansible.netcommon.restconf_get
******************************
**Fetch configuration/state data from RESTCONF enabled devices.**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- RESTCONF is a standard mechanisms to allow web applications to access the configuration data and state data developed and standardized by the IETF. It is documented in RFC 8040.
- This module allows the user to fetch configuration and state data from RESTCONF enabled devices.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>content</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>config</li>
<li>nonconfig</li>
<li>all</li>
</ul>
</td>
<td>
<div>The <code>content</code> is a query parameter that controls how descendant nodes of the requested data nodes in <code>path</code> will be processed in the reply. If value is <em>config</em> return only configuration descendant data nodes of value in <code>path</code>. If value is <em>nonconfig</em> return only non-configuration descendant data nodes of value in <code>path</code>. If value is <em>all</em> return all descendant data nodes of value in <code>path</code></div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>output</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>json</b>&nbsp;&larr;</div></li>
<li>xml</li>
</ul>
</td>
<td>
<div>The output of response received.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>path</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
<div>URI being used to execute API calls.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- This module requires the RESTCONF system service be enabled on the remote device being managed.
- This module is supported with *ansible_connection* value of *ansible.netcommon.httpapi* and *ansible_network_os* value of *ansible.netcommon.restconf*.
- This module is tested against Cisco IOSXE 16.12.02 version.
Examples
--------
.. code-block:: yaml
- name: get l3vpn services
ansible.netcommon.restconf_get:
path: /config/ietf-l3vpn-svc:l3vpn-svc/vpn-services
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>response</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
</td>
<td>when the device response is valid JSON</td>
<td>
<div>A dictionary representing a JSON-formatted response</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">{
&quot;vpn-services&quot;: {
&quot;vpn-service&quot;: [
{
&quot;customer-name&quot;: &quot;red&quot;,
&quot;vpn-id&quot;: &quot;blue_vpn1&quot;,
&quot;vpn-service-topology&quot;: &quot;ietf-l3vpn-svc:any-to-any&quot;
}
]
}
}</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Ganesh Nalawade (@ganeshrn)

View File

@@ -0,0 +1,77 @@
.. _ansible.netcommon.restconf_httpapi:
**************************
ansible.netcommon.restconf
**************************
**HttpApi Plugin for devices supporting Restconf API**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- This HttpApi plugin provides methods to connect to Restconf API endpoints.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>root_path</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"/restconf"</div>
</td>
<td>
<div>var: ansible_httpapi_restconf_root</div>
</td>
<td>
<div>Specifies the location of the Restconf root.</div>
</td>
</tr>
</table>
<br/>
Status
------
Authors
~~~~~~~
- Ansible Networking Team (@ansible-network)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,319 @@
.. _ansible.netcommon.telnet_module:
************************
ansible.netcommon.telnet
************************
**Executes a low-down and dirty telnet command**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- Executes a low-down and dirty telnet command, not going through the module subsystem.
- This is mostly to be used for enabling ssh on devices that only have telnet enabled by default.
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>command</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
/ <span style="color: purple">elements=string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
<div>List of commands to be executed in the telnet session.</div>
<div style="font-size: small; color: darkgreen"><br/>aliases: commands</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>crlf</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>Sends a CRLF (Carrage Return) instead of just a LF (Line Feed).</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>host</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"remote_addr"</div>
</td>
<td>
<div>The host/target on which to execute the command</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>login_prompt</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"login: "</div>
</td>
<td>
<div>Login or username prompt to expect</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>password</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
<div>The password for login</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>password_prompt</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"Password: "</div>
</td>
<td>
<div>Login or username prompt to expect</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>pause</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">1</div>
</td>
<td>
<div>Seconds to pause between each command issued</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>port</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">23</div>
</td>
<td>
<div>Remote port to use</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>prompts</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
/ <span style="color: purple">elements=string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">["$"]</div>
</td>
<td>
<div>List of prompts expected before sending next command</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>send_newline</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>Sends a newline character upon successful connection to start the terminal session.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>timeout</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">120</div>
</td>
<td>
<div>timeout for remote operations</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>user</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"remote_user"</div>
</td>
<td>
<div>The user for login</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- The ``environment`` keyword does not work with this task
Examples
--------
.. code-block:: yaml
- name: send configuration commands to IOS
ansible.netcommon.telnet:
user: cisco
password: cisco
login_prompt: "Username: "
prompts:
- "[>#]"
command:
- terminal length 0
- configure terminal
- hostname ios01
- name: run show commands
ansible.netcommon.telnet:
user: cisco
password: cisco
login_prompt: "Username: "
prompts:
- "[>#]"
command:
- terminal length 0
- show version
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Key</th>
<th>Returned</th>
<th width="100%">Description</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>output</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
</div>
</td>
<td>always</td>
<td>
<div>output of each command is an element in this list</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[&#x27;success&#x27;, &#x27;success&#x27;, &#x27;&#x27;, &#x27;warning .. something&#x27;]</div>
</td>
</tr>
</table>
<br/><br/>
Status
------
Authors
~~~~~~~
- Ansible Core Team

View File

@@ -0,0 +1,127 @@
.. _ansible.netcommon.type5_pw_filter:
**************************
ansible.netcommon.type5_pw
**************************
**The type5_pw filter plugin.**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- Filter plugin to produce cisco type5 hashed password.
- Using the parameters below - ``xml_data | ansible.netcommon.type5_pw(template.yml``)
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>password</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>The password to be hashed.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>salt</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>Mention the salt to hash the password.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- The filter plugin generates cisco type5 hashed password.
Examples
--------
.. code-block:: yaml
# Using type5_pw
- name: Set some facts
ansible.builtin.set_fact:
password: "cisco@123"
- name: Filter type5_pw invocation
ansible.builtin.debug:
msg: "{{ password | ansible.netcommon.type5_pw(salt='avs') }}"
# Task Output
# -----------
#
# TASK [Set some facts]
# ok: [host] => changed=false
# ansible_facts:
# password: cisco@123
# TASK [Filter type5_pw invocation]
# ok: [host] =>
# msg: $1$avs$uSTOEMh65qzvpb9yBMpzd/
Status
------
Authors
~~~~~~~
- Ken Celenza (@itdependsnetworks)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,119 @@
.. _ansible.netcommon.vlan_expander_filter:
*******************************
ansible.netcommon.vlan_expander
*******************************
**The vlan_expander filter plugin.**
Version added: 2.3.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- Expand shorthand list of VLANs to list all VLANs. Inverse of vlan_parser
- Using the parameters below - ``vlans_data | ansible.netcommon.vlan_expander``
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>data</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>This option represents a string containing the range of vlans.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- The filter plugin extends vlans when data provided in range or comma separated.
Examples
--------
.. code-block:: yaml
# Using vlan_expander
- name: Setting host facts for vlan_expander filter plugin
ansible.builtin.set_fact:
vlan_ranges: "1,10-12,15,20-22"
- name: Invoke vlan_expander filter plugin
ansible.builtin.set_fact:
extended_vlans: "{{ vlan_ranges | ansible.netcommon.vlan_expander }}"
# Task Output
# -----------
#
# TASK [Setting host facts for vlan_expander filter plugin]
# ok: [host] => changed=false
# ansible_facts:
# vlan_ranges: 1,10-12,15,20-22
# TASK [Invoke vlan_expander filter plugin]
# ok: [host] => changed=false
# ansible_facts:
# extended_vlans:
# - 1
# - 10
# - 11
# - 12
# - 15
# - 20
# - 21
# - 22
Status
------
Authors
~~~~~~~
- Akira Yokochi (@akira6592)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,181 @@
.. _ansible.netcommon.vlan_parser_filter:
*****************************
ansible.netcommon.vlan_parser
*****************************
**The vlan_parser filter plugin.**
Version added: 1.0.0
.. contents::
:local:
:depth: 1
Synopsis
--------
- The filter plugin converts a list of vlans to IOS like vlan configuration.
- Converts list to a list of range of numbers into multiple lists.
- ``vlans_data | ansible.netcommon.vlan_parser(first_line_len = 20, other_line_len=20``)
Parameters
----------
.. raw:: html
<table border=0 cellpadding=0 class="documentation-table">
<tr>
<th colspan="1">Parameter</th>
<th>Choices/<font color="blue">Defaults</font></th>
<th>Configuration</th>
<th width="100%">Comments</th>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>data</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">list</span>
/ <span style="color: red">required</span>
</div>
</td>
<td>
</td>
<td>
</td>
<td>
<div>This option represents a list containing vlans.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>first_line_len</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">48</div>
</td>
<td>
</td>
<td>
<div>The first line of the list can be first_line_len characters long.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>other_line_len</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">integer</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">44</div>
</td>
<td>
</td>
<td>
<div>The subsequent list lines can be other_line_len characters.</div>
</td>
</tr>
</table>
<br/>
Notes
-----
.. note::
- The filter plugin extends vlans when data provided in range or comma separated.
Examples
--------
.. code-block:: yaml
# Using vlan_parser
- name: Setting host facts for vlan_parser filter plugin
ansible.builtin.set_fact:
vlans:
[
100,
1688,
3002,
3003,
3004,
3005,
3102,
3103,
3104,
3105,
3802,
3900,
3998,
3999,
]
- name: Invoke vlan_parser filter plugin
ansible.builtin.set_fact:
vlans_ranges: "{{ vlans | ansible.netcommon.vlan_parser(first_line_len = 20, other_line_len=20) }}"
# Task Output
# -----------
#
# TASK [Setting host facts for vlan_parser filter plugin]
# ok: [host] => changed=false
# ansible_facts:
# vlans:
# - 100
# - 1688
# - 3002
# - 3003
# - 3004
# - 3005
# - 3102
# - 3103
# - 3104
# - 3105
# - 3802
# - 3900
# - 3998
# - 3999
# TASK [Invoke vlan_parser filter plugin]
# ok: [host] => changed=false
# ansible_facts:
# msg:
# - 100,1688,3002-3005
# - 3102-3105,3802,3900
# - 3998,3999
Status
------
Authors
~~~~~~~
- Steve Dodd (@idahood)
.. hint::
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.

View File

@@ -0,0 +1,94 @@
---
requires_ansible: ">=2.14.0"
plugin_routing:
action:
grpc_config:
redirect: ansible.netcommon.grpc
grpc_get:
redirect: ansible.netcommon.grpc
filter:
cidr_merge:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.cidr_merge' module instead.
redirect: ansible.utils.cidr_merge
ipaddr:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.ipaddr' module instead.
redirect: ansible.utils.ipaddr
ipmath:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.ipmath' module instead.
redirect: ansible.utils.ipmath
ipwrap:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.ipwrap' module instead.
redirect: ansible.utils.ipwrap
ip4_hex:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.ip4_hex' module instead.
redirect: ansible.utils.ipv4_hex
ipv4:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.ipv4' module instead.
redirect: ansible.utils.ipv4
ipv6:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.ipv6' module instead.
redirect: ansible.utils.ipv6
ipsubnet:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.ipsubnet' module instead.
redirect: ansible.utils.ipsubnet
next_nth_usable:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.next_nth_usable' module instead.
redirect: ansible.utils.next_nth_usable
network_in_network:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.network_in_network' module instead.
redirect: ansible.utils.network_in_network
network_in_usable:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.network_in_usable' module instead.
redirect: ansible.utils.network_in_usable
reduce_on_network:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.reduce_on_network' module instead.
redirect: ansible.utils.reduce_on_network
nthhost:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.nthhost' module instead.
redirect: ansible.utils.nthhost
previous_nth_usable:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.previous_nth_usable' module instead.
redirect: ansible.utils.previous_nth_usable
slaac:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.slaac' module instead.
redirect: ansible.utils.slaac
hwaddr:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.hwaddr' module instead.
redirect: ansible.utils.hwaddr
macaddr:
deprecation:
removal_date: "2024-01-01"
warning_text: Use 'ansible.utils.macaddr' module instead.
redirect: ansible.utils.macaddr

View File

@@ -0,0 +1,31 @@
#
# Copyright 2018 Red Hat Inc.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.ansible.netcommon.plugins.action.network import (
ActionModule as ActionNetworkModule,
)
class ActionModule(ActionNetworkModule):
def run(self, tmp=None, task_vars=None):
if self._play_context.connection.split(".")[-1] != "network_cli":
return {
"failed": True,
"msg": "Connection type %s is not valid for this module"
% self._play_context.connection,
}
result = super(ActionModule, self).run(task_vars=task_vars)
self._handle_backup_option(
result,
task_vars,
self._task.args,
)
return result

View File

@@ -0,0 +1,24 @@
#
# Copyright 2018 Red Hat Inc.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.ansible.netcommon.plugins.action.network import (
ActionModule as ActionNetworkModule,
)
class ActionModule(ActionNetworkModule):
def run(self, tmp=None, task_vars=None):
if self._play_context.connection.split(".")[-1] != "network_cli":
return {
"failed": True,
"msg": "Connection type %s is not valid for this module"
% self._play_context.connection,
}
return super(ActionModule, self).run(task_vars=task_vars)

View File

@@ -0,0 +1,28 @@
#
# Copyright 2018 Red Hat Inc.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.ansible.netcommon.plugins.action.network import (
ActionModule as ActionNetworkModule,
)
class ActionModule(ActionNetworkModule):
def run(self, tmp=None, task_vars=None):
del tmp # tmp no longer has any effect
self._config_module = True
if self._play_context.connection.split(".")[-1] != "network_cli":
return {
"failed": True,
"msg": "Connection type %s is not valid for cli_config module"
% self._play_context.connection,
}
return super(ActionModule, self).run(task_vars=task_vars)

View File

@@ -0,0 +1,35 @@
#
# Copyright 2022 Red Hat Inc.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.ansible.netcommon.plugins.action.network import (
ActionModule as ActionNetworkModule,
)
class ActionModule(ActionNetworkModule):
def run(self, tmp=None, task_vars=None):
del tmp # tmp no longer has any effect
self._config_module = True
warnings = []
if self._play_context.connection.split(".")[-1] != "grpc":
return {
"failed": True,
"msg": "Connection type %s is not valid for grpc module. "
"Valid connection type is grpc" % self._play_context.connection,
}
result = super(ActionModule, self).run(task_vars=task_vars)
if warnings:
if "warnings" in result:
result["warnings"].extend(warnings)
else:
result["warnings"] = warnings
return result

View File

@@ -0,0 +1,182 @@
# (c) 2018, Ansible Inc,
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import hashlib
import os
import re
import uuid
from ansible.errors import AnsibleError
from ansible.module_utils._text import to_bytes, to_text
from ansible.module_utils.connection import Connection, ConnectionError
from ansible.module_utils.six.moves.urllib.parse import urlsplit
from ansible.plugins.action import ActionBase
from ansible.utils.display import Display
display = Display()
class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
changed = False
socket_path = None
self._get_network_os(task_vars)
persistent_connection = self._play_context.connection.split(".")[-1]
result = super(ActionModule, self).run(task_vars=task_vars)
if persistent_connection != "network_cli":
# It is supported only with network_cli
result["failed"] = True
result["msg"] = (
"connection type %s is not valid for net_get module,"
" please use fully qualified name of network_cli connection type"
% self._play_context.connection
)
return result
try:
src = self._task.args["src"]
except KeyError as exc:
return {
"failed": True,
"msg": "missing required argument: %s" % exc,
}
# Get destination file if specified
dest = self._task.args.get("dest")
if dest is None:
dest = self._get_default_dest(src)
else:
dest = self._handle_dest_path(dest)
# Get proto
proto = self._task.args.get("protocol")
if proto is None:
proto = "scp"
if socket_path is None:
socket_path = self._connection.socket_path
conn = Connection(socket_path)
sock_timeout = conn.get_option("persistent_command_timeout")
try:
changed = self._handle_existing_file(conn, src, dest, proto, sock_timeout)
if changed is False:
result["changed"] = changed
result["destination"] = dest
return result
except Exception as exc:
result["msg"] = "Warning: %s idempotency check failed. Check dest" % exc
try:
conn.get_file(source=src, destination=dest, proto=proto, timeout=sock_timeout)
except Exception as exc:
result["failed"] = True
result["msg"] = "Exception received: %s" % exc
result["changed"] = changed
result["destination"] = dest
return result
def _handle_dest_path(self, dest):
working_path = self._get_working_path()
if os.path.isabs(dest) or urlsplit("dest").scheme:
dst = dest
else:
dst = self._loader.path_dwim_relative(working_path, "", dest)
return dst
def _get_src_filename_from_path(self, src_path):
filename_list = re.split("/|:", src_path)
return filename_list[-1]
def _get_default_dest(self, src_path):
dest_path = self._get_working_path()
src_fname = self._get_src_filename_from_path(src_path)
filename = "%s/%s" % (dest_path, src_fname)
return filename
def _handle_existing_file(self, conn, source, dest, proto, timeout):
"""
Determines whether the source and destination file match.
:return: False if source and dest both exist and have matching sha1 sums, True otherwise.
"""
if not os.path.exists(dest):
return True
cwd = self._loader.get_basedir()
filename = str(uuid.uuid4())
tmp_dest_file = os.path.join(cwd, filename)
try:
conn.get_file(
source=source,
destination=tmp_dest_file,
proto=proto,
timeout=timeout,
)
except ConnectionError as exc:
error = to_text(exc)
if error.endswith("No such file or directory"):
if os.path.exists(tmp_dest_file):
os.remove(tmp_dest_file)
return True
try:
with open(tmp_dest_file, "r") as f:
new_content = f.read()
with open(dest, "r") as f:
old_content = f.read()
except (IOError, OSError):
os.remove(tmp_dest_file)
raise
sha1 = hashlib.sha1()
old_content_b = to_bytes(old_content, errors="surrogate_or_strict")
sha1.update(old_content_b)
checksum_old = sha1.digest()
sha1 = hashlib.sha1()
new_content_b = to_bytes(new_content, errors="surrogate_or_strict")
sha1.update(new_content_b)
checksum_new = sha1.digest()
os.remove(tmp_dest_file)
if checksum_old == checksum_new:
return False
return True
def _get_working_path(self):
cwd = self._loader.get_basedir()
if self._task._role is not None:
cwd = self._task._role._role_path
return cwd
def _get_network_os(self, task_vars):
if "network_os" in self._task.args and self._task.args["network_os"]:
display.vvvv("Getting network OS from task argument")
network_os = self._task.args["network_os"]
elif self._play_context.network_os:
display.vvvv("Getting network OS from inventory")
network_os = self._play_context.network_os
elif (
"network_os" in task_vars.get("ansible_facts", {})
and task_vars["ansible_facts"]["network_os"]
):
display.vvvv("Getting network OS from fact")
network_os = task_vars["ansible_facts"]["network_os"]
else:
raise AnsibleError("ansible_network_os must be specified on this host")
return network_os

View File

@@ -0,0 +1,87 @@
# (c) 2017, Ansible by Red Hat, inc
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import copy
from ansible.errors import AnsibleError
from ansible.plugins.action import ActionBase
from ansible.utils.display import Display
display = Display()
class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
del tmp # tmp no longer has any effect
result = {}
play_context = copy.deepcopy(self._play_context)
play_context.network_os = self._get_network_os(task_vars)
new_task = self._task.copy()
module = self._get_implementation_module(play_context.network_os, self._task.action)
if not module:
if self._task.args["fail_on_missing_module"]:
result["failed"] = True
else:
result["failed"] = False
result["msg"] = "Could not find implementation module %s for %s" % (
self._task.action,
play_context.network_os,
)
return result
new_task.action = module
action = self._shared_loader_obj.action_loader.get(
play_context.network_os,
task=new_task,
connection=self._connection,
play_context=play_context,
loader=self._loader,
templar=self._templar,
shared_loader_obj=self._shared_loader_obj,
)
display.vvvv("Running implementation module %s" % module)
return action.run(task_vars=task_vars)
def _get_network_os(self, task_vars):
if "network_os" in self._task.args and self._task.args["network_os"]:
display.vvvv("Getting network OS from task argument")
network_os = self._task.args["network_os"]
elif self._play_context.network_os:
display.vvvv("Getting network OS from inventory")
network_os = self._play_context.network_os
elif (
"network_os" in task_vars.get("ansible_facts", {})
and task_vars["ansible_facts"]["network_os"]
):
display.vvvv("Getting network OS from fact")
network_os = task_vars["ansible_facts"]["network_os"]
else:
raise AnsibleError(
"ansible_network_os must be specified on this host to use platform agnostic modules"
)
return network_os
def _get_implementation_module(self, network_os, platform_agnostic_module):
module_name = network_os.split(".")[-1] + "_" + platform_agnostic_module.partition("_")[2]
if "." in network_os:
fqcn_module = ".".join(network_os.split(".")[0:-1])
implementation_module = fqcn_module + "." + module_name
else:
implementation_module = module_name
if implementation_module not in self._shared_loader_obj.module_loader:
implementation_module = None
return implementation_module

View File

@@ -0,0 +1,255 @@
# (c) 2018, Ansible Inc,
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import hashlib
import os
import uuid
from ansible.errors import AnsibleError
from ansible.module_utils._text import to_bytes, to_text
from ansible.module_utils.connection import Connection, ConnectionError
from ansible.module_utils.six.moves.urllib.parse import urlsplit
from ansible.plugins.action import ActionBase
from ansible.utils.display import Display
display = Display()
class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
changed = False
socket_path = None
network_os = self._get_network_os(task_vars).split(".")[-1]
persistent_connection = self._play_context.connection.split(".")[-1]
result = super(ActionModule, self).run(task_vars=task_vars)
if persistent_connection != "network_cli":
# It is supported only with network_cli
result["failed"] = True
result["msg"] = (
"connection type %s is not valid for net_put module,"
" please use fully qualified name of network_cli connection type"
% self._play_context.connection
)
return result
try:
src = self._task.args["src"]
except KeyError as exc:
return {
"failed": True,
"msg": "missing required argument: %s" % exc,
}
src_file_path_name = src
# Get destination file if specified
dest = self._task.args.get("dest")
# Get proto
proto = self._task.args.get("protocol")
if proto is None:
proto = "scp"
# Get mode if set
mode = self._task.args.get("mode")
if mode is None:
mode = "binary"
if mode == "text":
try:
self._handle_src_option(convert_data=False)
except AnsibleError as exc:
return dict(failed=True, msg=to_text(exc))
# Now src has resolved file write to disk in current diectory for scp
src = self._task.args.get("src")
filename = str(uuid.uuid4())
cwd = self._loader.get_basedir()
output_file = os.path.join(cwd, filename)
try:
with open(output_file, "wb") as f:
f.write(to_bytes(src, encoding="utf-8"))
except Exception:
os.remove(output_file)
raise
else:
try:
output_file = self._get_binary_src_file(src)
except ValueError as exc:
return dict(failed=True, msg=to_text(exc))
if socket_path is None:
socket_path = self._connection.socket_path
conn = Connection(socket_path)
sock_timeout = conn.get_option("persistent_command_timeout")
if dest is None:
dest = src_file_path_name
try:
changed = self._handle_existing_file(conn, output_file, dest, proto, sock_timeout)
if changed is False:
result["changed"] = changed
result["destination"] = dest
if mode == "text":
# Cleanup tmp file expanded wih ansible vars
os.remove(output_file)
return result
except Exception as exc:
result["msg"] = "Warning: %s idempotency check failed. Check dest" % exc
try:
conn.copy_file(
source=output_file,
destination=dest,
proto=proto,
timeout=sock_timeout,
)
except Exception as exc:
if to_text(exc) == "No response from server":
if network_os == "iosxr":
# IOSXR sometimes closes socket prematurely after completion
# of file transfer
result["msg"] = "Warning: iosxr scp server pre close issue. Please check dest"
else:
result["failed"] = True
result["msg"] = "Exception received: %s" % exc
if mode == "text":
# Cleanup tmp file expanded wih ansible vars
os.remove(output_file)
result["changed"] = changed
result["destination"] = dest
return result
def _handle_existing_file(self, conn, source, dest, proto, timeout):
"""
Determines whether the source and destination file match.
:return: False if source and dest both exist and have matching sha1 sums, True otherwise.
"""
cwd = self._loader.get_basedir()
filename = str(uuid.uuid4())
tmp_source_file = os.path.join(cwd, filename)
try:
conn.get_file(
source=dest,
destination=tmp_source_file,
proto=proto,
timeout=timeout,
)
except ConnectionError as exc:
error = to_text(exc)
if error.endswith("No such file or directory"):
if os.path.exists(tmp_source_file):
os.remove(tmp_source_file)
return True
try:
with open(source, "r") as f:
new_content = f.read()
with open(tmp_source_file, "r") as f:
old_content = f.read()
except (IOError, OSError):
os.remove(tmp_source_file)
raise
sha1 = hashlib.sha1()
old_content_b = to_bytes(old_content, errors="surrogate_or_strict")
sha1.update(old_content_b)
checksum_old = sha1.digest()
sha1 = hashlib.sha1()
new_content_b = to_bytes(new_content, errors="surrogate_or_strict")
sha1.update(new_content_b)
checksum_new = sha1.digest()
os.remove(tmp_source_file)
if checksum_old == checksum_new:
return False
return True
def _get_binary_src_file(self, src):
working_path = self._get_working_path()
if os.path.isabs(src) or urlsplit("src").scheme:
source = src
else:
source = self._loader.path_dwim_relative(working_path, "templates", src)
if not source:
source = self._loader.path_dwim_relative(working_path, src)
if not os.path.exists(source):
raise ValueError("path specified in src not found")
return source
def _get_working_path(self):
cwd = self._loader.get_basedir()
if self._task._role is not None:
cwd = self._task._role._role_path
return cwd
def _handle_src_option(self, convert_data=True):
src = self._task.args.get("src")
working_path = self._get_working_path()
if os.path.isabs(src) or urlsplit("src").scheme:
source = src
else:
source = self._loader.path_dwim_relative(working_path, "templates", src)
if not source:
source = self._loader.path_dwim_relative(working_path, src)
if not os.path.exists(source):
raise AnsibleError("path specified in src not found")
try:
with open(source, "r") as f:
template_data = to_text(f.read())
except IOError as e:
raise AnsibleError(
"unable to load src file {0}, I/O error({1}): {2}".format(
source, e.errno, e.strerror
)
)
# Create a template search path in the following order:
# [working_path, self_role_path, dependent_role_paths, dirname(source)]
searchpath = [working_path]
if self._task._role is not None:
searchpath.append(self._task._role._role_path)
if hasattr(self._task, "_block:"):
dep_chain = self._task._block.get_dep_chain()
if dep_chain is not None:
for role in dep_chain:
searchpath.append(role._role_path)
searchpath.append(os.path.dirname(source))
self._templar.environment.loader.searchpath = searchpath
self._task.args["src"] = self._templar.template(template_data)
def _get_network_os(self, task_vars):
if "network_os" in self._task.args and self._task.args["network_os"]:
display.vvvv("Getting network OS from task argument")
network_os = self._task.args["network_os"]
elif self._play_context.network_os:
display.vvvv("Getting network OS from inventory")
network_os = self._play_context.network_os
elif (
"network_os" in task_vars.get("ansible_facts", {})
and task_vars["ansible_facts"]["network_os"]
):
display.vvvv("Getting network OS from fact")
network_os = task_vars["ansible_facts"]["network_os"]
else:
raise AnsibleError("ansible_network_os must be specified on this host")
return network_os

View File

@@ -0,0 +1,112 @@
#
# Copyright 2018 Red Hat Inc.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import copy
import sys
from ansible.utils.display import Display
from ansible_collections.ansible.netcommon.plugins.action.network import (
ActionModule as ActionNetworkModule,
)
display = Display()
class ActionModule(ActionNetworkModule):
def run(self, tmp=None, task_vars=None):
del tmp # tmp no longer has any effect
module_name = self._task.action.split(".")[-1]
self._config_module = True if module_name == "netconf_config" else False
persistent_connection = self._play_context.connection.split(".")[-1]
warnings = []
if persistent_connection not in ["netconf", "local"] and module_name == "netconf_config":
return {
"failed": True,
"msg": "Connection type %s is not valid for netconf_config module. "
"Valid connection type is netconf or local (deprecated)"
% self._play_context.connection,
}
elif persistent_connection not in ["netconf"] and module_name != "netconf_config":
return {
"failed": True,
"msg": "Connection type %s is not valid for %s module. "
"Valid connection type is netconf." % (self._play_context.connection, module_name),
}
if self._play_context.connection == "local" and module_name == "netconf_config":
args = self._task.args
pc = copy.deepcopy(self._play_context)
pc.connection = "ansible.netcommon.netconf"
pc.port = int(args.get("port") or self._play_context.port or 830)
pc.remote_user = args.get("username") or self._play_context.connection_user
pc.password = args.get("password") or self._play_context.password
pc.private_key_file = args.get("ssh_keyfile") or self._play_context.private_key_file
connection = self._shared_loader_obj.connection_loader.get(
"ansible.netcommon.persistent",
pc,
sys.stdin,
task_uuid=self._task._uuid,
)
# TODO: Remove below code after ansible minimal is cut out
if connection is None:
pc.connection = "netconf"
connection = self._shared_loader_obj.connection_loader.get(
"persistent", pc, sys.stdin, task_uuid=self._task._uuid
)
display.vvv(
"using connection plugin %s (was local)" % pc.connection,
pc.remote_addr,
)
timeout = args.get("timeout")
command_timeout = (
int(timeout) if timeout else connection.get_option("persistent_command_timeout")
)
connection.set_options(
direct={
"persistent_command_timeout": command_timeout,
"look_for_keys": args.get("look_for_keys"),
"hostkey_verify": args.get("hostkey_verify"),
"allow_agent": args.get("allow_agent"),
}
)
socket_path = connection.run()
display.vvvv("socket_path: %s" % socket_path, pc.remote_addr)
if not socket_path:
return {
"failed": True,
"msg": "unable to open shell. Please see: "
+ "https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell",
}
task_vars["ansible_socket"] = socket_path
warnings.append(
[
"connection local support for this module is deprecated and will be removed in version 2.14, use connection %s"
% pc.connection
]
)
result = super(ActionModule, self).run(task_vars=task_vars)
if warnings:
if "warnings" in result:
result["warnings"].extend(warnings)
else:
result["warnings"] = warnings
return result

View File

@@ -0,0 +1,363 @@
#
# (c) 2018 Red Hat Inc.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import os
import re
import time
from ansible.errors import AnsibleError
from ansible.module_utils._text import to_text
from ansible.module_utils.six import PY3
from ansible.module_utils.six.moves.urllib.parse import urlsplit
from ansible.plugins.action.normal import ActionModule as _ActionModule
from ansible.utils.display import Display
from ansible.utils.hashing import checksum, checksum_s
display = Display()
DEXEC_PREFIX = "ANSIBLE_NETWORK_IMPORT_MODULES:"
class ActionModule(_ActionModule):
def run(self, tmp=None, task_vars=None):
config_module = hasattr(self, "_config_module") and self._config_module
if config_module and self._task.args.get("src"):
try:
self._handle_src_option()
except AnsibleError as exc:
return dict(failed=True, msg=to_text(exc))
host = task_vars["ansible_host"]
dexec_eligible = self._check_dexec_eligibility(host)
# attempt to run using dexec
if dexec_eligible:
# find and load the module
filename, module = self._find_load_module()
display.vvvv(
"{prefix} found {action} at {fname}".format(
prefix=DEXEC_PREFIX,
action=self._task.action,
fname=filename,
),
host,
)
# not using AnsibleModule, return to normal run (eg eos_bgp)
if getattr(module, "AnsibleModule", None):
# patch and update the module
self._patch_update_module(module, task_vars)
display.vvvv(
"{prefix} running {module}".format(
prefix=DEXEC_PREFIX, module=self._task.action
),
host,
)
# execute the module, collect result
result = self._exec_module(module)
display.vvvv("{prefix} complete".format(prefix=DEXEC_PREFIX), host)
display.vvvvv(
"{prefix} Result: {result}".format(prefix=DEXEC_PREFIX, result=result),
host,
)
else:
dexec_eligible = False
display.vvvv(
"{prefix} {module} doesn't support direct execution, disabled".format(
prefix=DEXEC_PREFIX, module=self._task.action
),
host,
)
if not dexec_eligible:
result = super(ActionModule, self).run(task_vars=task_vars)
if config_module and self._task.args.get("backup") and not result.get("failed"):
self._handle_backup_option(
result,
task_vars,
self._task.args.get("backup_options"),
)
return result
def _handle_backup_option(self, result, task_vars, backup_options):
filename = None
backup_path = None
try:
non_config_regexes = self._connection.cliconf.get_option("non_config_lines", task_vars)
except (AttributeError, KeyError):
non_config_regexes = []
try:
content = self._sanitize_contents(
contents=result.pop("__backup__"), filters=non_config_regexes
)
except KeyError:
raise AnsibleError("Failed while reading configuration backup")
if backup_options:
filename = backup_options.get("filename")
backup_path = backup_options.get("dir_path")
tstamp = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time()))
if not backup_path:
cwd = self._get_working_path()
backup_path = os.path.join(cwd, "backup")
if not filename:
filename = "%s_config.%s" % (
task_vars["inventory_hostname"],
tstamp,
)
dest = os.path.join(backup_path, filename)
if not os.path.exists(backup_path):
os.makedirs(backup_path)
changed = False
# Do not overwrite the destination if the contents match.
if not os.path.exists(dest) or checksum(dest) != checksum_s(content):
try:
with open(dest, "w") as output_file:
output_file.write(content)
except Exception as exc:
result["failed"] = True
result["msg"] = "Could not write to destination file %s: %s" % (
dest,
to_text(exc),
)
return
changed = True
result["backup_path"] = dest
result["changed"] = changed
result["date"], result["time"] = tstamp.split("@")
if not (backup_options and backup_options.get("filename")):
result["filename"] = os.path.basename(result["backup_path"])
result["shortname"] = os.path.splitext(result["backup_path"])[0]
def _get_working_path(self):
cwd = self._loader.get_basedir()
if self._task._role is not None:
cwd = self._task._role._role_path
return cwd
def _handle_src_option(self, convert_data=True):
src = self._task.args.get("src")
working_path = self._get_working_path()
if os.path.isabs(src) or urlsplit("src").scheme:
source = src
else:
source = self._loader.path_dwim_relative(working_path, "templates", src)
if not source:
source = self._loader.path_dwim_relative(working_path, src)
if not os.path.exists(source):
raise AnsibleError("path specified in src not found")
try:
with open(source, "r") as f:
template_data = to_text(f.read())
except IOError as e:
raise AnsibleError(
"unable to load src file {0}, I/O error({1}): {2}".format(
source, e.errno, e.strerror
)
)
# Create a template search path in the following order:
# [working_path, self_role_path, dependent_role_paths, dirname(source)]
searchpath = [working_path]
if self._task._role is not None:
searchpath.append(self._task._role._role_path)
if hasattr(self._task, "_block:"):
dep_chain = self._task._block.get_dep_chain()
if dep_chain is not None:
for role in dep_chain:
searchpath.append(role._role_path)
searchpath.append(os.path.dirname(source))
self._templar.environment.loader.searchpath = searchpath
self._task.args["src"] = self._templar.template(template_data)
def _get_network_os(self, task_vars):
if "network_os" in self._task.args and self._task.args["network_os"]:
display.vvvv("Getting network OS from task argument")
network_os = self._task.args["network_os"]
elif self._play_context.network_os:
display.vvvv("Getting network OS from inventory")
network_os = self._play_context.network_os
elif (
"network_os" in task_vars.get("ansible_facts", {})
and task_vars["ansible_facts"]["network_os"]
):
display.vvvv("Getting network OS from fact")
network_os = task_vars["ansible_facts"]["network_os"]
else:
raise AnsibleError("ansible_network_os must be specified on this host")
return network_os
def _check_dexec_eligibility(self, host):
"""Check if current python and task are eligble"""
dexec = self.get_connection_option("import_modules")
# log early about dexec
if dexec:
display.vvvv("{prefix} enabled".format(prefix=DEXEC_PREFIX), host)
# disable dexec when not PY3
if not PY3:
dexec = False
display.vvvv(
"{prefix} disabled for when not Python 3".format(prefix=DEXEC_PREFIX),
host=host,
)
# disable dexec when running async
if self._task.async_val:
dexec = False
display.vvvv(
"{prefix} disabled for a task using async".format(prefix=DEXEC_PREFIX),
host=host,
)
else:
display.vvvv("{prefix} disabled".format(prefix=DEXEC_PREFIX), host)
display.vvvv(
"{prefix} module execution time may be extended".format(prefix=DEXEC_PREFIX),
host,
)
return dexec
def _find_load_module(self):
"""Use the task action to find a module
and import it.
:return filename: The module's filename
:rtype filename: str
:return module: The loaded module file
:rtype module: module
"""
import importlib
mloadr = self._shared_loader_obj.module_loader
# 2.10
try:
context = mloadr.find_plugin_with_context(
self._task.action, collection_list=self._task.collections
)
filename = context.plugin_resolved_path
module = importlib.import_module(context.plugin_resolved_name)
# 2.9
except AttributeError:
fullname, filename = mloadr.find_plugin_with_name(
self._task.action, collection_list=self._task.collections
)
module = importlib.import_module(fullname)
return filename, module
def _patch_update_module(self, module, task_vars):
"""Update a module instance, replacing it's AnsibleModule
with one that doesn't load params
:param module: An loaded module
:type module: A module file that was loaded
:param task_vars: The vars provided to the task
:type task_vars: dict
"""
import copy
from ansible.module_utils.basic import AnsibleModule as _AnsibleModule
# build an AnsibleModule that doesn't load params
class PatchedAnsibleModule(_AnsibleModule):
def _load_params(self):
pass
# update the task args w/ all the magic vars
self._update_module_args(self._task.action, self._task.args, task_vars)
# set the params of the ansible module cause we're not using stdin
# use a copy so the module doesn't change the original task args
PatchedAnsibleModule.params = copy.deepcopy(self._task.args)
# give the module our revised AnsibleModule
module.AnsibleModule = PatchedAnsibleModule
def _exec_module(self, module):
"""exec the module's main() since modules
print their result, we need to replace stdout
with a buffer. If main() fails, we assume that as stderr
Once we collect stdout/stderr, use our super to json load
it or handle a traceback
:param module: An loaded module
:type module: A module file that was loaded
:return module_result: The result of the module
:rtype module_result: dict
"""
import io
import sys
from ansible.module_utils._text import to_native
from ansible.vars.clean import remove_internal_keys
# preserve previous stdout, replace with buffer
sys_stdout = sys.stdout
sys.stdout = io.StringIO()
stdout = ""
stderr = ""
# run the module, catch the SystemExit so we continue
try:
module.main()
except SystemExit:
# module exited cleanly
stdout = sys.stdout.getvalue()
except Exception as exc:
# dirty module or connection traceback
stderr = to_native(exc)
# restore stdout & stderr
sys.stdout = sys_stdout
# parse the response
dict_out = {
"stdout": stdout,
"stdout_lines": stdout.splitlines(),
"stderr": stderr,
"stderr_lines": stderr.splitlines(),
}
data = self._parse_returned_data(dict_out)
# Clean up the response like action _execute_module
remove_internal_keys(data)
# split stdout/stderr into lines if needed
if "stdout" in data and "stdout_lines" not in data:
# if the value is 'False', a default won't catch it.
txt = data.get("stdout", None) or ""
data["stdout_lines"] = txt.splitlines()
if "stderr" in data and "stderr_lines" not in data:
# if the value is 'False', a default won't catch it.
txt = data.get("stderr", None) or ""
data["stderr_lines"] = txt.splitlines()
return data
def _sanitize_contents(self, contents, filters):
"""remove lines from contents that match
regexes specified in the `filters` list
"""
for x in filters:
contents = re.sub(x, "", contents)
return contents.strip()

View File

@@ -0,0 +1,246 @@
#
# Copyright 2021 Red Hat Inc.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import copy
import glob
import os
from importlib import import_module
try:
import yaml
# use C version if possible for speedup
try:
from yaml import CSafeLoader as SafeLoader
except ImportError:
from yaml import SafeLoader
HAS_YAML = True
except ImportError:
HAS_YAML = False
from ansible.errors import AnsibleActionFail, AnsibleError
from ansible.module_utils._text import to_text
from ansible.utils.display import Display
from ansible_collections.ansible.netcommon.plugins.action.network import (
ActionModule as ActionNetworkModule,
)
display = Display()
class RunMode:
RM_LIST = 0 # get list of supported resource modules for given os_name
RM_GET = 1 # get resource module facts for given host
RM_CONFIG = 1 # push resource module configuration
class ActionModule(ActionNetworkModule):
def run(self, task_vars=None):
run_mode = None
self._task_vars = task_vars
self._rm_play_context = copy.deepcopy(self._play_context)
self._os_name = self._task.args.get("os_name") or self._get_os_name()
if not self._os_name:
return {"error": "either value of 'os_name' or 'ansible_network_os' should be set"}
if len(self._os_name.split(".")) != 3:
msg = (
"OS value name should a fully qualified collection name in the format"
" <org-name>.<collection-name>.<plugin-name>"
)
return {"error": msg}
self._rm_play_context.network_os = self._os_name
self._name = self._task.args.get("name")
self._config = self._task.args.get("config")
self._running_config = self._task.args.get("running_config")
self._state = self._task.args.get("state")
run_mode = self._get_run_mode()
result = {}
if run_mode == RunMode.RM_LIST:
result = self._list_resource_modules()
elif run_mode in [RunMode.RM_GET, RunMode.RM_CONFIG]:
try:
result = self._run_resource_module()
except AnsibleError as exc:
# handle short name redirection not working for ansible-2.9
if "was not found" in to_text(exc):
result = self._run_resource_module(prefix_os_name=True)
else:
raise
result.update(
{
"ansible_network_os": self._task_vars.get("ansible_network_os"),
"ansible_connection": self._task_vars.get("ansible_connection"),
}
)
return result
def _run_resource_module(self, prefix_os_name=False):
new_task = self._task.copy()
self._module = self._get_resource_module(prefix_os_name=prefix_os_name)
if not self._module:
msg = "Could not find resource module '%s' for os name '%s'" % (
self._name,
self._os_name,
)
raise AnsibleActionFail(msg)
new_task.action = self._module
action = self._shared_loader_obj.action_loader.get(
self._rm_play_context.network_os,
task=new_task,
connection=self._connection,
play_context=self._rm_play_context,
loader=self._loader,
templar=self._templar,
shared_loader_obj=self._shared_loader_obj,
)
display.vvvv("Running resource module %s" % self._module)
for option in ["os_name", "name"]:
if option in new_task.args:
new_task.args.pop(option)
result = action.run(task_vars=self._task_vars)
result.update({"resource_module_name": self._module})
return result
def _get_resource_module(self, prefix_os_name=False):
if "." in self._name:
if len(self._name.split(".")) != 3:
msg = (
"name should a fully qualified collection name in the format"
" <org-name>.<collection-name>.<resource-module-name>"
)
raise AnsibleActionFail(msg)
fqcn_module_name = self._name
else:
if prefix_os_name:
module_name = self._os_name.split(".")[1] + "_" + self._name
else:
module_name = self._name
fqcn_module_name = ".".join(self._os_name.split(".")[:2] + [module_name])
return fqcn_module_name
def _get_os_name(self):
os_name = None
if "network_os" in self._task.args and self._task.args["network_os"]:
display.vvvv("Getting OS name from task argument")
os_name = self._task.args["network_os"]
elif self._play_context.network_os:
display.vvvv("Getting OS name from inventory")
os_name = self._play_context.network_os
elif (
"network_os" in self._task_vars.get("ansible_facts", {})
and self._task_vars["ansible_facts"]["network_os"]
):
display.vvvv("Getting OS name from fact")
os_name = self._task_vars["ansible_facts"]["network_os"]
return os_name
def _is_resource_module(self, docs):
doc_obj = yaml.load(docs, SafeLoader)
if "config" in doc_obj["options"] and "state" in doc_obj["options"]:
return True
def _get_run_mode(self):
error_msg = None
if self._config or self._running_config:
if not self._name:
error_msg = "'name' is required if 'config' option is set"
if not self._state:
error_msg = "'state' is required if 'config' option is set"
run_mode = RunMode.RM_CONFIG
elif self._state:
if not self._name:
error_msg = "'name' is required if 'state' option is set"
run_mode = RunMode.RM_GET
elif self._name:
if not any([self._config, self._running_config, self._state]):
error_msg = (
"If 'name' is set atleast one of 'config', "
"'running_config' or 'state' is required"
)
else:
run_mode = RunMode.RM_LIST
if error_msg:
raise AnsibleActionFail(error_msg)
return run_mode
def _list_resource_modules(self):
result = {}
resource_modules = []
self._cref = dict(zip(["corg", "cname", "plugin"], self._os_name.split(".")))
fact_modulelib = "ansible_collections.{corg}.{cname}.plugins.module_utils.network.{plugin}.facts.facts".format(
corg=self._cref["corg"],
cname=self._cref["cname"],
plugin=self._cref["plugin"],
)
try:
display.vvvv("fetching facts list from path %s" % (fact_modulelib))
facts_resource_subset = getattr(import_module(fact_modulelib), "FACT_RESOURCE_SUBSETS")
resource_modules = sorted(facts_resource_subset.keys())
except ModuleNotFoundError:
display.vvvv("'%s' is not defined" % (fact_modulelib))
except AttributeError:
display.vvvv("'FACT_RESOURCE_SUBSETS is not defined in '%s'" % (fact_modulelib))
# parse module docs to check for 'config' and 'state' options to identify it as resource module
if not resource_modules:
modulelib = "ansible_collections.{corg}.{cname}.plugins.modules".format(
corg=self._cref["corg"], cname=self._cref["cname"]
)
module_dir_path = os.path.dirname(import_module(modulelib).__file__)
module_paths = glob.glob(
"{module_dir_path}/[!_]*.py".format(module_dir_path=module_dir_path)
)
for module_path in module_paths:
module_name = os.path.basename(module_path).split(".")[0]
docs = None
try:
display.vvvv("reading 'DOCUMENTATION' from path %s" % (module_path))
docs = getattr(
import_module("%s.%s" % (modulelib, module_name)),
"DOCUMENTATION",
)
except ModuleNotFoundError:
display.vvvv("'%s' is not defined" % (fact_modulelib))
except AttributeError:
display.vvvv("'DOCUMENTATION is not defined in '%s'" % (fact_modulelib))
if docs:
if self._is_resource_module(docs):
resource_modules.append(module_name.split("_", 1)[1])
else:
display.vvvvv(
"module in path '%s' is not a resource module" % (module_path)
)
result.update({"modules": sorted(resource_modules)})
return result

View File

@@ -0,0 +1,118 @@
# (c) 2017, Ansible Project
#
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from time import sleep
from ansible.module_utils._text import to_bytes, to_text
from ansible.module_utils.six import text_type
from ansible.plugins.action import ActionBase
from ansible.utils.display import Display
from ansible_collections.ansible.netcommon.plugins.plugin_utils.compat import telnetlib
display = Display()
class ActionModule(ActionBase):
TRANSFERS_FILES = False
def run(self, tmp=None, task_vars=None):
if self._task.environment and any(self._task.environment):
self._display.warning("The telnet task does not support the environment keyword")
result = super(ActionModule, self).run(tmp, task_vars)
del tmp # tmp no longer has any effect
if self._play_context.check_mode:
# in --check mode, always skip this module execution
result["skipped"] = True
result["msg"] = "The telnet task does not support check mode"
else:
result["changed"] = True
result["failed"] = False
host = to_text(self._task.args.get("host", self._play_context.remote_addr))
user = to_text(self._task.args.get("user", self._play_context.remote_user))
password = to_text(self._task.args.get("password", self._play_context.password))
# FIXME, default to play_context?
port = int(self._task.args.get("port", 23))
timeout = int(self._task.args.get("timeout", 120))
pause = int(self._task.args.get("pause", 1))
send_newline = self._task.args.get("send_newline", False)
clrf = self._task.args.get("clrf", False)
login_prompt = to_text(self._task.args.get("login_prompt", "login: "))
password_prompt = to_text(self._task.args.get("password_prompt", "Password: "))
prompts = self._task.args.get("prompts", ["\\$ "])
commands = self._task.args.get("command") or self._task.args.get("commands")
if clrf:
line_ending = "\r\n"
else:
line_ending = "\n"
if isinstance(commands, text_type):
commands = commands.split(",")
if isinstance(commands, list) and commands:
self.tn = telnetlib.Telnet(host, port, timeout)
self.output = bytes()
try:
if send_newline:
self.tn.write(to_bytes(line_ending))
self.await_prompts([login_prompt], timeout)
display.vvvvv(">>>user: %s" % user)
self.tn.write(to_bytes(user + line_ending))
if password:
self.await_prompts([password_prompt], timeout)
display.vvvvv(">>>password: %s" % password)
self.tn.write(to_bytes(password + line_ending))
self.await_prompts(prompts, timeout)
for cmd in commands:
display.vvvvv(">>> %s" % cmd)
self.tn.write(to_bytes(cmd + line_ending))
self.await_prompts(prompts, timeout)
display.vvvvv("<<< %s" % cmd)
sleep(pause)
self.tn.write(to_bytes("exit" + line_ending))
except EOFError as e:
result["failed"] = True
result["msg"] = "Telnet action failed: %s" % to_text(e)
except TimeoutError as e:
result["failed"] = True
result["msg"] = "Telnet timed out trying to find prompt(s): '%s'" % to_text(e)
finally:
if self.tn:
self.tn.close()
result["stdout"] = to_text(self.output)
result["stdout_lines"] = self.output.splitlines(True)
else:
result["failed"] = True
result["msg"] = "Telnet requires a command to execute"
return result
def await_prompts(self, prompts, timeout):
index, match, out = self.tn.expect(list(map(to_bytes, prompts)), timeout=timeout)
self.output += out
if not match:
raise TimeoutError(prompts)
return index

View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2018, Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
author:
- Ansible Networking Team (@ansible-network)
name: enable
short_description: Switch to elevated permissions on a network device
description:
- This become plugins allows elevated permissions on a remote network device.
version_added: 1.0.0
options:
become_pass:
description: password
ini:
- section: enable_become_plugin
key: password
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_enable_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_ENABLE_PASS
notes:
- enable is really implemented in the network connection handler and as such can only
be used with network connections.
- This plugin ignores the 'become_exe' and 'become_user' settings as it uses an API
and not an executable.
"""
from ansible.plugins.become import BecomeBase
class BecomeModule(BecomeBase):
name = "ansible.netcommon.enable"
def build_become_command(self, cmd, shell):
# enable is implemented inside the network connection plugins
return cmd

View File

@@ -0,0 +1,49 @@
#
# (c) 2020 Red Hat Inc.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
short_description: RAM backed, non persistent cache.
description:
- RAM backed cache that is not persistent.
- Tailored for networking use case.
version_added: 2.0.0
author:
- Ansible Networking Team (@ansible-network)
name: memory
"""
from ansible.plugins import AnsiblePlugin
class CacheModule(AnsiblePlugin):
def __init__(self, *args, **kwargs):
super(CacheModule, self).__init__(*args, **kwargs)
self._cache = {}
def get(self, key):
return self._cache.get(key)
def set(self, key, value):
self._cache[key] = value
def keys(self):
return self._cache.keys()
def flush(self):
self._cache = {}
def lookup(self, key):
return self.get(key)
def populate(self, key, value):
self.set(key, value)
def invalidate(self):
self.flush()

View File

@@ -0,0 +1,67 @@
# (c) 2023 Red Hat Inc.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
author: Ansible Networking Team (@ansible-network)
name: default
short_description: General purpose cliconf plugin for new platforms
description:
- This plugin attemts to provide low level abstraction apis for sending and receiving CLI
commands from arbitrary network devices.
version_added: 5.2.0
"""
import json
from ansible.errors import AnsibleConnectionFailure
from ansible_collections.ansible.netcommon.plugins.plugin_utils.cliconf_base import CliconfBase
class Cliconf(CliconfBase):
def __init__(self, *args, **kwargs):
super(Cliconf, self).__init__(*args, **kwargs)
self._device_info = {}
def get_device_info(self):
if not self._device_info:
device_info = {}
device_info["network_os"] = "default"
self._device_info = device_info
return self._device_info
def get_config(self, flags=None, format=None):
network_os = self.get_device_info()["network_os"]
raise AnsibleConnectionFailure("get_config is not supported by network_os %s" % network_os)
def edit_config(self, candidate=None, commit=True, replace=None, comment=None):
network_os = self.get_device_info()["network_os"]
raise AnsibleConnectionFailure("edit_config is not supported by network_os %s" % network_os)
def get_capabilities(self):
result = super(Cliconf, self).get_capabilities()
result["device_operations"] = self.get_device_operations()
return json.dumps(result)
def get_device_operations(self):
return {
"supports_diff_replace": False,
"supports_commit": False,
"supports_rollback": False,
"supports_defaults": False,
"supports_onbox_diff": False,
"supports_commit_comment": False,
"supports_multiline_delimiter": False,
"supports_diff_match": False,
"supports_diff_ignore_lines": False,
"supports_generate_diff": False,
"supports_replace": False,
}

View File

@@ -0,0 +1,278 @@
# (c) 2022 Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
author:
- Ansible Networking Team (@ansible-network)
name: grpc
short_description: Provides a persistent connection using the gRPC protocol
description:
- This connection plugin provides a connection to remote devices over gRPC and
is typically used with devices for sending and receiving RPC calls
over gRPC framework.
- Note this connection plugin requires the grpcio python library to be installed on the
local Ansible controller.
version_added: "3.1.0"
requirements:
- grpcio
- protobuf
extends_documentation_fragment:
- ansible.netcommon.connection_persistent
options:
host:
description:
- Specifies the remote device FQDN or IP address to establish the gRPC
connection to.
default: inventory_hostname
type: string
vars:
- name: ansible_host
port:
type: int
description:
- Specifies the port on the remote device that listens for connections
when establishing the gRPC connection. If None only the C(host) part will
be used.
ini:
- section: defaults
key: remote_port
env:
- name: ANSIBLE_REMOTE_PORT
vars:
- name: ansible_port
network_os:
description:
- Configures the device platform network operating system. This value is
used to load a device specific grpc plugin to communicate with the remote
device.
type: string
vars:
- name: ansible_network_os
remote_user:
description:
- The username used to authenticate to the remote device when the gRPC
connection is first established. If the remote_user is not specified,
the connection will use the username of the logged in user.
- Can be configured from the CLI via the C(--user) or C(-u) options.
type: string
ini:
- section: defaults
key: remote_user
env:
- name: ANSIBLE_REMOTE_USER
vars:
- name: ansible_user
password:
description:
- Configures the user password used to authenticate to the remote device
when first establishing the gRPC connection.
type: string
vars:
- name: ansible_password
- name: ansible_ssh_pass
private_key_file:
description:
- The PEM encoded private key file used to authenticate to the
remote device when first establishing the grpc connection.
type: string
ini:
- section: grpc_connection
key: private_key_file
env:
- name: ANSIBLE_PRIVATE_KEY_FILE
vars:
- name: ansible_private_key_file
root_certificates_file:
description:
- The PEM encoded root certificate file used to create a SSL-enabled
channel, if the value is None it reads the root certificates from
a default location chosen by gRPC at runtime.
type: string
ini:
- section: grpc_connection
key: root_certificates_file
env:
- name: ANSIBLE_ROOT_CERTIFICATES_FILE
vars:
- name: ansible_root_certificates_file
certificate_chain_file:
description:
- The PEM encoded certificate chain file used to create a SSL-enabled
channel. If the value is None, no certificate chain is used.
type: string
ini:
- section: grpc_connection
key: certificate_chain_file
env:
- name: ANSIBLE_CERTIFICATE_CHAIN_FILE
vars:
- name: ansible_certificate_chain_file
ssl_target_name_override:
description:
- The option overrides SSL target name used for SSL host name checking.
The name used for SSL host name checking will be the target parameter
(assuming that the secure channel is an SSL channel). If this parameter is
specified and the underlying is not an SSL channel, it will just be ignored.
type: string
ini:
- section: grpc_connection
key: ssl_target_name_override
env:
- name: ANSIBLE_GPRC_SSL_TARGET_NAME_OVERRIDE
vars:
- name: ansible_grpc_ssl_target_name_override
grpc_type:
description:
- This option indicates the grpc type and it can be used
in place of network_os. (example cisco.iosxr.iosxr)
default: False
ini:
- section: grpc_connection
key: type
env:
- name: ANSIBLE_GRPC_CONNECTION_TYPE
vars:
- name: ansible_grpc_connection_type
"""
from importlib import import_module
from ansible.errors import AnsibleConnectionFailure, AnsibleError
from ansible.plugins.connection import NetworkConnectionBase
try:
from grpc import insecure_channel, secure_channel, ssl_channel_credentials
from grpc.beta import implementations
HAS_GRPC = True
except ImportError:
HAS_GRPC = False
try:
from google import protobuf # noqa: F401 # pylint: disable=unused-import
HAS_PROTOBUF = True
except ImportError:
HAS_PROTOBUF = False
class Connection(NetworkConnectionBase):
"""GRPC connections"""
transport = "ansible.netcommon.grpc"
has_pipelining = False
def __init__(self, play_context, new_stdin, *args, **kwargs):
super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
grpc_type = self._network_os or self.get_option("grpc_type")
if grpc_type:
if not HAS_PROTOBUF:
raise AnsibleError(
"protobuf is required to use the grpc connection type. Please run 'pip install protobuf'"
)
if not self._network_os:
self._network_os = grpc_type
cref = dict(zip(["corg", "cname", "plugin"], grpc_type.split(".")))
grpclib = "ansible_collections.{corg}.{cname}.plugins.sub_plugins.grpc.{plugin}".format(
**cref
)
grpccls = getattr(import_module(grpclib), "Grpc")
grpc_obj = grpccls(self)
if grpc_obj:
self._sub_plugin = {
"type": "grpc",
"name": grpc_type,
"obj": grpc_obj,
}
self.queue_message("log", "loaded gRPC plugin for type %s" % grpc_type)
self.queue_message("log", "grpc type is set to %s" % grpc_type)
else:
raise AnsibleConnectionFailure(
"unable to load API plugin for network_os %s" % grpc_type
)
else:
raise AnsibleConnectionFailure(
"Unable to automatically determine gRPC implementation type."
" Please manually configure ansible_network_os value or grpc_type configuration for this host",
)
def _connect(self):
"""
Create GRPC connection to target host
:return: None
"""
if not HAS_GRPC:
raise AnsibleError(
"grpcio is required to use the gRPC connection type. Please run 'pip install grpcio'"
)
host = self.get_option("host")
host = self._play_context.remote_addr
if self.connected:
self.queue_message("log", "gRPC connection to host %s already exist" % host)
return
port = self.get_option("port")
self._target = host if port is None else "%s:%d" % (host, port)
self._timeout = self.get_option("persistent_command_timeout")
self._login_credentials = [
("username", self.get_option("remote_user")),
("password", self.get_option("password")),
]
ssl_target_name_override = self.get_option("ssl_target_name_override")
if ssl_target_name_override:
self._channel_options = [
("grpc.ssl_target_name_override", ssl_target_name_override),
]
else:
self._channel_options = None
certs = {}
private_key_file = self.get_option("private_key_file")
root_certificates_file = self.get_option("root_certificates_file")
certificate_chain_file = self.get_option("certificate_chain_file")
try:
if root_certificates_file:
with open(root_certificates_file, "rb") as f:
certs["root_certificates"] = f.read()
if private_key_file:
with open(private_key_file, "rb") as f:
certs["private_key"] = f.read()
if certificate_chain_file:
with open(certificate_chain_file, "rb") as f:
certs["certificate_chain"] = f.read()
except Exception as e:
raise AnsibleConnectionFailure("Failed to read certificate keys: %s" % e)
if certs:
creds = ssl_channel_credentials(**certs)
channel = secure_channel(self._target, creds, options=self._channel_options)
else:
channel = insecure_channel(self._target, options=self._channel_options)
self.queue_message(
"vvv",
"ESTABLISH GRPC CONNECTION FOR USER: %s on PORT %s TO %s"
% (self.get_option("remote_user"), port, host),
)
self._channel = implementations.Channel(channel)
self.queue_message("vvvv", "grpc connection has completed successfully")
self._connected = True
def close(self):
"""
Close the active session to the device
:return: None
"""
if self._connected:
self.queue_message("vvvv", "closing gRPC connection to target host")
self._channel.close()
super(Connection, self).close()

View File

@@ -0,0 +1,386 @@
# (c) 2018 Red Hat Inc.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
author:
- Ansible Networking Team (@ansible-network)
name: httpapi
short_description: Use httpapi to run command on network appliances
description:
- This connection plugin provides a connection to remote devices over a HTTP(S)-based
api.
version_added: 1.0.0
extends_documentation_fragment:
- ansible.netcommon.connection_persistent
options:
host:
description:
- Specifies the remote device FQDN or IP address to establish the HTTP(S) connection
to.
default: inventory_hostname
type: string
vars:
- name: inventory_hostname
- name: ansible_host
port:
type: int
description:
- Specifies the port on the remote device that listens for connections when establishing
the HTTP(S) connection.
- When unspecified, will pick 80 or 443 based on the value of use_ssl.
ini:
- section: defaults
key: remote_port
env:
- name: ANSIBLE_REMOTE_PORT
vars:
- name: ansible_httpapi_port
network_os:
description:
- Configures the device platform network operating system. This value is used
to load the correct httpapi plugin to communicate with the remote device
type: string
vars:
- name: ansible_network_os
remote_user:
description:
- The username used to authenticate to the remote device when the API connection
is first established. If the remote_user is not specified, the connection will
use the username of the logged in user.
- Can be configured from the CLI via the C(--user) or C(-u) options.
type: string
ini:
- section: defaults
key: remote_user
env:
- name: ANSIBLE_REMOTE_USER
vars:
- name: ansible_user
password:
description:
- Configures the user password used to authenticate to the remote device when
needed for the device API.
type: string
vars:
- name: ansible_password
- name: ansible_httpapi_pass
- name: ansible_httpapi_password
session_key:
type: dict
description:
- Configures the session key to be used to authenticate to the remote device when
needed for the device API.
- This should contain a dictionary representing the key name and value for the
token.
- When specified, I(password) is ignored.
vars:
- name: ansible_httpapi_session_key
ca_path:
description:
- Path to CA cert bundle to use.
type: path
version_added: 5.2.0
vars:
- name: ansible_httpapi_ca_path
client_cert:
description:
- PEM formatted certificate chain file to be used for SSL client
authentication. This file can also include the key as well, and if the key
is included, I(client_key) is not required
version_added: 5.2.0
vars:
- name: ansible_httpapi_client_cert
client_key:
description:
- PEM formatted file that contains the private key to be used for SSL client
authentication. If I(client_cert) contains both the certificate and key,
this option is not required.
version_added: 5.2.0
vars:
- name: ansible_httpapi_client_key
http_agent:
description: User-Agent to use in the request.
version_added: 5.2.0
vars:
- name: ansible_httpapi_http_agent
use_ssl:
type: boolean
description:
- Whether to connect using SSL (HTTPS) or not (HTTP).
default: false
vars:
- name: ansible_httpapi_use_ssl
validate_certs:
type: boolean
description:
- Whether to validate SSL certificates
default: true
vars:
- name: ansible_httpapi_validate_certs
use_proxy:
type: boolean
description:
- Whether to use https_proxy for requests.
default: true
vars:
- name: ansible_httpapi_use_proxy
ciphers:
description:
- SSL/TLS Ciphers to use for requests
- 'When a list is provided, all ciphers are joined in order with C(:)'
- See the L(OpenSSL Cipher List Format,https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html#CIPHER-LIST-FORMAT)
for more details.
- The available ciphers is dependent on the Python and OpenSSL/LibreSSL versions.
- This option will have no effect on ansible-core<2.14 but a warning will be emitted.
version_added: 5.0.0
type: list
elements: string
vars:
- name: ansible_httpapi_ciphers
become:
type: boolean
description:
- The become option will instruct the CLI session to attempt privilege escalation
on platforms that support it. Normally this means transitioning from user mode
to C(enable) mode in the CLI session. If become is set to True and the remote
device does not support privilege escalation or the privilege has already been
elevated, then this option is silently ignored.
- Can be configured from the CLI via the C(--become) or C(-b) options.
default: false
ini:
- section: privilege_escalation
key: become
env:
- name: ANSIBLE_BECOME
vars:
- name: ansible_become
become_method:
description:
- This option allows the become method to be specified in for handling privilege
escalation. Typically the become_method value is set to C(enable) but could
be defined as other values.
default: sudo
type: string
ini:
- section: privilege_escalation
key: become_method
env:
- name: ANSIBLE_BECOME_METHOD
vars:
- name: ansible_become_method
platform_type:
description:
- Set type of platform.
type: string
env:
- name: ANSIBLE_PLATFORM_TYPE
vars:
- name: ansible_platform_type
"""
from io import BytesIO
from ansible.errors import AnsibleConnectionFailure
from ansible.module_utils._text import to_bytes
from ansible.module_utils.six import PY3
from ansible.module_utils.six.moves import cPickle
from ansible.module_utils.six.moves.urllib.error import HTTPError, URLError
from ansible.module_utils.urls import open_url
from ansible.playbook.play_context import PlayContext
from ansible.plugins.connection import ensure_connect
from ansible.plugins.loader import httpapi_loader
from ansible.release import __version__ as ANSIBLE_CORE_VERSION
from ansible_collections.ansible.netcommon.plugins.plugin_utils.connection_base import (
NetworkConnectionBase,
)
from ansible_collections.ansible.netcommon.plugins.plugin_utils.version import Version
class Connection(NetworkConnectionBase):
"""Network API connection"""
transport = "ansible.netcommon.httpapi"
has_pipelining = True
def __init__(self, play_context, new_stdin, *args, **kwargs):
super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
self._auth = None
if self._network_os:
self.load_platform_plugins(self._network_os)
def load_platform_plugins(self, platform_type=None):
platform_type = platform_type or self.get_option("platform_type")
if platform_type:
self.httpapi = httpapi_loader.get(platform_type, self)
if self.httpapi:
self._sub_plugin = {
"type": "httpapi",
"name": self.httpapi._load_name,
"obj": self.httpapi,
}
self.queue_message(
"vvvv",
"loaded API plugin %s from path %s for platform type %s"
% (
self.httpapi._load_name,
self.httpapi._original_path,
platform_type,
),
)
else:
raise AnsibleConnectionFailure(
"unable to load API plugin for platform type %s" % platform_type
)
else:
raise AnsibleConnectionFailure(
"Unable to automatically determine host platform type. Please "
"manually configure platform_type value for this host"
)
self.queue_message("log", "platform_type is set to %s" % platform_type)
@property
def _url(self):
protocol = "https" if self.get_option("use_ssl") else "http"
host = self.get_option("host")
port = self.get_option("port") or (443 if protocol == "https" else 80)
return "%s://%s:%s" % (protocol, host, port)
def update_play_context(self, pc_data):
"""Updates the play context information for the connection"""
pc_data = to_bytes(pc_data)
if PY3:
pc_data = cPickle.loads(pc_data, encoding="bytes")
else:
pc_data = cPickle.loads(pc_data)
play_context = PlayContext()
play_context.deserialize(pc_data)
self.queue_message("vvvv", "updating play_context for connection")
if self._play_context.become ^ play_context.become:
self.set_become(play_context)
if play_context.become is True:
self.queue_message("vvvv", "authorizing connection")
else:
self.queue_message("vvvv", "deauthorizing connection")
self._play_context = play_context
def _connect(self):
if not self.connected:
self.queue_message(
"vvv",
"ESTABLISH HTTP(S) CONNECTFOR USER: %s TO %s"
% (self._play_context.remote_user, self._url),
)
self.httpapi.set_become(self._play_context)
self._connected = True
if self.get_option("session_key"):
self._auth = self.get_option("session_key")
else:
self.httpapi.login(self.get_option("remote_user"), self.get_option("password"))
def close(self):
"""
Close the active session to the device
"""
# only close the connection if its connected.
if self._connected:
self.queue_message("vvvv", "closing http(s) connection to device")
self.logout()
super(Connection, self).close()
@ensure_connect
def send(self, path, data, retries=None, **kwargs):
"""
Sends the command to the device over api
"""
url_kwargs = dict(
headers={},
use_proxy=self.get_option("use_proxy"),
timeout=self.get_option("persistent_command_timeout"),
validate_certs=self.get_option("validate_certs"),
http_agent=self.get_option("http_agent"),
client_cert=self.get_option("client_cert"),
client_key=self.get_option("client_key"),
ca_path=self.get_option("ca_path"),
)
url_kwargs.update(kwargs)
ciphers = self.get_option("ciphers")
if ciphers:
if Version(ANSIBLE_CORE_VERSION) >= Version("2.14.0"):
# Only insert "ciphers" kwarg for ansible-core versions >= 2.14.0.
url_kwargs["ciphers"] = ciphers
else:
# Emit warning when "ansible_httpapi_ciphers" is set but not supported
self.queue_message(
"warning",
"'ansible_httpapi_ciphers' option is unavailable on ansible-core<2.14",
)
if self._auth:
# Avoid modifying passed-in headers
headers = dict(kwargs.get("headers", {}))
headers.update(self._auth)
url_kwargs["headers"] = headers
else:
url_kwargs["force_basic_auth"] = True
url_kwargs["url_username"] = self.get_option("remote_user")
url_kwargs["url_password"] = self.get_option("password")
try:
url = self._url + path
self._log_messages(
"send url '%s' with data '%s' and kwargs '%s'" % (url, data, url_kwargs)
)
response = open_url(url, data=data, **url_kwargs)
except HTTPError as exc:
is_handled = self.handle_httperror(exc)
if is_handled is True:
if retries is None:
# The default behavior, retry indefinitely until timeout.
return self.send(path, data, **kwargs)
if retries:
return self.send(path, data, retries=retries - 1, **kwargs)
raise
if is_handled is False:
raise
response = is_handled
except URLError as exc:
raise AnsibleConnectionFailure(
"Could not connect to {0}: {1}".format(self._url + path, exc.reason)
)
response_buffer = BytesIO()
resp_data = response.read()
self._log_messages("received response: '%s'" % resp_data)
response_buffer.write(resp_data)
# Try to assign a new auth token if one is given
self._auth = self.update_auth(response, response_buffer) or self._auth
response_buffer.seek(0)
return response, response_buffer
def transport_test(self, connect_timeout):
"""This method enables wait_for_connection to work.
The sole purpose of this method is to raise an exception if the API's URL
cannot be reached. As such, it does not do anything except attempt to
request the root URL with no error handling.
"""
open_url(self._url, timeout=connect_timeout)

View File

@@ -0,0 +1,623 @@
# (c) 2020 Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
author:
- Ansible Networking Team (@ansible-network)
name: libssh
short_description: Run tasks using libssh for ssh connection
description:
- Use the ansible-pylibssh python bindings to connect to targets
- The python bindings use libssh C library (https://www.libssh.org/) to connect to targets
- This plugin borrows a lot of settings from the ssh plugin as they both cover the same protocol.
version_added: 1.1.0
options:
remote_addr:
description:
- Address of the remote target
type: string
default: inventory_hostname
vars:
- name: inventory_hostname
- name: ansible_host
- name: ansible_ssh_host
- name: ansible_libssh_host
remote_user:
description:
- User to login/authenticate as
- Can be set from the CLI via the C(--user) or C(-u) options.
type: string
vars:
- name: ansible_user
- name: ansible_ssh_user
- name: ansible_libssh_user
env:
- name: ANSIBLE_REMOTE_USER
- name: ANSIBLE_LIBSSH_REMOTE_USER
ini:
- section: defaults
key: remote_user
- section: libssh_connection
key: remote_user
password:
description:
- Secret used to either login the ssh server or as a passphrase for ssh keys that require it
- Can be set from the CLI via the C(--ask-pass) option.
type: string
vars:
- name: ansible_password
- name: ansible_ssh_pass
- name: ansible_ssh_password
- name: ansible_libssh_pass
- name: ansible_libssh_password
password_prompt:
description:
- Text to match when using keyboard-interactive authentication to determine if the prompt is
for the password.
- Requires ansible-pylibssh version >= 1.0.0
type: string
vars:
- name: ansible_libssh_password_prompt
version_added: 3.1.0
host_key_auto_add:
description: 'TODO: write it'
env: [{name: ANSIBLE_LIBSSH_HOST_KEY_AUTO_ADD}]
ini:
- {key: host_key_auto_add, section: libssh_connection}
type: boolean
look_for_keys:
default: True
description: 'TODO: write it'
env: [{name: ANSIBLE_LIBSSH_LOOK_FOR_KEYS}]
ini:
- {key: look_for_keys, section: libssh_connection}
type: boolean
proxy_command:
default: ''
description:
- Proxy information for running the connection via a jumphost.
- Also this plugin will scan 'ssh_args', 'ssh_extra_args' and 'ssh_common_args' from the 'ssh' plugin settings for proxy information if set.
type: string
env:
- name: ANSIBLE_LIBSSH_PROXY_COMMAND
ini:
- {key: proxy_command, section: libssh_connection}
vars:
- name: ansible_paramiko_proxy_command
- name: ansible_libssh_proxy_command
pty:
default: True
description: 'TODO: write it'
env:
- name: ANSIBLE_LIBSSH_PTY
ini:
- section: libssh_connection
key: pty
type: boolean
host_key_checking:
description: 'Set this to "False" if you want to avoid host key checking by the underlying tools Ansible uses to connect to the host'
type: boolean
default: True
env:
- name: ANSIBLE_HOST_KEY_CHECKING
- name: ANSIBLE_SSH_HOST_KEY_CHECKING
- name: ANSIBLE_LIBSSH_HOST_KEY_CHECKING
ini:
- section: defaults
key: host_key_checking
- section: libssh_connection
key: host_key_checking
vars:
- name: ansible_host_key_checking
- name: ansible_ssh_host_key_checking
- name: ansible_libssh_host_key_checking
use_persistent_connections:
description: 'Toggles the use of persistence for connections'
type: boolean
default: False
env:
- name: ANSIBLE_USE_PERSISTENT_CONNECTIONS
ini:
- section: defaults
key: use_persistent_connections
ssh_args:
version_added: 3.2.0
description:
- Arguments to pass to all ssh CLI tools.
- ProxyCommand is the only supported argument.
- This option is deprecated in favor of I(proxy_command) and will be removed
in a release after 2026-01-01.
type: string
ini:
- section: 'ssh_connection'
key: 'ssh_args'
env:
- name: ANSIBLE_SSH_ARGS
vars:
- name: ansible_ssh_args
cli:
- name: ssh_args
ssh_common_args:
version_added: 3.2.0
description:
- Common extra arguments for all ssh CLI tools.
- ProxyCommand is the only supported argument.
- This option is deprecated in favor of I(proxy_command) and will be removed
in a release after 2026-01-01.
type: string
ini:
- section: 'ssh_connection'
key: 'ssh_common_args'
env:
- name: ANSIBLE_SSH_COMMON_ARGS
vars:
- name: ansible_ssh_common_args
cli:
- name: ssh_common_args
ssh_extra_args:
version_added: 3.2.0
description:
- Extra arguments exclusive to the 'ssh' CLI tool.
- ProxyCommand is the only supported argument.
- This option is deprecated in favor of I(proxy_command) and will be removed
in a release after 2026-01-01.
type: string
vars:
- name: ansible_ssh_extra_args
env:
- name: ANSIBLE_SSH_EXTRA_ARGS
ini:
- key: ssh_extra_args
section: ssh_connection
cli:
- name: ssh_extra_args
config_file:
version_added: 5.1.0
description: Alternate SSH config file location
type: path
env:
- name: ANSIBLE_LIBSSH_CONFIG_FILE
ini:
- section: libssh_connection
key: config_file
vars:
- name: ansible_libssh_config_file
# TODO:
#timeout=self._play_context.timeout,
"""
import logging
import os
import re
import socket
import sys
from termios import TCIFLUSH, tcflush
from ansible.errors import AnsibleConnectionFailure, AnsibleError, AnsibleFileNotFound
from ansible.module_utils._text import to_bytes, to_native, to_text
from ansible.module_utils.basic import missing_required_lib
from ansible.module_utils.six.moves import input
from ansible.plugins.connection import ConnectionBase
from ansible.utils.display import Display
from ansible_collections.ansible.netcommon.plugins.plugin_utils.version import Version
display = Display()
try:
from pylibsshext import __version__ as PYLIBSSH_VERSION
from pylibsshext.errors import LibsshSCPException, LibsshSessionException
from pylibsshext.session import Session
HAS_PYLIBSSH = True
except ImportError:
HAS_PYLIBSSH = False
AUTHENTICITY_MSG = """
libssh: The authenticity of host '%s' can't be established due to '%s'.
The %s key fingerprint is %s.
Are you sure you want to continue connecting (yes/no)?
"""
# SSH Options Regex
SETTINGS_REGEX = re.compile(r"(\w+)(?:\s*=\s*|\s+)(.+)")
class MyAddPolicy(object):
"""
Based on AutoAddPolicy in paramiko so we can determine when keys are added
and also prompt for input.
Policy for automatically adding the hostname and new host key to the
local L{HostKeys} object, and saving it. This is used by L{SSHClient}.
"""
def __init__(self, new_stdin, connection):
self._new_stdin = new_stdin
self.connection = connection
self._options = connection._options
def missing_host_key(self, session, hostname, username, key_type, fingerprint, message):
if all(
(
self._options["host_key_checking"],
not self._options["host_key_auto_add"],
)
):
if (
self.connection.get_option("use_persistent_connections")
or self.connection.force_persistence
):
# don't print the prompt string since the user cannot respond
# to the question anyway
raise AnsibleError(
AUTHENTICITY_MSG.rsplit("\n", 2)[0] % (hostname, message, key_type, fingerprint)
)
self.connection.connection_lock()
old_stdin = sys.stdin
sys.stdin = self._new_stdin
# clear out any premature input on sys.stdin
tcflush(sys.stdin, TCIFLUSH)
inp = input(AUTHENTICITY_MSG % (hostname, message, key_type, fingerprint))
sys.stdin = old_stdin
self.connection.connection_unlock()
if inp not in ["yes", "y", ""]:
raise AnsibleError("host connection rejected by user")
session.hostkey_auto_add(username)
# host keys are actually saved in close() function below
# in order to control ordering.
# keep connection objects on a per host basis to avoid repeated attempts to reconnect
SSH_CONNECTION_CACHE = {}
SFTP_CONNECTION_CACHE = {}
class Connection(ConnectionBase):
"""SSH based connections with Paramiko"""
transport = "ansible.netcommon.libssh"
_log_channel = None
def _cache_key(self):
return "%s__%s__" % (
self._play_context.remote_addr,
self._play_context.remote_user,
)
def _connect(self):
cache_key = self._cache_key()
if cache_key in SSH_CONNECTION_CACHE:
self.ssh = SSH_CONNECTION_CACHE[cache_key]
else:
self.ssh = SSH_CONNECTION_CACHE[cache_key] = self._connect_uncached()
return self
def _set_log_channel(self, name):
self._log_channel = name
def _get_proxy_command(self, port=22):
proxy_command = None
# Parse ansible_ssh_common_args, specifically looking for ProxyCommand
ssh_args = [
self.get_option("ssh_extra_args") or "",
self.get_option("ssh_common_args") or "",
self.get_option("ssh_args") or "",
]
if any(ssh_args):
display.warning(
"The ssh_*_args options are deprecated and will be removed in a release after 2026-01-01. Please use the proxy_command option instead."
)
args = self._split_ssh_args(" ".join(ssh_args))
for i, arg in enumerate(args):
if arg.lower() == "proxycommand":
# _split_ssh_args split ProxyCommand from the command itself
proxy_command = args[i + 1]
else:
# ProxyCommand and the command itself are a single string
match = SETTINGS_REGEX.match(arg)
if match:
if match.group(1).lower() == "proxycommand":
proxy_command = match.group(2)
if proxy_command:
break
proxy_command = proxy_command or self.get_option("proxy_command")
if proxy_command:
replacers = {
"%h": self._play_context.remote_addr,
"%p": port,
"%r": self._play_context.remote_user,
}
for find, replace in replacers.items():
proxy_command = proxy_command.replace(find, str(replace))
return proxy_command
def _connect_uncached(self):
"""activates the connection object"""
if not HAS_PYLIBSSH:
raise AnsibleError(missing_required_lib("ansible-pylibssh"))
display.vvv(
"USING PYLIBSSH VERSION %s" % PYLIBSSH_VERSION,
host=self._play_context.remote_addr,
)
ssh_connect_kwargs = {}
remote_user = self.get_option("remote_user")
remote_addr = self.get_option("remote_addr")
port = self._play_context.port or 22
display.vvv(
"ESTABLISH LIBSSH CONNECTION FOR USER: %s on PORT %s TO %s"
% (remote_user, port, remote_addr),
host=remote_addr,
)
self.ssh = Session()
if self._play_context.verbosity > 3:
self.ssh.set_log_level(logging.INFO)
self.keyfile = os.path.expanduser("~/.ssh/known_hosts")
proxy_command = self._get_proxy_command(port)
try:
private_key = None
if self._play_context.private_key_file:
with open(os.path.expanduser(self._play_context.private_key_file)) as fp:
b_content = fp.read()
private_key = to_bytes(b_content, errors="surrogate_or_strict")
if proxy_command:
ssh_connect_kwargs["proxycommand"] = proxy_command
if self.get_option("config_file"):
ssh_connect_kwargs["config_file"] = self.get_option("config_file")
if self.get_option("password_prompt") and (Version(PYLIBSSH_VERSION) < "1.0.0"):
raise AnsibleError(
"Configuring password prompt is not supported in ansible-pylibssh version %s. "
"Please upgrade to ansible-pylibssh 1.0.0 or newer." % PYLIBSSH_VERSION
)
self.ssh.set_missing_host_key_policy(MyAddPolicy(self._new_stdin, self))
self.ssh.connect(
host=remote_addr.lower(),
user=remote_user,
look_for_keys=self.get_option("look_for_keys"),
host_key_checking=self.get_option("host_key_checking"),
password=self.get_option("password"),
password_prompt=self.get_option("password_prompt"),
private_key=private_key,
timeout=self._play_context.timeout,
port=port,
**ssh_connect_kwargs,
)
except LibsshSessionException as e:
msg = "ssh connection failed: " + to_text(e)
raise AnsibleConnectionFailure(msg)
except Exception as e:
raise AnsibleConnectionFailure(to_text(e))
display.vvv("ssh connection is OK: " + str(self.ssh))
return self.ssh
def exec_command(self, cmd, in_data=None, sudoable=True):
"""run a command on the remote host"""
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
if in_data:
raise AnsibleError(
"Internal Error: this module does not support optimized module pipelining"
)
bufsize = 4096
try:
self.chan = self.ssh.new_channel()
except Exception as e:
text_e = to_text(e)
msg = "Failed to open session"
if text_e:
msg += ": %s" % text_e
raise AnsibleConnectionFailure(to_native(msg))
# sudo usually requires a PTY (cf. requiretty option), therefore
# we give it one by default (pty=True in ansible.cfg), and we try
# to initialise from the calling environment when sudoable is enabled
if self.get_option("pty") and sudoable:
self.chan.request_shell()
display.vvv("EXEC %s" % cmd, host=self._play_context.remote_addr)
cmd = to_bytes(cmd, errors="surrogate_or_strict")
result = None
no_prompt_out = b""
no_prompt_err = b""
become_output = b""
out = b""
err = b""
try:
if self.become and self.become.expect_prompt():
passprompt = False
become_sucess = False
self.chan.sendall(cmd)
while not (become_sucess or passprompt):
display.debug("Waiting for Privilege Escalation input")
self.chan.poll(timeout=self._play_context.timeout)
chunk = self.chan.recv(bufsize)
display.debug("chunk is: %s" % chunk)
if not chunk:
if b"unknown user" in become_output:
n_become_user = to_native(
self.become.get_option(
"become_user",
playcontext=self._play_context,
)
)
raise AnsibleError("user %s does not exist" % n_become_user)
else:
break
# raise AnsibleError('ssh connection closed waiting for password prompt')
become_output += chunk
# need to check every line because we might get lectured
# and we might get the middle of a line in a chunk
for line in become_output.splitlines(True):
if self.become.check_success(line):
become_sucess = True
break
if self.become.check_password_prompt(line):
passprompt = True
break
if passprompt:
if self.become:
become_pass = self.become.get_option(
"become_pass", playcontext=self._play_context
)
self.chan.sendall(
to_bytes(become_pass, errors="surrogate_or_strict") + b"\n"
)
else:
raise AnsibleError("A password is required but none was supplied")
else:
no_prompt_out += become_output
no_prompt_err += become_output
else:
result = self.chan.exec_command(to_text(cmd, errors="surrogate_or_strict"))
except socket.timeout:
raise AnsibleError("ssh timed out waiting for privilege escalation.\n" + become_output)
if result:
rc = result.returncode
out = result.stdout
err = result.stderr
else:
rc = self.chan.get_channel_exit_status()
return rc, out, err
def put_file(self, in_path, out_path, proto="sftp"):
"""transfer a file from local to remote"""
super(Connection, self).put_file(in_path, out_path)
display.vvv(
"PUT %s TO %s" % (in_path, out_path),
host=self._play_context.remote_addr,
)
if not os.path.exists(to_bytes(in_path, errors="surrogate_or_strict")):
raise AnsibleFileNotFound("file or module does not exist: %s" % in_path)
if proto == "sftp":
try:
self.sftp = self.ssh.sftp()
except Exception as e:
raise AnsibleError("failed to open a SFTP connection (%s)" % e)
try:
self.sftp.put(
to_bytes(in_path, errors="surrogate_or_strict"),
to_bytes(out_path, errors="surrogate_or_strict"),
)
except IOError:
raise AnsibleError("failed to transfer file to %s" % out_path)
elif proto == "scp":
scp = self.ssh.scp()
try:
scp.put(in_path, out_path)
except LibsshSCPException as exc:
raise AnsibleError("Error transferring file to %s: %s" % (out_path, to_text(exc)))
else:
raise AnsibleError("Don't know how to transfer file over protocol %s" % proto)
def _connect_sftp(self):
cache_key = "%s__%s__" % (
self._play_context.remote_addr,
self._play_context.remote_user,
)
if cache_key in SFTP_CONNECTION_CACHE:
return SFTP_CONNECTION_CACHE[cache_key]
else:
result = SFTP_CONNECTION_CACHE[cache_key] = self._connect().ssh.sftp()
return result
def fetch_file(self, in_path, out_path, proto="sftp"):
"""save a remote file to the specified path"""
super(Connection, self).fetch_file(in_path, out_path)
display.vvv(
"FETCH %s TO %s" % (in_path, out_path),
host=self._play_context.remote_addr,
)
if proto == "sftp":
try:
self.sftp = self._connect_sftp()
except Exception as e:
raise AnsibleError("failed to open a SFTP connection (%s)" % to_native(e))
try:
self.sftp.get(
to_bytes(in_path, errors="surrogate_or_strict"),
to_bytes(out_path, errors="surrogate_or_strict"),
)
except IOError:
raise AnsibleError("failed to transfer file from %s" % in_path)
elif proto == "scp":
scp = self.ssh.scp()
try:
scp.get(out_path, in_path)
except LibsshSCPException as exc:
raise AnsibleError("Error transferring file from %s: %s" % (out_path, to_text(exc)))
else:
raise AnsibleError("Don't know how to transfer file over protocol %s" % proto)
def reset(self):
self.close()
self._connect()
def close(self):
"""terminate the connection"""
cache_key = self._cache_key()
SSH_CONNECTION_CACHE.pop(cache_key, None)
SFTP_CONNECTION_CACHE.pop(cache_key, None)
if hasattr(self, "sftp"):
if self.sftp is not None:
self.sftp.close()
if hasattr(self, "chan"):
if self.chan is not None:
self.chan.close()
self.ssh.close()
self._connected = False

View File

@@ -0,0 +1,435 @@
# (c) 2016 Red Hat Inc.
# (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
author:
- Ansible Networking Team (@ansible-network)
name: netconf
short_description: Provides a persistent connection using the netconf protocol
description:
- This connection plugin provides a connection to remote devices over the SSH NETCONF
subsystem. This connection plugin is typically used by network devices for sending
and receiving RPC calls over NETCONF.
- Note this connection plugin requires ncclient to be installed on the local Ansible
controller.
version_added: 1.0.0
requirements:
- ncclient
extends_documentation_fragment:
- ansible.netcommon.connection_persistent
options:
host:
description:
- Specifies the remote device FQDN or IP address to establish the SSH connection
to.
default: inventory_hostname
type: string
vars:
- name: inventory_hostname
- name: ansible_host
port:
type: int
description:
- Specifies the port on the remote device that listens for connections when establishing
the SSH connection.
default: 830
ini:
- section: defaults
key: remote_port
env:
- name: ANSIBLE_REMOTE_PORT
vars:
- name: ansible_port
network_os:
description:
- Configures the device platform network operating system. This value is used
to load a device specific netconf plugin. If this option is not configured
(or set to C(auto)), then Ansible will attempt to guess the correct network_os
to use. If it can not guess a network_os correctly it will use C(default).
type: string
vars:
- name: ansible_network_os
remote_user:
description:
- The username used to authenticate to the remote device when the SSH connection
is first established. If the remote_user is not specified, the connection will
use the username of the logged in user.
- Can be configured from the CLI via the C(--user) or C(-u) options.
type: string
ini:
- section: defaults
key: remote_user
env:
- name: ANSIBLE_REMOTE_USER
vars:
- name: ansible_user
password:
description:
- Configures the user password used to authenticate to the remote device when
first establishing the SSH connection.
type: string
vars:
- name: ansible_password
- name: ansible_ssh_pass
- name: ansible_ssh_password
- name: ansible_netconf_password
private_key_file:
description:
- The private SSH key or certificate file used to authenticate to the remote device
when first establishing the SSH connection.
type: string
ini:
- section: defaults
key: private_key_file
env:
- name: ANSIBLE_PRIVATE_KEY_FILE
vars:
- name: ansible_private_key_file
look_for_keys:
default: true
description:
- Enables looking for ssh keys in the usual locations for ssh keys (e.g. :file:`~/.ssh/id_*`).
env:
- name: ANSIBLE_PARAMIKO_LOOK_FOR_KEYS
ini:
- section: paramiko_connection
key: look_for_keys
type: boolean
host_key_checking:
description: Set this to "False" if you want to avoid host key checking by the
underlying tools Ansible uses to connect to the host
type: boolean
default: true
env:
- name: ANSIBLE_HOST_KEY_CHECKING
- name: ANSIBLE_SSH_HOST_KEY_CHECKING
- name: ANSIBLE_NETCONF_HOST_KEY_CHECKING
ini:
- section: defaults
key: host_key_checking
- section: paramiko_connection
key: host_key_checking
vars:
- name: ansible_host_key_checking
- name: ansible_ssh_host_key_checking
- name: ansible_netconf_host_key_checking
proxy_command:
default: ''
description:
- Proxy information for running the connection via a jumphost.
- This requires ncclient >= 0.6.10 to be installed on the controller.
type: string
env:
- name: ANSIBLE_NETCONF_PROXY_COMMAND
ini:
- {key: proxy_command, section: paramiko_connection}
vars:
- name: ansible_paramiko_proxy_command
- name: ansible_netconf_proxy_command
netconf_ssh_config:
description:
- This variable is used to enable bastion/jump host with netconf connection. If
set to True the bastion/jump host ssh settings should be present in ~/.ssh/config
file, alternatively it can be set to custom ssh configuration file path to read
the bastion/jump host settings.
type: string
ini:
- section: netconf_connection
key: ssh_config
env:
- name: ANSIBLE_NETCONF_SSH_CONFIG
vars:
- name: ansible_netconf_ssh_config
"""
import json
import logging
import os
from ansible.errors import AnsibleConnectionFailure, AnsibleError
from ansible.module_utils._text import to_bytes, to_native, to_text
from ansible.module_utils.basic import missing_required_lib
from ansible.module_utils.parsing.convert_bool import BOOLEANS_FALSE, BOOLEANS_TRUE
from ansible.module_utils.six import PY3
from ansible.module_utils.six.moves import cPickle
from ansible.playbook.play_context import PlayContext
from ansible.plugins.connection import ensure_connect
from ansible.plugins.loader import netconf_loader
from ansible_collections.ansible.netcommon.plugins.plugin_utils.connection_base import (
NetworkConnectionBase,
)
from ansible_collections.ansible.netcommon.plugins.plugin_utils.version import Version
try:
from ncclient import __version__ as NCCLIENT_VERSION
from ncclient import manager
from ncclient.operations import RPCError
from ncclient.transport.errors import AuthenticationError, SSHUnknownHostError
from ncclient.xml_ import to_ele, to_xml
from paramiko import ProxyCommand
HAS_NCCLIENT = True
NCCLIENT_IMP_ERR = None
# paramiko and gssapi are incompatible and raise AttributeError not ImportError
# When running in FIPS mode, cryptography raises InternalError
# https://bugzilla.redhat.com/show_bug.cgi?id=1778939
except Exception as err:
HAS_NCCLIENT = False
NCCLIENT_IMP_ERR = err
logging.getLogger("ncclient").setLevel(logging.INFO)
class Connection(NetworkConnectionBase):
"""NetConf connections"""
transport = "ansible.netcommon.netconf"
has_pipelining = False
def __init__(self, play_context, new_stdin, *args, **kwargs):
super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
# If network_os is not specified then set the network os to auto
# This will be used to trigger the use of guess_network_os when connecting.
self._network_os = self._network_os or "auto"
self.netconf = netconf_loader.get(self._network_os, self)
if self.netconf:
self._sub_plugin = {
"type": "netconf",
"name": self.netconf._load_name,
"obj": self.netconf,
}
self.queue_message(
"vvvv",
"loaded netconf plugin %s from path %s for network_os %s"
% (
self.netconf._load_name,
self.netconf._original_path,
self._network_os,
),
)
else:
self.netconf = netconf_loader.get("default", self)
self._sub_plugin = {
"type": "netconf",
"name": "default",
"obj": self.netconf,
}
self.queue_message(
"vvvv",
"unable to load netconf plugin for network_os %s, falling back to default plugin"
% self._network_os,
)
self.queue_message("log", "network_os is set to %s" % self._network_os)
self._manager = None
self.key_filename = None
self._ssh_config = None
def exec_command(self, cmd, in_data=None, sudoable=True):
"""Sends the request to the node and returns the reply
The method accepts two forms of request. The first form is as a byte
string that represents xml string be send over netconf session.
The second form is a json-rpc (2.0) byte string.
"""
if self._manager:
# to_ele operates on native strings
request = to_ele(to_native(cmd, errors="surrogate_or_strict"))
if request is None:
return "unable to parse request"
try:
reply = self._manager.rpc(request)
except RPCError as exc:
error = self.internal_error(
data=to_text(to_xml(exc.xml), errors="surrogate_or_strict")
)
return json.dumps(error)
return reply.data_xml
else:
return super(Connection, self).exec_command(cmd, in_data, sudoable)
def update_play_context(self, pc_data):
"""Updates the play context information for the connection"""
pc_data = to_bytes(pc_data)
if PY3:
pc_data = cPickle.loads(pc_data, encoding="bytes")
else:
pc_data = cPickle.loads(pc_data)
play_context = PlayContext()
play_context.deserialize(pc_data)
self._play_context = play_context
@property
@ensure_connect
def manager(self):
return self._manager
def _get_proxy_command(self, port=22):
proxy_command = None
# TO-DO: Add logic to scan ssh_* args to read ProxyCommand
proxy_command = self.get_option("proxy_command")
sock = None
if proxy_command:
if Version(NCCLIENT_VERSION) < "0.6.10":
raise AnsibleError(
"Configuring jumphost settings through ProxyCommand is unsupported in ncclient version %s. "
"Please upgrade to ncclient 0.6.10 or newer." % NCCLIENT_VERSION
)
replacers = {
"%h": self._play_context.remote_addr,
"%p": port,
"%r": self._play_context.remote_user,
}
for find, replace in replacers.items():
proxy_command = proxy_command.replace(find, str(replace))
sock = ProxyCommand(proxy_command)
return sock
def _connect(self):
if not HAS_NCCLIENT:
raise AnsibleError(
"%s: %s"
% (
missing_required_lib("ncclient"),
to_native(NCCLIENT_IMP_ERR),
)
)
self.queue_message("log", "ssh connection done, starting ncclient")
allow_agent = True
if self._play_context.password is not None:
allow_agent = False
setattr(self._play_context, "allow_agent", allow_agent)
self.key_filename = self._play_context.private_key_file or self.get_option(
"private_key_file"
)
if self.key_filename:
self.key_filename = str(os.path.expanduser(self.key_filename))
self._ssh_config = self.get_option("netconf_ssh_config")
if self._ssh_config in BOOLEANS_TRUE:
self._ssh_config = True
elif self._ssh_config in BOOLEANS_FALSE:
self._ssh_config = None
# Try to guess the network_os if the network_os is set to auto
if self._network_os == "auto":
for cls in netconf_loader.all(class_only=True):
network_os = cls.guess_network_os(self)
if network_os:
self.queue_message("vvv", "discovered network_os %s" % network_os)
self._network_os = network_os
# If we have tried to detect the network_os but were unable to i.e. network_os is still 'auto'
# then use default as the network_os
if self._network_os == "auto":
# Network os not discovered. Set it to default
self.queue_message(
"vvv",
"Unable to discover network_os. Falling back to default.",
)
self._network_os = "default"
try:
ncclient_device_handler = self.netconf.get_option("ncclient_device_handler")
except KeyError:
ncclient_device_handler = "default"
self.queue_message(
"vvv",
"identified ncclient device handler: %s." % ncclient_device_handler,
)
device_params = {"name": ncclient_device_handler}
try:
port = self._play_context.port or 830
self.queue_message(
"vvv",
"ESTABLISH NETCONF SSH CONNECTION FOR USER: %s on PORT %s TO %s WITH SSH_CONFIG = %s"
% (
self._play_context.remote_user,
port,
self._play_context.remote_addr,
self._ssh_config,
),
)
params = dict(
host=self._play_context.remote_addr,
port=port,
username=self._play_context.remote_user,
password=self._play_context.password,
key_filename=self.key_filename,
hostkey_verify=self.get_option("host_key_checking"),
look_for_keys=self.get_option("look_for_keys"),
device_params=device_params,
allow_agent=self._play_context.allow_agent,
timeout=self.get_option("persistent_connect_timeout"),
ssh_config=self._ssh_config,
)
# sock is only supported by ncclient >= 0.6.10, and will error if
# included on older versions. We check the version in
# _get_proxy_command, so if this returns a value, the version is
# fine and we have something to send. Otherwise, don't even send
# the option to support older versions of ncclient
sock = self._get_proxy_command(port)
if sock:
params["sock"] = sock
self._manager = manager.connect(**params)
self._manager._timeout = self.get_option("persistent_command_timeout")
except SSHUnknownHostError as exc:
raise AnsibleConnectionFailure(to_native(exc))
except AuthenticationError as exc:
if str(exc).startswith("FileNotFoundError"):
raise AnsibleError(
"Encountered FileNotFoundError in ncclient connect. Does {0} exist?".format(
self.key_filename
)
)
raise
except ImportError:
raise AnsibleError(
"connection=netconf is not supported on {0}".format(self._network_os)
)
if not self._manager.connected:
return 1, b"", b"not connected"
self.queue_message("log", "ncclient manager object created successfully")
self._connected = True
super(Connection, self)._connect()
return (
0,
to_bytes(self._manager.session_id, errors="surrogate_or_strict"),
b"",
)
def close(self):
if self._manager:
self._manager.close_session()
super(Connection, self).close()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
# 2017 Red Hat Inc.
# (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
author:
- Ansible Networking Team (@ansible-network)
name: persistent
short_description: Use a persistent unix socket for connection
description:
- This is a helper plugin to allow making other connections persistent.
version_added: 1.0.0
extends_documentation_fragment:
- ansible.netcommon.connection_persistent
"""
from ansible.executor.task_executor import start_connection
from ansible.module_utils._text import to_text
from ansible.module_utils.connection import Connection as SocketConnection
from ansible.plugins.connection import ConnectionBase
from ansible.utils.display import Display
display = Display()
class Connection(ConnectionBase):
"""Local based connections"""
transport = "ansible.netcommon.persistent"
has_pipelining = False
def __init__(self, play_context, new_stdin, *args, **kwargs):
super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
self._task_uuid = to_text(kwargs.get("task_uuid", ""))
def _connect(self):
self._connected = True
return self
def exec_command(self, cmd, in_data=None, sudoable=True):
display.vvvv(
"exec_command(), socket_path=%s" % self.socket_path,
host=self._play_context.remote_addr,
)
connection = SocketConnection(self.socket_path)
out = connection.exec_command(cmd, in_data=in_data, sudoable=sudoable)
return 0, out, ""
def put_file(self, in_path, out_path):
pass
def fetch_file(self, in_path, out_path):
pass
def close(self):
self._connected = False
def run(self):
"""Returns the path of the persistent connection socket.
Attempts to ensure (within playcontext.timeout seconds) that the
socket path exists. If the path exists (or the timeout has expired),
returns the socket path.
"""
display.vvvv(
"starting connection from persistent connection plugin",
host=self._play_context.remote_addr,
)
variables = {"ansible_command_timeout": self.get_option("persistent_command_timeout")}
socket_path = start_connection(self._play_context, variables, self._task_uuid)
display.vvvv(
"local domain socket path is %s" % socket_path,
host=self._play_context.remote_addr,
)
setattr(self, "_socket_path", socket_path)
return socket_path

View File

@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
class ModuleDocFragment(object):
# Standard files documentation fragment
DOCUMENTATION = r"""
options:
import_modules:
type: boolean
description:
- Reduce CPU usage and network module execution time
by enabling direct execution. Instead of the module being packaged
and executed by the shell, it will be directly executed by the Ansible
control node using the same python interpreter as the Ansible process.
Note- Incompatible with C(asynchronous mode).
Note- Python 3 and Ansible 2.9.16 or greater required.
Note- With Ansible 2.9.x fully qualified modules names are required in tasks.
default: true
ini:
- section: ansible_network
key: import_modules
env:
- name: ANSIBLE_NETWORK_IMPORT_MODULES
vars:
- name: ansible_network_import_modules
persistent_connect_timeout:
type: int
description:
- Configures, in seconds, the amount of time to wait when trying to initially
establish a persistent connection. If this value expires before the connection
to the remote device is completed, the connection will fail.
default: 30
ini:
- section: persistent_connection
key: connect_timeout
env:
- name: ANSIBLE_PERSISTENT_CONNECT_TIMEOUT
vars:
- name: ansible_connect_timeout
persistent_command_timeout:
type: int
description:
- Configures, in seconds, the amount of time to wait for a command to
return from the remote device. If this timer is exceeded before the
command returns, the connection plugin will raise an exception and
close.
default: 30
ini:
- section: persistent_connection
key: command_timeout
env:
- name: ANSIBLE_PERSISTENT_COMMAND_TIMEOUT
vars:
- name: ansible_command_timeout
persistent_log_messages:
type: boolean
description:
- This flag will enable logging the command executed and response received from
target device in the ansible log file. For this option to work 'log_path' ansible
configuration option is required to be set to a file path with write access.
- Be sure to fully understand the security implications of enabling this
option as it could create a security vulnerability by logging sensitive information in log file.
default: False
ini:
- section: persistent_connection
key: log_messages
env:
- name: ANSIBLE_PERSISTENT_LOG_MESSAGES
vars:
- name: ansible_persistent_log_messages
"""

View File

@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
__metaclass__ = type
# Copyright: (c) 2019 Ansible, Inc
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
class ModuleDocFragment(object):
# Standard files documentation fragment
DOCUMENTATION = r"""options: {}
notes:
- This module is supported on C(ansible_network_os) network platforms. See the :ref:`Network
Platform Options <platform_options>` for details.
"""

View File

@@ -0,0 +1,109 @@
#
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
"""
The comp_type5 filter plugin
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
name: comp_type5
author: Ken Celenza (@itdependsnetworks)
version_added: "1.0.0"
short_description: The comp_type5 filter plugin.
description:
- The filter confirms configuration idempotency on use of type5_pw.
notes:
- The filter confirms configuration idempotency on use of type5_pw.
- Can be used to validate password post hashing
username cisco secret 5 {{ ansible_ssh_pass | ansible.netcommon.comp_type5(encrypted, True) }}
options:
unencrypted_password:
description:
- The unencrypted text.
type: str
required: True
encrypted_password:
description:
- The encrypted text.
type: str
required: True
return_original:
description:
- Return the original text.
type: bool
"""
EXAMPLES = r"""
# Using comp_type5
# playbook
- name: Set the facts
ansible.builtin.set_fact:
unencrypted_password: "cisco@123"
encrypted_password: "$1$avs$uSTOEMh65ADDBREAKqzvpb9yBMpzd/"
- name: Invoke comp_type5
ansible.builtin.debug:
msg: "{{ unencrypted_password | ansible.netcommon.comp_type5(encrypted_password, False) }}"
# Task Output
# -----------
#
# TASK [Set the facts]
# ok: [35.155.113.92] => changed=false
# ansible_facts:
# encrypted_password: $1$avs$uSTOEMh65ADDBREAKqzvpb9yBMpzd/
# unencrypted_password: cisco@123
# TASK [Invoke comp_type5]
# ok: [35.155.113.92] =>
# msg: true
"""
from ansible.errors import AnsibleFilterError
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
)
from ansible_collections.ansible.netcommon.plugins.plugin_utils.comp_type5 import comp_type5
try:
from jinja2.filters import pass_environment
except ImportError:
from jinja2.filters import environmentfilter as pass_environment
@pass_environment
def _comp_type5(*args, **kwargs):
"""Extend vlan data"""
keys = [
"unencrypted_password",
"encrypted_password",
"return_original",
]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="comp_type5")
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return comp_type5(**updated_data)
class FilterModule(object):
"""comp_type5"""
def filters(self):
"""a mapping of filter names to functions"""
return {"comp_type5": _comp_type5}

View File

@@ -0,0 +1,96 @@
#
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
"""
The hash_salt filter plugin
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
name: hash_salt
author: Ken Celenza (@itdependsnetworks)
version_added: "1.0.0"
short_description: The hash_salt filter plugin.
description:
- The filter plugin produces the salt from a hashed password.
- Using the parameters below - C(password | ansible.netcommon.hash_salt(template.yml))
notes:
- The filter plugin produces the salt from a hashed password.
options:
password:
description:
- This source data on which hash_salt invokes.
- For example C(password | ansible.netcommon.hash_salt),
in this case C(password) represents the hashed password.
type: str
required: True
"""
EXAMPLES = r"""
# Using hash_salt
# playbook
- name: Set the facts
ansible.builtin.set_fact:
password: "$1$avs$uSTOEMh65ADDBREAKqzvpb9yBMpzd/"
- name: Invoke hash_salt
ansible.builtin.debug:
msg: "{{ password | ansible.netcommon.hash_salt() }}"
# Task Output
# -----------
#
# TASK [Set the facts]
# ok: [host] => changed=false
# ansible_facts:
# password: $1$avs$uSTOEMh65ADDBREAKqzvpb9yBMpzd/
# TASK [Invoke hash_salt]
# ok: [host] =>
# msg: avs
"""
from ansible.errors import AnsibleFilterError
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
)
from ansible_collections.ansible.netcommon.plugins.plugin_utils.hash_salt import hash_salt
try:
from jinja2.filters import pass_environment
except ImportError:
from jinja2.filters import environmentfilter as pass_environment
@pass_environment
def _hash_salt(*args, **kwargs):
"""Extend vlan data"""
keys = ["password"]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="hash_salt")
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return hash_salt(**updated_data)
class FilterModule(object):
"""hash_salt"""
def filters(self):
"""a mapping of filter names to functions"""
return {"hash_salt": _hash_salt}

View File

@@ -0,0 +1,164 @@
#
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
"""
The parse_cli filter plugin
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
name: parse_cli
author: Peter Sprygada (@privateip)
version_added: "1.0.0"
short_description: parse_cli filter plugin.
description:
- The filter plugins converts the output of a network device
CLI command into structured JSON output.
- Using the parameters below - C(xml_data | ansible.netcommon.parse_cli(template.yml))
notes:
- The parse_cli filter will load the spec file and pass the command output through it,
returning JSON output. The YAML spec file defines how to parse the CLI output
options:
output:
description:
- This source data on which parse_cli invokes.
type: raw
required: True
tmpl:
description:
- The spec file should be valid formatted YAML.
It defines how to parse the CLI output and return JSON data.
- For example C(cli_data | ansible.netcommon.parse_cli(template.yml)),
in this case C(cli_data) represents cli output.
type: str
"""
EXAMPLES = r"""
# Using parse_cli
# outputConfig
# ip dhcp pool Data
# import all
# network 192.168.1.0 255.255.255.0
# update dns
# default-router 192.168.1.1
# dns-server 192.168.1.1 8.8.8.8
# option 42 ip 192.168.1.1
# domain-name test.local
# lease 8
# pconnection.yml
# ---
# vars:
# dhcp_pool:
# name: "{{ item.name }}"
# network: "{{ item.network_ip }}"
# subnet: "{{ item.network_subnet }}"
# dns_servers: "{{ item.dns_servers_1 }}{{ item.dns_servers_2 }}"
# domain_name: "{{ item.domain_name_0 }}{{ item.domain_name_1 }}{{ item.domain_name_2 }}{{ item.domain_name_3 }}"
# options: "{{ item.options_1 }}{{ item.options_2 }}"
# lease_days: "{{ item.lease_days }}"
# lease_hours: "{{ item.lease_hours }}"
# lease_minutes: "{{ item.lease_minutes }}"
# keys:
# dhcp_pools:
# value: "{{ dhcp_pool }}"
# items: "^ip dhcp pool (
# ?P<name>[^\\n]+)\\s+(?:import (?P<import_all>all)\\s*)?(?:network (?P<network_ip>[\\d.]+)
# (?P<network_subnet>[\\d.]+)?\\s*)?(?:update dns\\s*)?(?:host (?P<host_ip>[\\d.]+)
# (?P<host_subnet>[\\d.]+)\\s*)?(?:domain-name (?P<domain_name_0>[\\w._-]+)\\s+)?
# (?:default-router (?P<default_router>[\\d.]+)\\s*)?(?:dns-server
# (?P<dns_servers_1>(?:[\\d.]+ ?)+ ?)+\\s*)?(?:domain-name (?P<domain_name_1>[\\w._-]+)\\s+)?
# (?P<options_1>(?:option [^\\n]+\\n*\\s*)*)?(?:domain-name (?P<domain_name_2>[\\w._-]+)\\s+)?(?P<options_2>(?:option [^\\n]+\\n*\\s*)*)?
# (?:dns-server (?P<dns_servers_2>(?:[\\d.]+ ?)+ ?)+\\s*)?(?:domain-name
# (?P<domain_name_3>[\\w._-]+)\\s*)?(lease (?P<lease_days>\\d+)(?: (?P<lease_hours>\\d+))?(?: (?P<lease_minutes>\\d+))?\\s*)?(?:update arp)?"
# playbook
- name: Add config data
ansible.builtin.set_fact:
opconfig: "{{lookup('ansible.builtin.file', 'outputConfig') }}"
- name: Parse Data
ansible.builtin.set_fact:
output: "{{ opconfig | parse_cli('pconnection.yml') }}"
# Task Output
# -----------
#
# TASK [Add config data]
# ok: [host] => changed=false
# ansible_facts:
# xml: |-
# ip dhcp pool Data
# import all
# network 192.168.1.0 255.255.255.0
# update dns
# default-router 192.168.1.1
# dns-server 192.168.1.1 8.8.8.8
# option 42 ip 192.168.1.1
# domain-name test.local
# lease 8
# TASK [Parse Data]
# ok: [host] => changed=false
# ansible_facts:
# output:
# dhcp_pools:
# - dns_servers: 192.168.1.1 8.8.8.8
# domain_name: test.local
# lease_days: 8
# lease_hours: null
# lease_minutes: null
# name: Data
# network: 192.168.1.0
# options: |-
# option 42 ip 192.168.1.1
# subnet: 255.255.255.0
"""
from ansible.errors import AnsibleFilterError
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
)
from ansible_collections.ansible.netcommon.plugins.plugin_utils.parse_cli import parse_cli
try:
from jinja2.filters import pass_environment
except ImportError:
from jinja2.filters import environmentfilter as pass_environment
@pass_environment
def _parse_cli(*args, **kwargs):
"""Extend vlan data"""
keys = ["output", "tmpl"]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="parse_cli")
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return parse_cli(**updated_data)
class FilterModule(object):
"""parse_cli"""
def filters(self):
"""a mapping of filter names to functions"""
return {"parse_cli": _parse_cli}

View File

@@ -0,0 +1,121 @@
#
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
"""
The parse_cli_textfsm filter plugin
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
name: parse_cli_textfsm
author: Peter Sprygada (@privateip)
version_added: "1.0.0"
short_description: parse_cli_textfsm filter plugin.
description:
- The network filters also support parsing the output of a CLI command using the TextFSM library.
To parse the CLI output with TextFSM use this filter.
- Using the parameters below - C(data | ansible.netcommon.parse_cli_textfsm(template.yml))
notes:
- Use of the TextFSM filter requires the TextFSM library to be installed.
options:
value:
description:
- This source data on which parse_cli_textfsm invokes.
type: raw
required: True
template:
description:
- The template to compare it with.
- For example C(data | ansible.netcommon.parse_cli_textfsm(template.yml)),
in this case C(data) represents this option.
type: str
"""
EXAMPLES = r"""
# Using parse_cli_textfsm
- name: "Fetch command output"
cisco.ios.ios_command:
commands:
- show lldp neighbors
register: lldp_output
- name: "Invoke parse_cli_textfsm"
ansible.builtin.set_fact:
device_neighbors: "{{ lldp_output.stdout[0] | parse_cli_textfsm('~/ntc-templates/templates/cisco_ios_show_lldp_neighbors.textfsm') }}"
- name: "Debug"
ansible.builtindebug:
msg: "{{ device_neighbors }}"
# Task Output
# -----------
#
# TASK [Fetch command output]
# ok: [rtr-2]
# TASK [Invoke parse_cli_textfsm]
# ok: [rtr-1]
# TASK [Debug]
# ok: [rtr-1] => {
# "msg": [
# {
# "CAPABILITIES": "R",
# "LOCAL_INTERFACE": "Gi0/0",
# "NEIGHBOR": "rtr-3",
# "NEIGHBOR_INTERFACE": "Gi0/0"
# },
# {
# "CAPABILITIES": "R",
# "LOCAL_INTERFACE": "Gi0/1",
# "NEIGHBOR": "rtr-1",
# "NEIGHBOR_INTERFACE": "Gi0/1"
# }
# ]
# }
"""
from ansible.errors import AnsibleFilterError
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
)
from ansible_collections.ansible.netcommon.plugins.plugin_utils.parse_cli_textfsm import (
parse_cli_textfsm,
)
try:
from jinja2.filters import pass_environment
except ImportError:
from jinja2.filters import environmentfilter as pass_environment
@pass_environment
def _parse_cli_textfsm(*args, **kwargs):
"""Extend vlan data"""
keys = ["value", "template"]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="parse_cli_textfsm")
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return parse_cli_textfsm(**updated_data)
class FilterModule(object):
"""parse_cli_textfsm"""
def filters(self):
"""a mapping of filter names to functions"""
return {"parse_cli_textfsm": _parse_cli_textfsm}

View File

@@ -0,0 +1,195 @@
#
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
"""
The parse_xml filter plugin
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
name: parse_xml
author: Ganesh Nalawade (@ganeshrn)
version_added: "1.0.0"
short_description: The parse_xml filter plugin.
description:
- This filter will load the spec file and pass the command output
through it, returning JSON output.
- The YAML spec file defines how to parse the CLI output.
notes:
- To convert the XML output of a network device command into structured JSON output.
options:
output:
description:
- This source xml on which parse_xml invokes.
type: raw
required: True
tmpl:
description:
- The spec file should be valid formatted YAML.
It defines how to parse the XML output and return JSON data.
- For example C(xml_data | ansible.netcommon.parse_xml(template.yml)),
in this case C(xml_data) represents xml data option.
type: str
"""
EXAMPLES = r"""
# Using parse_xml
# example_output.xml
# <?xml version="1.0" encoding="UTF-8"?>
# <rpc-reply message-id="urn:uuid:0cadb4e8-5bba-47f4-986e-72906227007f">
# <data>
# <ntp>
# <nodes>
# <node>
# <node>0/0/CPU0</node>
# <associations>
# <is-ntp-enabled>true</is-ntp-enabled>
# <sys-leap>ntp-leap-no-warning</sys-leap>
# <peer-summary-info>
# <peer-info-common>
# <host-mode>ntp-mode-client</host-mode>
# <is-configured>true</is-configured>
# <address>10.1.1.1</address>
# <reachability>0</reachability>
# </peer-info-common>
# <time-since>-1</time-since>
# </peer-summary-info>
# <peer-summary-info>
# <peer-info-common>
# <host-mode>ntp-mode-client</host-mode>
# <is-configured>true</is-configured>
# <address>172.16.252.29</address>
# <reachability>255</reachability>
# </peer-info-common>
# <time-since>991</time-since>
# </peer-summary-info>
# </associations>
# </node>
# </nodes>
# </ntp>
# </data>
# </rpc-reply>
# parse_xml.yml
# ---
# vars:
# ntp_peers:
# address: "{{ item.address }}"
# reachability: "{{ item.reachability}}"
# keys:
# result:
# value: "{{ ntp_peers }}"
# top: data/ntp/nodes/node/associations
# items:
# address: peer-summary-info/peer-info-common/address
# reachability: peer-summary-info/peer-info-common/reachability
- name: Facts setup
ansible.builtin.set_fact:
xml: "{{ lookup('file', 'example_output.xml') }}"
- name: Parse xml invocation
ansible.builtin.debug:
msg: "{{ xml | ansible.netcommon.parse_xml('parse_xml.yml') }}"
# Task Output
# -----------
#
# TASK [set xml Data]
# ok: [host] => changed=false
# ansible_facts:
# xml: |-
# <?xml version="1.0" encoding="UTF-8"?>
# <rpc-reply message-id="urn:uuid:0cadb4e8-5bba-47f4-986e-72906227007f">
# <data>
# <ntp>
# <nodes>
# <node>
# <node>0/0/CPU0</node>
# <associations>
# <is-ntp-enabled>true</is-ntp-enabled>
# <sys-leap>ntp-leap-no-warning</sys-leap>
# <peer-summary-info>
# <peer-info-common>
# <host-mode>ntp-mode-client</host-mode>
# <is-configured>true</is-configured>
# <address>10.1.1.1</address>
# <reachability>0</reachability>
# </peer-info-common>
# <time-since>-1</time-since>
# </peer-summary-info>
# <peer-summary-info>
# <peer-info-common>
# <host-mode>ntp-mode-client</host-mode>
# <is-configured>true</is-configured>
# <address>172.16.252.29</address>
# <reachability>255</reachability>
# </peer-info-common>
# <time-since>991</time-since>
# </peer-summary-info>
# </associations>
# </node>
# </nodes>
# </ntp>
# </data>
# </rpc-reply>
# TASK [Parse Data]
# ok: [host] => changed=false
# ansible_facts:
# output:
# result:
# - address:
# - 10.1.1.1
# - 172.16.252.29
# reachability:
# - '0'
# - '255'
"""
from ansible.errors import AnsibleFilterError
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
)
from ansible_collections.ansible.netcommon.plugins.plugin_utils.parse_xml import parse_xml
try:
from jinja2.filters import pass_environment
except ImportError:
from jinja2.filters import environmentfilter as pass_environment
@pass_environment
def _parse_xml(*args, **kwargs):
"""Extend vlan data"""
keys = ["output", "tmpl"]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="parse_xml")
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return parse_xml(**updated_data)
class FilterModule(object):
"""parse_xml"""
def filters(self):
"""a mapping of filter names to functions"""
return {"parse_xml": _parse_xml}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,96 @@
#
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
"""
The type5_pw filter plugin
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
name: type5_pw
author: Ken Celenza (@itdependsnetworks)
version_added: "1.0.0"
short_description: The type5_pw filter plugin.
description:
- Filter plugin to produce cisco type5 hashed password.
- Using the parameters below - C(xml_data | ansible.netcommon.type5_pw(template.yml))
notes:
- The filter plugin generates cisco type5 hashed password.
options:
password:
description:
- The password to be hashed.
type: str
required: True
salt:
description:
- Mention the salt to hash the password.
type: str
"""
EXAMPLES = r"""
# Using type5_pw
- name: Set some facts
ansible.builtin.set_fact:
password: "cisco@123"
- name: Filter type5_pw invocation
ansible.builtin.debug:
msg: "{{ password | ansible.netcommon.type5_pw(salt='avs') }}"
# Task Output
# -----------
#
# TASK [Set some facts]
# ok: [host] => changed=false
# ansible_facts:
# password: cisco@123
# TASK [Filter type5_pw invocation]
# ok: [host] =>
# msg: $1$avs$uSTOEMh65qzvpb9yBMpzd/
"""
from ansible.errors import AnsibleFilterError
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
)
from ansible_collections.ansible.netcommon.plugins.plugin_utils.type5_pw import type5_pw
try:
from jinja2.filters import pass_environment
except ImportError:
from jinja2.filters import environmentfilter as pass_environment
@pass_environment
def _type5_pw(*args, **kwargs):
"""Extend vlan data"""
keys = ["password", "salt"]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="type5_pw")
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return type5_pw(**updated_data)
class FilterModule(object):
"""type5_pw"""
def filters(self):
"""a mapping of filter names to functions"""
return {"type5_pw": _type5_pw}

View File

@@ -0,0 +1,101 @@
#
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
"""
The vlan_expander filter plugin
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
name: vlan_expander
author: Akira Yokochi (@akira6592)
version_added: "2.3.0"
short_description: The vlan_expander filter plugin.
description:
- Expand shorthand list of VLANs to list all VLANs. Inverse of vlan_parser
- Using the parameters below - C(vlans_data | ansible.netcommon.vlan_expander)
notes:
- The filter plugin extends vlans when data provided in range or comma separated.
options:
data:
description:
- This option represents a string containing the range of vlans.
type: str
required: True
"""
EXAMPLES = r"""
# Using vlan_expander
- name: Setting host facts for vlan_expander filter plugin
ansible.builtin.set_fact:
vlan_ranges: "1,10-12,15,20-22"
- name: Invoke vlan_expander filter plugin
ansible.builtin.set_fact:
extended_vlans: "{{ vlan_ranges | ansible.netcommon.vlan_expander }}"
# Task Output
# -----------
#
# TASK [Setting host facts for vlan_expander filter plugin]
# ok: [host] => changed=false
# ansible_facts:
# vlan_ranges: 1,10-12,15,20-22
# TASK [Invoke vlan_expander filter plugin]
# ok: [host] => changed=false
# ansible_facts:
# extended_vlans:
# - 1
# - 10
# - 11
# - 12
# - 15
# - 20
# - 21
# - 22
"""
from ansible.errors import AnsibleFilterError
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
)
from ansible_collections.ansible.netcommon.plugins.plugin_utils.vlan_expander import vlan_expander
try:
from jinja2.filters import pass_environment
except ImportError:
from jinja2.filters import environmentfilter as pass_environment
@pass_environment
def _vlan_expander(*args, **kwargs):
"""Extend vlan data"""
keys = ["data"]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="vlan_expander")
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return vlan_expander(**updated_data)
class FilterModule(object):
"""vlan_expander"""
def filters(self):
"""a mapping of filter names to functions"""
return {"vlan_expander": _vlan_expander}

View File

@@ -0,0 +1,137 @@
#
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
"""
The vlan_parser filter plugin
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
name: vlan_parser
author: Steve Dodd (@idahood)
version_added: "1.0.0"
short_description: The vlan_parser filter plugin.
description:
- The filter plugin converts a list of vlans to IOS like vlan configuration.
- Converts list to a list of range of numbers into multiple lists.
- C(vlans_data | ansible.netcommon.vlan_parser(first_line_len = 20, other_line_len=20))
notes:
- The filter plugin extends vlans when data provided in range or comma separated.
options:
data:
description:
- This option represents a list containing vlans.
type: list
required: True
first_line_len:
description:
- The first line of the list can be first_line_len characters long.
type: int
default: 48
other_line_len:
description:
- The subsequent list lines can be other_line_len characters.
type: int
default: 44
"""
EXAMPLES = r"""
# Using vlan_parser
- name: Setting host facts for vlan_parser filter plugin
ansible.builtin.set_fact:
vlans:
[
100,
1688,
3002,
3003,
3004,
3005,
3102,
3103,
3104,
3105,
3802,
3900,
3998,
3999,
]
- name: Invoke vlan_parser filter plugin
ansible.builtin.set_fact:
vlans_ranges: "{{ vlans | ansible.netcommon.vlan_parser(first_line_len = 20, other_line_len=20) }}"
# Task Output
# -----------
#
# TASK [Setting host facts for vlan_parser filter plugin]
# ok: [host] => changed=false
# ansible_facts:
# vlans:
# - 100
# - 1688
# - 3002
# - 3003
# - 3004
# - 3005
# - 3102
# - 3103
# - 3104
# - 3105
# - 3802
# - 3900
# - 3998
# - 3999
# TASK [Invoke vlan_parser filter plugin]
# ok: [host] => changed=false
# ansible_facts:
# msg:
# - 100,1688,3002-3005
# - 3102-3105,3802,3900
# - 3998,3999
"""
from ansible.errors import AnsibleFilterError
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
AnsibleArgSpecValidator,
)
from ansible_collections.ansible.netcommon.plugins.plugin_utils.vlan_parser import vlan_parser
try:
from jinja2.filters import pass_environment
except ImportError:
from jinja2.filters import environmentfilter as pass_environment
@pass_environment
def _vlan_parser(*args, **kwargs):
"""Extend vlan data"""
keys = ["data", "first_line_len", "other_line_len"]
data = dict(zip(keys, args[1:]))
data.update(kwargs)
aav = AnsibleArgSpecValidator(data=data, schema=DOCUMENTATION, name="vlan_parser")
valid, errors, updated_data = aav.validate()
if not valid:
raise AnsibleFilterError(errors)
return vlan_parser(**updated_data)
class FilterModule(object):
"""vlan_parser"""
def filters(self):
"""a mapping of filter names to functions"""
return {"vlan_parser": _vlan_parser}

View File

@@ -0,0 +1,81 @@
# Copyright (c) 2018 Cisco and/or its affiliates.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = """
author:
- Ansible Networking Team (@ansible-network)
name: restconf
short_description: HttpApi Plugin for devices supporting Restconf API
description:
- This HttpApi plugin provides methods to connect to Restconf API endpoints.
version_added: 1.0.0
options:
root_path:
type: str
description:
- Specifies the location of the Restconf root.
default: /restconf
vars:
- name: ansible_httpapi_restconf_root
"""
import json
from ansible.module_utils._text import to_text
from ansible.module_utils.connection import ConnectionError
from ansible.module_utils.six.moves.urllib.error import HTTPError
from ansible_collections.ansible.netcommon.plugins.plugin_utils.httpapi_base import HttpApiBase
CONTENT_TYPE = "application/yang-data+json"
class HttpApi(HttpApiBase):
def send_request(self, data, **message_kwargs):
if data:
data = json.dumps(data)
path = "/".join(
[
self.get_option("root_path").rstrip("/"),
message_kwargs.get("path", "").lstrip("/"),
]
)
headers = {
"Content-Type": message_kwargs.get("content_type") or CONTENT_TYPE,
"Accept": message_kwargs.get("accept") or CONTENT_TYPE,
}
response, response_data = self.connection.send(
path, data, headers=headers, method=message_kwargs.get("method")
)
return handle_response(response, response_data)
def handle_response(response, response_data):
try:
response_data = json.loads(response_data.read())
except ValueError:
response_data.seek(0)
response_data = response_data.read()
if isinstance(response, HTTPError):
if response_data:
if "errors" in response_data:
errors = response_data["errors"]["error"]
error_text = "\n".join((error["error-message"] for error in errors))
else:
error_text = response_data
raise ConnectionError(error_text, code=response.code)
raise ConnectionError(to_text(response), code=response.code)
return response_data

Some files were not shown because too many files have changed in this diff Show More