summaryrefslogtreecommitdiffstats
path: root/docs/docsite/rst/network
diff options
context:
space:
mode:
Diffstat (limited to 'docs/docsite/rst/network')
-rw-r--r--docs/docsite/rst/network/dev_guide/developing_plugins_network.rst265
-rw-r--r--docs/docsite/rst/network/dev_guide/developing_resource_modules_network.rst826
-rw-r--r--docs/docsite/rst/network/dev_guide/documenting_modules_network.rst52
-rw-r--r--docs/docsite/rst/network/dev_guide/index.rst32
-rw-r--r--docs/docsite/rst/network/getting_started/basic_concepts.rst10
-rw-r--r--docs/docsite/rst/network/getting_started/first_inventory.rst431
-rw-r--r--docs/docsite/rst/network/getting_started/first_playbook.rst212
-rw-r--r--docs/docsite/rst/network/getting_started/index.rst34
-rw-r--r--docs/docsite/rst/network/getting_started/intermediate_concepts.rst39
-rw-r--r--docs/docsite/rst/network/getting_started/network_connection_options.rst48
-rw-r--r--docs/docsite/rst/network/getting_started/network_differences.rst68
-rw-r--r--docs/docsite/rst/network/getting_started/network_resources.rst47
-rw-r--r--docs/docsite/rst/network/getting_started/network_roles.rst267
-rw-r--r--docs/docsite/rst/network/getting_started/sample_files/first_playbook.yml15
-rw-r--r--docs/docsite/rst/network/getting_started/sample_files/first_playbook_ext.yml29
-rw-r--r--docs/docsite/rst/network/index.rst20
-rw-r--r--docs/docsite/rst/network/user_guide/cli_parsing.rst744
-rw-r--r--docs/docsite/rst/network/user_guide/faq.rst76
-rw-r--r--docs/docsite/rst/network/user_guide/index.rst26
-rw-r--r--docs/docsite/rst/network/user_guide/network_best_practices_2.5.rst483
-rw-r--r--docs/docsite/rst/network/user_guide/network_debug_troubleshooting.rst840
-rw-r--r--docs/docsite/rst/network/user_guide/network_resource_modules.rst196
-rw-r--r--docs/docsite/rst/network/user_guide/network_working_with_command_output.rst126
-rw-r--r--docs/docsite/rst/network/user_guide/platform_ce.rst213
-rw-r--r--docs/docsite/rst/network/user_guide/platform_cnos.rst78
-rw-r--r--docs/docsite/rst/network/user_guide/platform_dellos10.rst80
-rw-r--r--docs/docsite/rst/network/user_guide/platform_dellos6.rst79
-rw-r--r--docs/docsite/rst/network/user_guide/platform_dellos9.rst79
-rw-r--r--docs/docsite/rst/network/user_guide/platform_enos.rst80
-rw-r--r--docs/docsite/rst/network/user_guide/platform_eos.rst140
-rw-r--r--docs/docsite/rst/network/user_guide/platform_eric_eccli.rst73
-rw-r--r--docs/docsite/rst/network/user_guide/platform_exos.rst108
-rw-r--r--docs/docsite/rst/network/user_guide/platform_frr.rst73
-rw-r--r--docs/docsite/rst/network/user_guide/platform_icx.rst77
-rw-r--r--docs/docsite/rst/network/user_guide/platform_index.rst124
-rw-r--r--docs/docsite/rst/network/user_guide/platform_ios.rst79
-rw-r--r--docs/docsite/rst/network/user_guide/platform_iosxr.rst130
-rw-r--r--docs/docsite/rst/network/user_guide/platform_ironware.rst80
-rw-r--r--docs/docsite/rst/network/user_guide/platform_junos.rst129
-rw-r--r--docs/docsite/rst/network/user_guide/platform_meraki.rst44
-rw-r--r--docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst133
-rw-r--r--docs/docsite/rst/network/user_guide/platform_netvisor.rst78
-rw-r--r--docs/docsite/rst/network/user_guide/platform_nos.rst76
-rw-r--r--docs/docsite/rst/network/user_guide/platform_nxos.rst166
-rw-r--r--docs/docsite/rst/network/user_guide/platform_routeros.rst80
-rw-r--r--docs/docsite/rst/network/user_guide/platform_slxos.rst77
-rw-r--r--docs/docsite/rst/network/user_guide/platform_voss.rst78
-rw-r--r--docs/docsite/rst/network/user_guide/platform_vyos.rst74
-rw-r--r--docs/docsite/rst/network/user_guide/platform_weos4.rst88
-rw-r--r--docs/docsite/rst/network/user_guide/shared_snippets/SSH_warning.txt2
-rw-r--r--docs/docsite/rst/network/user_guide/validate.rst164
51 files changed, 7568 insertions, 0 deletions
diff --git a/docs/docsite/rst/network/dev_guide/developing_plugins_network.rst b/docs/docsite/rst/network/dev_guide/developing_plugins_network.rst
new file mode 100644
index 0000000..b550c28
--- /dev/null
+++ b/docs/docsite/rst/network/dev_guide/developing_plugins_network.rst
@@ -0,0 +1,265 @@
+
+.. _developing_modules_network:
+.. _developing_plugins_network:
+
+**************************
+Developing network plugins
+**************************
+
+You can extend the existing network modules with custom plugins in your collection.
+
+.. contents::
+ :local:
+
+Network connection plugins
+==========================
+Each network connection plugin has a set of its own plugins which provide a specification of the
+connection for a particular set of devices. The specific plugin used is selected at runtime based
+on the value of the ``ansible_network_os`` variable assigned to the host. This variable should be
+set to the same value as the name of the plugin to be loaded. Thus, ``ansible_network_os=nxos``
+will try to load a plugin in a file named ``nxos.py``, so it is important to name the plugin in a
+way that will be sensible to users.
+
+Public methods of these plugins may be called from a module or module_utils with the connection
+proxy object just as other connection methods can. The following is a very simple example of using
+such a call in a module_utils file so it may be shared with other modules.
+
+.. code-block:: python
+
+ from ansible.module_utils.connection import Connection
+
+ def get_config(module):
+ # module is your AnsibleModule instance.
+ connection = Connection(module._socket_path)
+
+ # You can now call any method (that doesn't start with '_') of the connection
+ # plugin or its platform-specific plugin
+ return connection.get_config()
+
+.. contents::
+ :local:
+
+.. _developing_plugins_httpapi:
+
+Developing httpapi plugins
+==========================
+
+:ref:`httpapi plugins <httpapi_plugins>` serve as adapters for various HTTP(S) APIs for use with the ``httpapi`` connection plugin. They should implement a minimal set of convenience methods tailored to the API you are attempting to use.
+
+Specifically, there are a few methods that the ``httpapi`` connection plugin expects to exist.
+
+Making requests
+---------------
+
+The ``httpapi`` connection plugin has a ``send()`` method, but an httpapi plugin needs a ``send_request(self, data, **message_kwargs)`` method as a higher-level wrapper to ``send()``. This method should prepare requests by adding fixed values like common headers or URL root paths. This method may do more complex work such as turning data into formatted payloads, or determining which path or method to request. It may then also unpack responses to be more easily consumed by the caller.
+
+.. code-block:: python
+
+ from ansible.module_utils.six.moves.urllib.error import HTTPError
+
+ def send_request(self, data, path, method='POST'):
+ # Fixed headers for requests
+ headers = {'Content-Type': 'application/json'}
+ try:
+ response, response_content = self.connection.send(path, data, method=method, headers=headers)
+ except HTTPError as exc:
+ return exc.code, exc.read()
+
+ # handle_response (defined separately) will take the format returned by the device
+ # and transform it into something more suitable for use by modules.
+ # This may be JSON text to Python dictionaries, for example.
+ return handle_response(response_content)
+
+Authenticating
+--------------
+
+By default, all requests will authenticate with HTTP Basic authentication. If a request can return some kind of token to stand in place of HTTP Basic, the ``update_auth(self, response, response_text)`` method should be implemented to inspect responses for such tokens. If the token is meant to be included with the headers of each request, it is sufficient to return a dictionary which will be merged with the computed headers for each request. The default implementation of this method does exactly this for cookies. If the token is used in another way, say in a query string, you should instead save that token to an instance variable, where the ``send_request()`` method (above) can add it to each request
+
+.. code-block:: python
+
+ def update_auth(self, response, response_text):
+ cookie = response.info().get('Set-Cookie')
+ if cookie:
+ return {'Cookie': cookie}
+
+ return None
+
+If instead an explicit login endpoint needs to be requested to receive an authentication token, the ``login(self, username, password)`` method can be implemented to call that endpoint. If implemented, this method will be called once before requesting any other resources of the server. By default, it will also be attempted once when a HTTP 401 is returned from a request.
+
+.. code-block:: python
+
+ def login(self, username, password):
+ login_path = '/my/login/path'
+ data = {'user': username, 'password': password}
+
+ response = self.send_request(data, path=login_path)
+ try:
+ # This is still sent as an HTTP header, so we can set our connection's _auth
+ # variable manually. If the token is returned to the device in another way,
+ # you will have to keep track of it another way and make sure that it is sent
+ # with the rest of the request from send_request()
+ self.connection._auth = {'X-api-token': response['token']}
+ except KeyError:
+ raise AnsibleAuthenticationFailure(message="Failed to acquire login token.")
+
+Similarly, ``logout(self)`` can be implemented to call an endpoint to invalidate and/or release the current token, if such an endpoint exists. This will be automatically called when the connection is closed (and, by extension, when reset).
+
+.. code-block:: python
+
+ def logout(self):
+ logout_path = '/my/logout/path'
+ self.send_request(None, path=logout_path)
+
+ # Clean up tokens
+ self.connection._auth = None
+
+Error handling
+--------------
+
+The ``handle_httperror(self, exception)`` method can deal with status codes returned by the server. The return value indicates how the plugin will continue with the request:
+
+* A value of ``true`` means that the request can be retried. This my be used to indicate a transient error, or one that has been resolved. For example, the default implementation will try to call ``login()`` when presented with a 401, and return ``true`` if successful.
+
+* A value of ``false`` means that the plugin is unable to recover from this response. The status code will be raised as an exception to the calling module.
+
+* Any other value will be taken as a nonfatal response from the request. This may be useful if the server returns error messages in the body of the response. Returning the original exception is usually sufficient in this case, as HTTPError objects have the same interface as a successful response.
+
+For example httpapi plugins, see the `source code for the httpapi plugins <https://github.com/ansible/ansible/tree/devel/lib/ansible/plugins/httpapi>`_ included with Ansible Core.
+
+
+
+Developing NETCONF plugins
+==========================
+
+The :ref:`netconf <netconf_connection>` connection plugin provides a connection to remote devices over the ``SSH NETCONF`` subsystem. Network devices typically use this connection plugin to send and receive ``RPC`` calls over ``NETCONF``.
+
+The ``netconf`` connection plugin uses the ``ncclient`` Python library under the hood to initiate a NETCONF session with a NETCONF-enabled remote network device. ``ncclient`` also executes NETCONF RPC requests and receives responses. You must install the ``ncclient`` on the local Ansible controller.
+
+To use the ``netconf`` connection plugin for network devices that support standard NETCONF (:RFC:`6241`) operations such as ``get``, ``get-config``, ``edit-config``, set ``ansible_network_os=default``.
+You can use :ref:`netconf_get <netconf_get_module>`, :ref:`netconf_config <netconf_config_module>` and :ref:`netconf_rpc <netconf_rpc_module>` modules to talk to a NETCONF enabled remote host.
+
+As a contributor and user, you should be able to use all the methods under the ``NetconfBase`` class if your device supports standard NETCONF. You can contribute a new plugin if the device you are working with has a vendor specific NETCONF RPC.
+To support a vendor specific NETCONF RPC, add the implementation in the network OS specific NETCONF plugin.
+
+For Junos for example:
+
+* See the vendor-specific Junos RPC methods implemented in ``plugins/netconf/junos.py``.
+* Set the value of ``ansible_network_os`` to the name of the netconf plugin file, that is ``junos`` in this case.
+
+.. _developing_plugins_network_cli:
+
+Developing network_cli plugins
+==============================
+
+The :ref:`network_cli <network_cli_connection>` connection type uses ``paramiko_ssh`` under the hood which creates a pseudo terminal to send commands and receive responses.
+``network_cli`` loads two platform specific plugins based on the value of ``ansible_network_os``:
+
+* Terminal plugin (for example ``plugins/terminal/ios.py``) - Controls the parameters related to terminal, such as setting terminal length and width, page disabling and privilege escalation. Also defines regex to identify the command prompt and error prompts.
+
+* :ref:`cliconf_plugins` (for example, :ref:`ios cliconf <ios_cliconf>`) - Provides an abstraction layer for low level send and receive operations. For example, the ``edit_config()`` method ensures that the prompt is in ``config`` mode before executing configuration commands.
+
+To contribute a new network operating system to work with the ``network_cli`` connection, implement the ``cliconf`` and ``terminal`` plugins for that network OS.
+
+The plugins can reside in:
+
+* Adjacent to playbook in folders
+
+ .. code-block:: bash
+
+ cliconf_plugins/
+ terminal_plugins/
+
+* Roles
+
+ .. code-block:: bash
+
+ myrole/cliconf_plugins/
+ myrole/terminal_plugins/
+
+* Collections
+
+ .. code-block:: bash
+
+ myorg/mycollection/plugins/terminal/
+ myorg/mycollection/plugins/cliconf/
+
+The user can also set the :ref:`DEFAULT_CLICONF_PLUGIN_PATH` to configure the ``cliconf`` plugin path.
+
+After adding the ``cliconf`` and ``terminal`` plugins in the expected locations, users can:
+
+* Use the :ref:`cli_command <cli_command_module>` to run an arbitrary command on the network device.
+* Use the :ref:`cli_config <cli_config_module>` to implement configuration changes on the remote hosts without platform-specific modules.
+
+
+.. _develop_cli_parse_plugins:
+
+Developing cli_parser plugins in a collection
+===============================================
+
+You can use ``cli_parse`` as an entry point for a cli_parser plugin in
+your own collection.
+
+The following sample shows the start of a custom cli_parser plugin:
+
+.. code-block:: python
+
+ from ansible_collections.ansible.netcommon.plugins.module_utils.cli_parser.cli_parserbase import (
+ CliParserBase,
+ )
+
+ class CliParser(CliParserBase):
+ """ Sample cli_parser plugin
+ """
+
+ # Use the follow extension when loading a template
+ DEFAULT_TEMPLATE_EXTENSION = "txt"
+ # Provide the contents of the template to the parse function
+ PROVIDE_TEMPLATE_CONTENTS = True
+
+ def myparser(text, template_contents):
+ # parse the text using the template contents
+ return {...}
+
+ def parse(self, *_args, **kwargs):
+ """ Standard entry point for a cli_parse parse execution
+
+ :return: Errors or parsed text as structured data
+ :rtype: dict
+
+ :example:
+
+ The parse function of a parser should return a dict:
+ {"errors": [a list of errors]}
+ or
+ {"parsed": obj}
+ """
+ template_contents = kwargs["template_contents"]
+ text = self._task_args.get("text")
+ try:
+ parsed = myparser(text, template_contents)
+ except Exception as exc:
+ msg = "Custom parser returned an error while parsing. Error: {err}"
+ return {"errors": [msg.format(err=to_native(exc))]}
+ return {"parsed": parsed}
+
+The following task uses this custom cli_parser plugin:
+
+.. code-block:: yaml
+
+ - name: Use a custom cli_parser
+ ansible.netcommon.cli_parse:
+ command: ls -l
+ parser:
+ name: my_organiztion.my_collection.custom_parser
+
+To develop a custom plugin:
+- Each cli_parser plugin requires a ``CliParser`` class.
+- Each cli_parser plugin requires a ``parse`` function.
+- Always return a dictionary with ``errors`` or ``parsed``.
+- Place the custom cli_parser in plugins/cli_parsers directory of the collection.
+- See the `current cli_parsers <https://github.com/ansible-collections/ansible.netcommon/tree/main/plugins/cli_parsers>`_ for examples to follow.
+
+
+.. seealso::
+
+ * :ref:`cli_parsing`
diff --git a/docs/docsite/rst/network/dev_guide/developing_resource_modules_network.rst b/docs/docsite/rst/network/dev_guide/developing_resource_modules_network.rst
new file mode 100644
index 0000000..fe16c57
--- /dev/null
+++ b/docs/docsite/rst/network/dev_guide/developing_resource_modules_network.rst
@@ -0,0 +1,826 @@
+
+.. _developing_resource_modules:
+
+***********************************
+Developing network resource modules
+***********************************
+
+.. contents::
+ :local:
+ :depth: 2
+
+Understanding network and security resource modules
+===================================================
+
+Network and security devices separate configuration into sections (such as interfaces, VLANs, and so on) that apply to a network or security service. Ansible resource modules take advantage of this to allow users to configure subsections or resources within the device configuration. Resource modules provide a consistent experience across different network and security devices. For example, a network resource module may only update the configuration for a specific portion of the network interfaces, VLANs, ACLs, and so on for a network device. The resource module:
+
+#. Fetches a piece of the configuration (fact gathering), for example, the interfaces configuration.
+#. Converts the returned configuration into key-value pairs.
+#. Places those key-value pairs into an internal independent structured data format.
+
+Now that the configuration data is normalized, the user can update and modify the data and then use the resource module to send the configuration data back to the device. This results in a full round-trip configuration update without the need for manual parsing, data manipulation, and data model management.
+
+The resource module has two top-level keys - ``config`` and ``state``:
+
+* ``config`` defines the resource configuration data model as key-value pairs. The type of the ``config`` option can be ``dict`` or ``list of dict`` based on the resource managed. That is, if the device has a single global configuration, it should be a ``dict`` (for example, a global LLDP configuration). If the device has multiple instances of configuration, it should be of type ``list`` with each element in the list of type ``dict`` (for example, interfaces configuration).
+
+
+* ``state`` defines the action the resource module takes on the end device.
+
+The ``state`` for a new resource module should support the following values (as applicable for the devices that support them):
+
+merged
+ Ansible merges the on-device configuration with the provided configuration in the task.
+
+replaced
+ Ansible replaces the on-device configuration subsection with the provided configuration subsection in the task.
+
+overridden
+ Ansible overrides the on-device configuration for the resource with the provided configuration in the task. Use caution with this state as you could remove your access to the device (for example, by overriding the management interface configuration).
+
+deleted
+ Ansible deletes the on-device configuration subsection and restores any default settings.
+
+gathered
+ Ansible displays the resource details gathered from the network device and accessed with the ``gathered`` key in the result.
+
+rendered
+ Ansible renders the provided configuration in the task in the device-native format (for example, Cisco IOS CLI). Ansible returns this rendered configuration in the ``rendered`` key in the result. Note this state does not communicate with the network device and can be used offline.
+
+parsed
+ Ansible parses the configuration from the ``running_configuration`` option into Ansible structured data in the ``parsed`` key in the result. Note this does not gather the configuration from the network device so this state can be used offline.
+
+
+Modules in Ansible-maintained collections must support these state values. If you develop a module with only "present" and "absent" for state, you may submit it to a community collection.
+
+.. note::
+
+ The states ``rendered``, ``gathered``, and ``parsed`` do not perform any change on the device.
+
+.. seealso::
+
+ `Deep Dive on VLANs Resource Modules for Network Automation <https://www.ansible.com/blog/deep-dive-on-vlans-resource-modules-for-network-automation>`_
+ Walkthrough of how state values are implemented for VLANs.
+
+
+Developing network and security resource modules
+=================================================
+
+The Ansible Engineering team ensures the module design and code pattern within Ansible-maintained collections is uniform across resources and across platforms to give a vendor-independent feel and deliver good quality code. We recommend you use the `resource module builder <https://github.com/ansible-network/resource_module_builder>`_ to develop a resource module.
+
+
+The highlevel process for developing a resource module is:
+
+#. Create and share a resource model design in the `resource module models repository <https://github.com/ansible-network/resource_module_models>`_ as a PR for review.
+#. Download the latest version of the `resource module builder <https://github.com/ansible-network/resource_module_builder>`_.
+#. Run the ``resource module builder`` to create a collection scaffold from your approved resource model.
+#. Write the code to implement your resource module.
+#. Develop integration and unit tests to verify your resource module.
+#. Create a PR to the appropriate collection that you want to add your new resource module to. See :ref:`contributing_maintained_collections` for details on determining the correct collection for your module.
+
+
+Understanding the model and resource module builder
+-----------------------------------------------------
+
+The resource module builder is an Ansible Playbook that helps developers scaffold and maintain an Ansible resource module. It uses a model as the single source of truth for the module. This model is a ``yaml`` file that is used for the module DOCUMENTATION section and the argument spec.
+
+The resource module builder has the following capabilities:
+
+- Uses a defined model to scaffold a resource module directory layout and initial class files.
+- Scaffolds either an Ansible role or a collection.
+- Subsequent uses of the resource module builder will only replace the module arspec and file containing the module docstring.
+- Allows you to store complex examples along side the model in the same directory.
+- Maintains the model as the source of truth for the module and use resource module builder to update the source files as needed.
+- Generates working sample modules for both ``<network_os>_<resource>`` and ``<network_os>_facts``.
+
+Accessing the resource module builder
+-------------------------------------
+
+To access the resource module builder:
+
+1. clone the github repository:
+
+ .. code-block:: bash
+
+ git clone https://github.com/ansible-network/resource_module_builder.git
+
+2. Install the requirements:
+
+ .. code-block:: bash
+
+ pip install -r requirements.txt
+
+Creating a model
+-----------------
+
+You must create a model for your new resource. The model is the single source of truth for both the argspec and docstring, keeping them in sync. Once your model is approved, you can use the resource module builder to generate three items based on the model:
+
+* The scaffold for a new module
+* The argspec for the new module
+* The docstring for the new module
+
+For any subsequent changes to the functionality, update the model first and use the resource module builder to update the module argspec and docstring.
+
+For example, the resource model builder includes the ``myos_interfaces.yml`` sample in the :file:`models` directory, as seen below:
+
+.. code-block:: yaml
+
+ ---
+ GENERATOR_VERSION: '1.0'
+
+ NETWORK_OS: myos
+ RESOURCE: interfaces
+ COPYRIGHT: Copyright 2019 Red Hat
+ LICENSE: gpl-3.0.txt
+
+ DOCUMENTATION: |
+ module: myos_interfaces
+ version_added: 1.0.0
+ short_description: 'Manages <xxxx> attributes of <network_os> <resource>'
+ description: 'Manages <xxxx> attributes of <network_os> <resource>.'
+ author: Ansible Network Engineer
+ notes:
+ - 'Tested against <network_os> <version>'
+ options:
+ config:
+ description: The provided configuration
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ type: str
+ description: The name of the <resource>
+ some_string:
+ type: str
+ description:
+ - The some_string_01
+ choices:
+ - choice_a
+ - choice_b
+ - choice_c
+ default: choice_a
+ some_bool:
+ description:
+ - The some_bool.
+ type: bool
+ some_int:
+ description:
+ - The some_int.
+ type: int
+ version_added: '1.1.0'
+ some_dict:
+ type: dict
+ description:
+ - The some_dict.
+ suboptions:
+ property_01:
+ description:
+ - The property_01
+ type: str
+ state:
+ description:
+ - The state of the configuration after module completion.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ default: merged
+ EXAMPLES:
+ - deleted_example_01.txt
+ - merged_example_01.txt
+ - overridden_example_01.txt
+ - replaced_example_01.txt
+
+Notice that you should include examples for each of the states that the resource supports. The resource module builder also includes these in the sample model.
+
+Share this model as a PR for review at `resource module models repository <https://github.com/ansible-network/resource_module_models>`_. You can also see more model examples at that location.
+
+
+Creating a collection scaffold from a resource model
+----------------------------------------------------
+
+To use the resource module builder to create a collection scaffold from your approved resource model:
+
+.. code-block:: bash
+
+ ansible-playbook -e rm_dest=<destination for modules and module utils> \
+ -e structure=collection \
+ -e collection_org=<collection_org> \
+ -e collection_name=<collection_name> \
+ -e model=<model> \
+ site.yml
+
+Where the parameters are as follows:
+
+- ``rm_dest``: The directory where the resource module builder places the files and directories for the resource module and facts modules.
+- ``structure``: The directory layout type (role or collection)
+
+ - ``role``: Generate a role directory layout.
+ - ``collection``: Generate a collection directory layout.
+
+- ``collection_org``: The organization of the collection, required when `structure=collection`.
+- ``collection_name``: The name of the collection, required when `structure=collection`.
+- ``model``: The path to the model file.
+
+To use the resource module builder to create a role scaffold:
+
+.. code-block:: bash
+
+ ansible-playbook -e rm_dest=<destination for modules and module utils> \
+ -e structure=role \
+ -e model=<model> \
+ site.yml
+
+Examples
+========
+
+Collection directory layout
+---------------------------
+
+This example shows the directory layout for the following:
+
+- ``network_os``: myos
+- ``resource``: interfaces
+
+.. code-block:: bash
+
+ ansible-playbook -e rm_dest=~/github/rm_example \
+ -e structure=collection \
+ -e collection_org=cidrblock \
+ -e collection_name=my_collection \
+ -e model=models/myos/interfaces/myos_interfaces.yml \
+ site.yml
+
+.. code-block:: text
+
+ ├── docs
+ ├── LICENSE.txt
+ ├── playbooks
+ ├── plugins
+ | ├── action
+ | ├── filter
+ | ├── inventory
+ | ├── modules
+ | | ├── __init__.py
+ | | ├── myos_facts.py
+ | | └── myos_interfaces.py
+ | └── module_utils
+ | ├── __init__.py
+ | └── network
+ | ├── __init__.py
+ | └── myos
+ | ├── argspec
+ | | ├── facts
+ | | | ├── facts.py
+ | | | └── __init__.py
+ | | ├── __init__.py
+ | | └── interfaces
+ | | ├── __init__.py
+ | | └── interfaces.py
+ | ├── config
+ | | ├── __init__.py
+ | | └── interfaces
+ | | ├── __init__.py
+ | | └── interfaces.py
+ | ├── facts
+ | | ├── facts.py
+ | | ├── __init__.py
+ | | └── interfaces
+ | | ├── __init__.py
+ | | └── interfaces.py
+ | ├── __init__.py
+ | └── utils
+ | ├── __init__.py
+ | └── utils.py
+ ├── README.md
+ └── roles
+
+
+Role directory layout
+---------------------
+
+This example displays the role directory layout for the following:
+
+- ``network_os``: myos
+- ``resource``: interfaces
+
+.. code-block:: bash
+
+ ansible-playbook -e rm_dest=~/github/rm_example/roles/my_role \
+ -e structure=role \
+ -e model=models/myos/interfaces/myos_interfaces.yml \
+ site.yml
+
+
+.. code-block:: text
+
+ roles
+ └── my_role
+ ├── library
+ │ ├── __init__.py
+ │ ├── myos_facts.py
+ │ └── myos_interfaces.py
+ ├── LICENSE.txt
+ ├── module_utils
+ │ ├── __init__.py
+ │ └── network
+ │ ├── __init__.py
+ │ └── myos
+ │ ├── argspec
+ │ │ ├── facts
+ │ │ │ ├── facts.py
+ │ │ │ └── __init__.py
+ │ │ ├── __init__.py
+ │ │ └── interfaces
+ │ │ ├── __init__.py
+ │ │ └── interfaces.py
+ │ ├── config
+ │ │ ├── __init__.py
+ │ │ └── interfaces
+ │ │ ├── __init__.py
+ │ │ └── interfaces.py
+ │ ├── facts
+ │ │ ├── facts.py
+ │ │ ├── __init__.py
+ │ │ └── interfaces
+ │ │ ├── __init__.py
+ │ │ └── interfaces.py
+ │ ├── __init__.py
+ │ └── utils
+ │ ├── __init__.py
+ │ └── utils.py
+ └── README.md
+
+
+Using the collection
+--------------------
+
+This example shows how to use the generated collection in a playbook:
+
+ .. code-block:: yaml
+
+ ----
+ - hosts: myos101
+ gather_facts: False
+ tasks:
+ - cidrblock.my_collection.myos_interfaces:
+ register: result
+ - debug:
+ var: result
+ - cidrblock.my_collection.myos_facts:
+ - debug:
+ var: ansible_network_resources
+
+
+Using the role
+--------------
+
+This example shows how to use the generated role in a playbook:
+
+.. code-block:: yaml
+
+ - hosts: myos101
+ gather_facts: False
+ roles:
+ - my_role
+
+ - hosts: myos101
+ gather_facts: False
+ tasks:
+ - myos_interfaces:
+ register: result
+ - debug:
+ var: result
+ - myos_facts:
+ - debug:
+ var: ansible_network_resources
+
+
+Resource module structure and workflow
+======================================
+
+The resource module structure includes the following components:
+
+Module
+ * ``library/<ansible_network_os>_<resource>.py``.
+ * Imports the ``module_utils`` resource package and calls ``execute_module`` API:
+
+ .. code-block:: text
+
+ def main():
+ result = <resource_package>(module).execute_module()
+
+Module argspec
+ * ``module_utils/<ansible_network_os>/argspec/<resource>/``.
+ * Argspec for the resource.
+
+Facts
+ * ``module_utils/<ansible_network_os>/facts/<resource>/``.
+ * Populate facts for the resource.
+ * Entry in ``module_utils/<ansible_network_os>/facts/facts.py`` for ``get_facts`` API to keep ``<ansible_network_os>_facts`` module and facts gathered for the resource module in sync for every subset.
+ * Entry of Resource subset in FACTS_RESOURCE_SUBSETS list in ``module_utils/<ansible_network_os>/facts/facts.py`` to make facts collection work.
+
+Module package in module_utils
+ * ``module_utils/<ansible_network_os>/<config>/<resource>/``.
+ * Implement ``execute_module`` API that loads the configuration to device and generates the result with ``changed``, ``commands``, ``before`` and ``after`` keys.
+ * Call ``get_facts`` API that returns the ``<resource>`` configuration facts or return the difference if the device has onbox diff support.
+ * Compare facts gathered and given key-values if diff is not supported.
+ * Generate final configuration.
+
+Utils
+ * ``module_utils/<ansible_network_os>/utils``.
+ * Utilities for the ``<ansible_network_os>`` platform.
+
+.. _tox_resource_modules:
+
+Running ``ansible-test sanity`` and ``tox`` on resource modules
+================================================================
+
+You should run ``ansible-test sanity`` and ``tox -elinters`` from the collection root directory before pushing your PR to an Ansible-maintained collection. The CI runs both and will fail if these tests fail. See :ref:`developing_testing` for details on ``ansible-test sanity``.
+
+To install the necessary packages:
+
+#. Ensure you have a valid Ansible development environment configured. See :ref:`environment_setup` for details.
+#. Run ``pip install -r requirements.txt`` from the collection root directory.
+
+
+ Running ``tox -elinters``:
+
+ * Reads :file:`tox.ini` from the collection root directory and installs required dependencies (such as ``black`` and ``flake8``).
+ * Runs these with preconfigured options (such as line-length and ignores.)
+ * Runs ``black`` in check mode to show which files will be formatted without actually formatting them.
+
+Testing resource modules
+========================
+
+The tests rely on a role generated by the resource module builder. After changes to the resource module builder, the role should be regenerated and the tests modified and run as needed. To generate the role after changes:
+
+.. code-block:: bash
+
+ rm -rf rmb_tests/roles/my_role
+ ansible-playbook -e rm_dest=./rmb_tests/roles/my_role \
+ -e structure=role \
+ -e model=models/myos/interfaces/myos_interfaces.yml \
+ site.yml
+
+
+.. _testing_resource_modules:
+
+Resource module integration tests
+----------------------------------
+
+High-level integration test requirements for new resource modules are as follows:
+
+#. Write a test case for every state.
+#. Write additional test cases to test the behavior of the module when an empty ``config.yaml`` is given.
+#. Add a round trip test case. This involves a ``merge`` operation, followed by ``gather_facts``, a ``merge`` update with additional configuration, and then reverting back to the base configuration using the previously gathered facts with the ``state`` set to ``overridden``.
+#. Wherever applicable, assertions should check after and before ``dicts`` against a hard coded Source of Truth.
+
+.. _using_zuul_resource_modules:
+
+We use Zuul as the CI to run the integration test.
+
+* To view the report, click :guilabel:`Details` on the CI comment in the PR
+* To view a failure report, click :guilabel:`ansible/check` and select the failed test.
+* To view logs while the test is running, check for your PR number in the `Zuul status board <https://dashboard.zuul.ansible.com/t/ansible/status>`_.
+* To fix static test failure locally, run the :command:`tox -e black` **inside the root folder of collection**.
+
+To view The Ansible run logs and debug test failures:
+
+#. Click the failed job to get the summary, and click :guilabel:`Logs` for the log.
+#. Click :guilabel:`console` and scroll down to find the failed test.
+#. Click :guilabel:`>` next to the failed test for complete details.
+
+
+Integration test structure
+...........................
+
+Each test case should generally follow this pattern:
+
+* setup —> test —> assert —> test again (for idempotency) —> assert —> tear down (if needed) -> done. This keeps test playbooks from becoming monolithic and difficult to troubleshoot.
+* Include a name for each task that is not an assertion. You can add names to assertions as well, but it is easier to identify the broken task within a failed test if you add a name for each task.
+* Files containing test cases must end in ``.yaml``
+
+Implementation
+..............
+
+For platforms that support ``connection: local`` *and* ``connection: network_cli`` use the following guidance:
+
+* Name the :file:`targets/` directories after the module name.
+* The :file:`main.yaml` file should just reference the transport.
+
+The following example walks through the integration tests for the ``vyos.vyos.vyos_l3_interfaces`` module in the `vyos.vyos <https://github.com/ansible-collections/vyos.vyos/tree/main/tests/integration>`_ collection:
+
+``test/integration/targets/vyos_l3_interfaces/tasks/main.yaml``
+
+.. code-block:: yaml
+
+ ---
+ - import_tasks: cli.yaml
+ tags:
+ - cli
+
+``test/integration/targets/vyos_l3_interfaces/tasks/cli.yaml``
+
+.. code-block:: yaml
+
+ ---
+ - name: collect all cli test cases
+ find:
+ paths: "{{ role_path }}/tests/cli"
+ patterns: "{{ testcase }}.yaml"
+ register: test_cases
+ delegate_to: localhost
+
+ - name: set test_items
+ set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
+
+ - name: run test cases (connection=network_cli)
+ include_tasks:
+ file: "{{ test_case_to_run }}"
+ vars:
+ ansible_connection: network_cli
+ with_items: "{{ test_items }}"
+ loop_control:
+ loop_var: test_case_to_run
+
+ - name: run test case (connection=local)
+ include_tasks:
+ file: "{{ test_case_to_run }}"
+ vars:
+ ansible_connection: local
+ ansible_become: no
+ with_first_found: "{{ test_items }}"
+ loop_control:
+ loop_var: test_case_to_run
+
+``test/integration/targets/vyos_l3_interfaces/tests/cli/overridden.yaml``
+
+.. code-block:: yaml
+
+ ---
+ - debug:
+ msg: START vyos_l3_interfaces merged integration tests on connection={{ ansible_connection
+ }}
+
+ - import_tasks: _remove_config.yaml
+
+ - block:
+
+ - import_tasks: _populate.yaml
+
+ - name: Overrides all device configuration with provided configuration
+ register: result
+ vyos.vyos.vyos_l3_interfaces: &id001
+ config:
+
+ - name: eth0
+ ipv4:
+
+ - address: dhcp
+
+ - name: eth1
+ ipv4:
+
+ - address: 192.0.2.15/24
+ state: overridden
+
+ - name: Assert that before dicts were correctly generated
+ assert:
+ that:
+ - "{{ populate | symmetric_difference(result['before']) |length == 0 }}"
+
+ - name: Assert that correct commands were generated
+ assert:
+ that:
+ - "{{ overridden['commands'] | symmetric_difference(result['commands'])\
+ \ |length == 0 }}"
+
+ - name: Assert that after dicts were correctly generated
+ assert:
+ that:
+ - "{{ overridden['after'] | symmetric_difference(result['after']) |length\
+ \ == 0 }}"
+
+ - name: Overrides all device configuration with provided configurations (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_l3_interfaces: *id001
+
+ - name: Assert that the previous task was idempotent
+ assert:
+ that:
+ - result['changed'] == false
+
+ - name: Assert that before dicts were correctly generated
+ assert:
+ that:
+ - "{{ overridden['after'] | symmetric_difference(result['before']) |length\
+ \ == 0 }}"
+ always:
+
+ - import_tasks: _remove_config.yaml
+
+
+Detecting test resources at runtime
+...................................
+
+Your tests should detect resources (such as interfaces) at runtime rather than hard-coding them into the test. This allows the test to run on a variety of systems.
+
+For example:
+
+.. code-block:: yaml
+
+ - name: Collect interface list
+ connection: ansible.netcommon.network_cli
+ register: intout
+ cisco.nxos.nxos_command:
+ commands:
+ - show interface brief | json
+
+ - set_fact:
+ intdataraw: "{{ intout.stdout_lines[0]['TABLE_interface']['ROW_interface'] }}"
+
+ - set_fact:
+ nxos_int1: '{{ intdataraw[1].interface }}'
+
+ - set_fact:
+ nxos_int2: '{{ intdataraw[2].interface }}'
+
+ - set_fact:
+ nxos_int3: '{{ intdataraw[3].interface }}'
+
+
+See the complete test example of this at https://github.com/ansible-collections/cisco.nxos/blob/main/tests/integration/targets/prepare_nxos_tests/tasks/main.yml.
+
+
+Running network integration tests
+..................................
+
+Ansible uses Zuul to run an integration test suite on every PR, including new tests introduced by that PR. To find and fix problems in network modules, run the network integration test locally before you submit a PR.
+
+
+First, create an inventory file that points to your test machines. The inventory group should match the platform name (for example, ``eos``, ``ios``):
+
+.. code-block:: bash
+
+ cd test/integration
+ cp inventory.network.template inventory.networking
+ ${EDITOR:-vi} inventory.networking
+ # Add in machines for the platform(s) you wish to test
+
+To run these network integration tests, use ``ansible-test network-integration --inventory </path/to/inventory> <tests_to_run>``:
+
+.. code-block:: console
+
+ ansible-test network-integration --inventory ~/myinventory -vvv vyos_facts
+ ansible-test network-integration --inventory ~/myinventory -vvv vyos_.*
+
+
+
+To run all network tests for a particular platform:
+
+.. code-block:: bash
+
+ ansible-test network-integration --inventory /path/to-collection-module/test/integration/inventory.networking vyos_.*
+
+This example will run against all ``vyos`` modules. Note that ``vyos_.*`` is a regex match, not a bash wildcard - include the `.` if you modify this example.
+
+To run integration tests for a specific module:
+
+.. code-block:: bash
+
+ ansible-test network-integration --inventory /path/to-collection-module/test/integration/inventory.networking vyos_l3_interfaces
+
+To run a single test case on a specific module:
+
+.. code-block:: bash
+
+ # Only run vyos_l3_interfaces/tests/cli/gathered.yaml
+ ansible-test network-integration --inventory /path/to-collection-module/test/integration/inventory.networking vyos_l3_interfaces --testcase gathered
+
+To run integration tests for a specific transport:
+
+.. code-block:: bash
+
+ # Only run nxapi test
+ ansible-test network-integration --inventory /path/to-collection-module/test/integration/inventory.networking --tags="nxapi" nxos_.*
+
+ # Skip any cli tests
+ ansible-test network-integration --inventory /path/to-collection-module/test/integration/inventory.networking --skip-tags="cli" nxos_.*
+
+See `test/integration/targets/nxos_bgp/tasks/main.yaml <https://github.com/ansible-collections/cisco.nxos/blob/main/tests/integration/targets/nxos_bgp/tasks/main.yaml>`_ for how this is implemented in the tests.
+
+For more options:
+
+.. code-block:: bash
+
+ ansible-test network-integration --help
+
+If you need additional help or feedback, reach out in the ``#ansible-network`` chat channel (using Matrix at ansible.im or using IRC at `irc.libera.chat <https://libera.chat/>`_).
+
+Unit test requirements
+-----------------------
+
+High-level unit test requirements that new resource modules should follow:
+
+#. Write test cases for all the states with all possible combinations of config values.
+#. Write test cases to test the error conditions ( negative scenarios).
+#. Check the value of ``changed`` and ``commands`` keys in every test case.
+
+We run all unit test cases on our Zuul test suite, on the latest python version supported by our CI setup.
+
+Use the :ref:`same procedure <using_zuul_resource_modules>` as the integration tests to view Zuul unit tests reports and logs.
+
+See :ref:`unit module testing <testing_units_modules>` for general unit test details.
+
+.. end of cut n .. parsed-literal::
+
+
+Example: Unit testing Ansible network resource modules
+======================================================
+
+
+This section walks through an example of how to develop unit tests for Ansible resource
+modules.
+
+See :ref:`testing_units` and :ref:`testing_units_modules` for general documentation on Ansible unit tests for modules.
+Please read those pages first to understand unit tests and why and when you should use them.
+
+
+Using mock objects to unit test Ansible network resource modules
+----------------------------------------------------------------
+
+
+`Mock objects <https://docs.python.org/3/library/unittest.mock.html>`_ can be very
+useful in building unit tests for special or difficult cases, but they can also
+lead to complex and confusing coding situations. One good use for mocks would be to
+simulate an API. The ``mock`` Python package is bundled with Ansible (use
+``import units.compat.mock``).
+
+You can mock the device connection and output from the device as follows:
+
+.. code-block:: python
+
+ self.mock_get_config = patch( "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config"
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config"
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection"
+ )
+ self.get_resource_connection_config = (self.mock_get_resource_connection_config.start())
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection"
+ )
+ self.get_resource_connection_facts = (self.mock_get_resource_connection_facts.start())
+
+ self.mock_edit_config = patch(
+ "ansible_collections.arista.eos.plugins.module_utils.network.eos.providers.providers.CliProvider.edit_config"
+ )
+ self.edit_config = self.mock_edit_config.start()
+
+ self.mock_execute_show_command = patch(
+ "ansible_collections.arista.eos.plugins.module_utils.network.eos.facts.l2_interfaces.l2_interfaces.L2_interfacesFacts.get_device_data"
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+
+The facts file of the module now includes a new method, ``get_device_data``. Call ``get_device_data`` here to emulate the device output.
+
+
+Mocking device data
+-----------------------
+
+To mock fetching results from devices or provide other complex data structures that
+come from external libraries, you can use ``fixtures`` to read in pre-generated data. The text files for this pre-generated data live in ``test/units/modules/network/PLATFORM/fixtures/``. See for example the `eos_l2_interfaces.cfg file <https://github.com/ansible-collections/arista.eos/blob/main/tests/unit/modules/network/eos/fixtures/eos_l2_interfaces_config.cfg>`_.
+
+Load data using the ``load_fixture`` method and set this data as the return value of the
+``get_device_data`` method in the facts file:
+
+.. code-block:: python
+
+ def load_fixtures(self, commands=None, transport='cli'):
+ def load_from_file(*args, **kwargs):
+ return load_fixture('eos_l2_interfaces_config.cfg')
+ self.execute_show_command.side_effect = load_from_file
+
+See the unit test file `test_eos_l2_interfaces <https://github.com/ansible-collections/arista.eos/blob/main/tests/unit/modules/network/eos/test_eos_l2_interfaces.py>`_
+for a practical example.
+
+
+.. seealso::
+
+ :ref:`testing_units`
+ Deep dive into developing unit tests for Ansible modules
+ :ref:`testing_running_locally`
+ Running tests locally including gathering and reporting coverage data
+ :ref:`developing_modules_general`
+ Get started developing a module
diff --git a/docs/docsite/rst/network/dev_guide/documenting_modules_network.rst b/docs/docsite/rst/network/dev_guide/documenting_modules_network.rst
new file mode 100644
index 0000000..99ba7a9
--- /dev/null
+++ b/docs/docsite/rst/network/dev_guide/documenting_modules_network.rst
@@ -0,0 +1,52 @@
+
+.. _documenting_modules_network:
+
+*********************************
+Documenting new network platforms
+*********************************
+
+.. contents::
+ :local:
+
+When you create network modules for a new platform, or modify the connections provided by an existing network platform (such as ``network_cli`` and ``httpapi``), you also need to update the :ref:`settings_by_platform` table and add or modify the Platform Options file for your platform.
+
+You should already have documented each module as described in :ref:`developing_modules_documenting`.
+
+Modifying the platform options table
+====================================
+
+The :ref:`settings_by_platform` table is a convenient summary of the connections options provided by each network platform that has modules in Ansible. Add a row for your platform to this table, in alphabetical order. For example:
+
+.. code-block:: text
+
+ +-------------------+-------------------------+-------------+---------+---------+----------+
+ | My OS | ``myos`` | ✓ | ✓ | | ✓ |
+
+Ensure that the table stays formatted correctly. That is:
+
+* Each row is inserted in alphabetical order.
+* The cell division ``|`` markers line up with the ``+`` markers.
+* The check marks appear only for the connection types provided by the network modules.
+
+
+
+Adding a platform-specific options section
+==========================================
+
+The platform- specific sections are individual ``.rst`` files that provide more detailed information for the users of your network platform modules. Name your new file ``platform_<name>.rst`` (for example, ``platform_myos.rst``). The platform name should match the module prefix. See `platform_eos.rst <https://github.com/ansible/ansible/blob/devel/docs/docsite/rst/network/user_guide/platform_eos.rst>`_ and :ref:`eos_platform_options` for an example of the details you should provide in your platform-specific options section.
+
+Your platform-specific section should include the following:
+
+* **Connections available table** - a deeper dive into each connection type, including details on credentials, indirect access, connections settings, and enable mode.
+* **How to use each connection type** - with working examples of each connection type.
+
+If your network platform supports SSH connections, also include the following at the bottom of your ``.rst`` file:
+
+.. code-block:: text
+
+ .. include:: shared_snippets/SSH_warning.txt
+
+Adding your new file to the table of contents
+=============================================
+
+As a final step, add your new file in alphabetical order in the ``platform_index.rst`` file. You should then build the documentation to verify your additions. See :ref:`community_documentation_contributions` for more details.
diff --git a/docs/docsite/rst/network/dev_guide/index.rst b/docs/docsite/rst/network/dev_guide/index.rst
new file mode 100644
index 0000000..5f0e792
--- /dev/null
+++ b/docs/docsite/rst/network/dev_guide/index.rst
@@ -0,0 +1,32 @@
+.. _network_developer_guide:
+
+**********************************
+Network Developer Guide
+**********************************
+
+Welcome to the Developer Guide for Ansible Network Automation!
+
+**Who should use this guide?**
+
+If you want to extend Ansible for Network Automation by creating a module or plugin, this guide is for you. This guide is specific to networking. You should already be familiar with how to create, test, and document modules and plugins, as well as the prerequisites for getting your module or plugin accepted into the main Ansible repository. See the :ref:`developer_guide` for details. Before you proceed, please read:
+
+* How to :ref:`add a custom plugin or module locally <developing_locally>`.
+* How to figure out if :ref:`developing a module is the right approach <module_dev_should_you>` for my use case.
+* How to :ref:`set up my Python development environment <environment_setup>`.
+* How to :ref:`get started writing a module <developing_modules_general>`.
+
+
+Find the network developer task that best describes what you want to do:
+
+ * I want to :ref:`develop a network resource module <developing_resource_modules>`.
+ * I want to :ref:`develop a network connection plugin <developing_plugins_network>`.
+ * I want to :ref:`document my set of modules for a network platform <documenting_modules_network>`.
+
+If you prefer to read the entire guide, here's a list of the pages in order.
+
+.. toctree::
+ :maxdepth: 1
+
+ developing_resource_modules_network
+ developing_plugins_network
+ documenting_modules_network
diff --git a/docs/docsite/rst/network/getting_started/basic_concepts.rst b/docs/docsite/rst/network/getting_started/basic_concepts.rst
new file mode 100644
index 0000000..980b144
--- /dev/null
+++ b/docs/docsite/rst/network/getting_started/basic_concepts.rst
@@ -0,0 +1,10 @@
+**************
+Basic Concepts
+**************
+
+These concepts are common to all uses of Ansible, including network automation. You need to understand them to use Ansible for network automation. This basic introduction provides the background you need to follow the examples in this guide.
+
+.. contents::
+ :local:
+
+.. include:: ../../shared_snippets/basic_concepts.txt
diff --git a/docs/docsite/rst/network/getting_started/first_inventory.rst b/docs/docsite/rst/network/getting_started/first_inventory.rst
new file mode 100644
index 0000000..1562ed4
--- /dev/null
+++ b/docs/docsite/rst/network/getting_started/first_inventory.rst
@@ -0,0 +1,431 @@
+***********************************************
+Build Your Inventory
+***********************************************
+
+Running a playbook without an inventory requires several command-line flags. Also, running a playbook against a single device is not a huge efficiency gain over making the same change manually. The next step to harnessing the full power of Ansible is to use an inventory file to organize your managed nodes into groups with information like the ``ansible_network_os`` and the SSH user. A fully-featured inventory file can serve as the source of truth for your network. Using an inventory file, a single playbook can maintain hundreds of network devices with a single command. This page shows you how to build an inventory file, step by step.
+
+.. contents::
+ :local:
+
+Basic inventory
+==================================================
+
+First, group your inventory logically. Best practice is to group servers and network devices by their What (application, stack or microservice), Where (datacenter or region), and When (development stage):
+
+- **What**: db, web, leaf, spine
+- **Where**: east, west, floor_19, building_A
+- **When**: dev, test, staging, prod
+
+Avoid spaces, hyphens, and preceding numbers (use ``floor_19``, not ``19th_floor``) in your group names. Group names are case sensitive.
+
+This tiny example data center illustrates a basic group structure. You can group groups using the syntax ``[metagroupname:children]`` and listing groups as members of the metagroup. Here, the group ``network`` includes all leafs and all spines; the group ``datacenter`` includes all network devices plus all webservers.
+
+.. code-block:: yaml
+
+ ---
+
+ leafs:
+ hosts:
+ leaf01:
+ ansible_host: 10.16.10.11
+ leaf02:
+ ansible_host: 10.16.10.12
+
+ spines:
+ hosts:
+ spine01:
+ ansible_host: 10.16.10.13
+ spine02:
+ ansible_host: 10.16.10.14
+
+ network:
+ children:
+ leafs:
+ spines:
+
+ webservers:
+ hosts:
+ webserver01:
+ ansible_host: 10.16.10.15
+ webserver02:
+ ansible_host: 10.16.10.16
+
+ datacenter:
+ children:
+ network:
+ webservers:
+
+
+
+You can also create this same inventory in INI format.
+
+.. code-block:: ini
+
+ [leafs]
+ leaf01
+ leaf02
+
+ [spines]
+ spine01
+ spine02
+
+ [network:children]
+ leafs
+ spines
+
+ [webservers]
+ webserver01
+ webserver02
+
+ [datacenter:children]
+ network
+ webservers
+
+
+Add variables to the inventory
+================================================================================
+
+Next, you can set values for many of the variables you needed in your first Ansible command in the inventory, so you can skip them in the ``ansible-playbook`` command. In this example, the inventory includes each network device's IP, OS, and SSH user. If your network devices are only accessible by IP, you must add the IP to the inventory file. If you access your network devices using hostnames, the IP is not necessary.
+
+.. code-block:: yaml
+
+ ---
+
+ leafs:
+ hosts:
+ leaf01:
+ ansible_host: 10.16.10.11
+ ansible_network_os: vyos.vyos.vyos
+ ansible_user: my_vyos_user
+ leaf02:
+ ansible_host: 10.16.10.12
+ ansible_network_os: vyos.vyos.vyos
+ ansible_user: my_vyos_user
+
+ spines:
+ hosts:
+ spine01:
+ ansible_host: 10.16.10.13
+ ansible_network_os: vyos.vyos.vyos
+ ansible_user: my_vyos_user
+ spine02:
+ ansible_host: 10.16.10.14
+ ansible_network_os: vyos.vyos.vyos
+ ansible_user: my_vyos_user
+
+ network:
+ children:
+ leafs:
+ spines:
+
+ webservers:
+ hosts:
+ webserver01:
+ ansible_host: 10.16.10.15
+ ansible_user: my_server_user
+ webserver02:
+ ansible_host: 10.16.10.16
+ ansible_user: my_server_user
+
+ datacenter:
+ children:
+ network:
+ webservers:
+
+
+Group variables within inventory
+================================================================================
+
+When devices in a group share the same variable values, such as OS or SSH user, you can reduce duplication and simplify maintenance by consolidating these into group variables:
+
+.. code-block:: yaml
+
+ ---
+
+ leafs:
+ hosts:
+ leaf01:
+ ansible_host: 10.16.10.11
+ leaf02:
+ ansible_host: 10.16.10.12
+ vars:
+ ansible_network_os: vyos.vyos.vyos
+ ansible_user: my_vyos_user
+
+ spines:
+ hosts:
+ spine01:
+ ansible_host: 10.16.10.13
+ spine02:
+ ansible_host: 10.16.10.14
+ vars:
+ ansible_network_os: vyos.vyos.vyos
+ ansible_user: my_vyos_user
+
+ network:
+ children:
+ leafs:
+ spines:
+
+ webservers:
+ hosts:
+ webserver01:
+ ansible_host: 10.16.10.15
+ webserver02:
+ ansible_host: 10.16.10.16
+ vars:
+ ansible_user: my_server_user
+
+ datacenter:
+ children:
+ network:
+ webservers:
+
+Variable syntax
+================================================================================
+
+The syntax for variable values is different in inventory, in playbooks, and in the ``group_vars`` files, which are covered below. Even though playbook and ``group_vars`` files are both written in YAML, you use variables differently in each.
+
+- In an ini-style inventory file you **must** use the syntax ``key=value`` for variable values: ``ansible_network_os=vyos.vyos.vyos``.
+- In any file with the ``.yml`` or ``.yaml`` extension, including playbooks and ``group_vars`` files, you **must** use YAML syntax: ``key: value``.
+
+- In ``group_vars`` files, use the full ``key`` name: ``ansible_network_os: vyos.vyos.vyos``.
+- In playbooks, use the short-form ``key`` name, which drops the ``ansible`` prefix: ``network_os: vyos.vyos.vyos``.
+
+
+Group inventory by platform
+================================================================================
+
+As your inventory grows, you may want to group devices by platform. This allows you to specify platform-specific variables easily for all devices on that platform:
+
+.. code-block:: yaml
+
+ ---
+
+ leafs:
+ hosts:
+ leaf01:
+ ansible_host: 10.16.10.11
+ leaf02:
+ ansible_host: 10.16.10.12
+
+ spines:
+ hosts:
+ spine01:
+ ansible_host: 10.16.10.13
+ spine02:
+ ansible_host: 10.16.10.14
+
+ network:
+ children:
+ leafs:
+ spines:
+ vars:
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: vyos.vyos.vyos
+ ansible_user: my_vyos_user
+
+ webservers:
+ hosts:
+ webserver01:
+ ansible_host: 10.16.10.15
+ webserver02:
+ ansible_host: 10.16.10.16
+ vars:
+ ansible_user: my_server_user
+
+ datacenter:
+ children:
+ network:
+ webservers:
+
+With this setup, you can run ``first_playbook.yml`` with only two flags:
+
+.. code-block:: console
+
+ ansible-playbook -i inventory.yml -k first_playbook.yml
+
+With the ``-k`` flag, you provide the SSH password(s) at the prompt. Alternatively, you can store SSH and other secrets and passwords securely in your group_vars files with ``ansible-vault``. See :ref:`network_vault` for details.
+
+Verifying the inventory
+=========================
+
+You can use the :ref:`ansible-inventory` CLI command to display the inventory as Ansible sees it.
+
+.. code-block:: console
+
+ $ ansible-inventory -i test.yml --list
+ {
+ "_meta": {
+ "hostvars": {
+ "leaf01": {
+ "ansible_connection": "ansible.netcommon.network_cli",
+ "ansible_host": "10.16.10.11",
+ "ansible_network_os": "vyos.vyos.vyos",
+ "ansible_user": "my_vyos_user"
+ },
+ "leaf02": {
+ "ansible_connection": "ansible.netcommon.network_cli",
+ "ansible_host": "10.16.10.12",
+ "ansible_network_os": "vyos.vyos.vyos",
+ "ansible_user": "my_vyos_user"
+ },
+ "spine01": {
+ "ansible_connection": "ansible.netcommon.network_cli",
+ "ansible_host": "10.16.10.13",
+ "ansible_network_os": "vyos.vyos.vyos",
+ "ansible_user": "my_vyos_user"
+ },
+ "spine02": {
+ "ansible_connection": "ansible.netcommon.network_cli",
+ "ansible_host": "10.16.10.14",
+ "ansible_network_os": "vyos.vyos.vyos",
+ "ansible_user": "my_vyos_user"
+ },
+ "webserver01": {
+ "ansible_host": "10.16.10.15",
+ "ansible_user": "my_server_user"
+ },
+ "webserver02": {
+ "ansible_host": "10.16.10.16",
+ "ansible_user": "my_server_user"
+ }
+ }
+ },
+ "all": {
+ "children": [
+ "datacenter",
+ "ungrouped"
+ ]
+ },
+ "datacenter": {
+ "children": [
+ "network",
+ "webservers"
+ ]
+ },
+ "leafs": {
+ "hosts": [
+ "leaf01",
+ "leaf02"
+ ]
+ },
+ "network": {
+ "children": [
+ "leafs",
+ "spines"
+ ]
+ },
+ "spines": {
+ "hosts": [
+ "spine01",
+ "spine02"
+ ]
+ },
+ "webservers": {
+ "hosts": [
+ "webserver01",
+ "webserver02"
+ ]
+ }
+ }
+
+.. _network_vault:
+
+Protecting sensitive variables with ``ansible-vault``
+================================================================================
+
+The ``ansible-vault`` command provides encryption for files and/or individual variables like passwords. This tutorial will show you how to encrypt a single SSH password. You can use the commands below to encrypt other sensitive information, such as database passwords, privilege-escalation passwords and more.
+
+First you must create a password for ansible-vault itself. It is used as the encryption key, and with this you can encrypt dozens of different passwords across your Ansible project. You can access all those secrets (encrypted values) with a single password (the ansible-vault password) when you run your playbooks. Here's a simple example.
+
+1. Create a file and write your password for ansible-vault to it:
+
+.. code-block:: console
+
+ echo "my-ansible-vault-pw" > ~/my-ansible-vault-pw-file
+
+2. Create the encrypted ssh password for your VyOS network devices, pulling your ansible-vault password from the file you just created:
+
+.. code-block:: console
+
+ ansible-vault encrypt_string --vault-id my_user@~/my-ansible-vault-pw-file 'VyOS_SSH_password' --name 'ansible_password'
+
+If you prefer to type your ansible-vault password rather than store it in a file, you can request a prompt:
+
+.. code-block:: console
+
+ ansible-vault encrypt_string --vault-id my_user@prompt 'VyOS_SSH_password' --name 'ansible_password'
+
+and type in the vault password for ``my_user``.
+
+The :option:`--vault-id <ansible-playbook --vault-id>` flag allows different vault passwords for different users or different levels of access. The output includes the user name ``my_user`` from your ``ansible-vault`` command and uses the YAML syntax ``key: value``:
+
+.. code-block:: yaml
+
+ ansible_password: !vault |
+ $ANSIBLE_VAULT;1.2;AES256;my_user
+ 66386134653765386232383236303063623663343437643766386435663632343266393064373933
+ 3661666132363339303639353538316662616638356631650a316338316663666439383138353032
+ 63393934343937373637306162366265383461316334383132626462656463363630613832313562
+ 3837646266663835640a313164343535316666653031353763613037656362613535633538386539
+ 65656439626166666363323435613131643066353762333232326232323565376635
+ Encryption successful
+
+This is an example using an extract from a YAML inventory, as the INI format does not support inline vaults:
+
+.. code-block:: yaml
+
+ ...
+
+ vyos: # this is a group in yaml inventory, but you can also do under a host
+ vars:
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: vyos.vyos.vyos
+ ansible_user: my_vyos_user
+ ansible_password: !vault |
+ $ANSIBLE_VAULT;1.2;AES256;my_user
+ 66386134653765386232383236303063623663343437643766386435663632343266393064373933
+ 3661666132363339303639353538316662616638356631650a316338316663666439383138353032
+ 63393934343937373637306162366265383461316334383132626462656463363630613832313562
+ 3837646266663835640a313164343535316666653031353763613037656362613535633538386539
+ 65656439626166666363323435613131643066353762333232326232323565376635
+
+ ...
+
+To use an inline vaulted variables with an INI inventory you need to store it in a 'vars' file in YAML format,
+it can reside in host_vars/ or group_vars/ to be automatically picked up or referenced from a play through ``vars_files`` or ``include_vars``.
+
+To run a playbook with this setup, drop the ``-k`` flag and add a flag for your ``vault-id``:
+
+.. code-block:: console
+
+ ansible-playbook -i inventory --vault-id my_user@~/my-ansible-vault-pw-file first_playbook.yml
+
+Or with a prompt instead of the vault password file:
+
+.. code-block:: console
+
+ ansible-playbook -i inventory --vault-id my_user@prompt first_playbook.yml
+
+To see the original value, you can use the debug module. Please note if your YAML file defines the `ansible_connection` variable (as we used in our example), it will take effect when you execute the command below. To prevent this, please make a copy of the file without the ansible_connection variable.
+
+.. code-block:: console
+
+ cat vyos.yml | grep -v ansible_connection >> vyos_no_connection.yml
+
+ ansible localhost -m debug -a var="ansible_password" -e "@vyos_no_connection.yml" --ask-vault-pass
+ Vault password:
+
+ localhost | SUCCESS => {
+ "ansible_password": "VyOS_SSH_password"
+ }
+
+
+.. warning::
+
+ Vault content can only be decrypted with the password that was used to encrypt it. If you want to stop using one password and move to a new one, you can update and re-encrypt existing vault content with ``ansible-vault rekey myfile``, then provide the old password and the new password. Copies of vault content still encrypted with the old password can still be decrypted with old password.
+
+For more details on building inventory files, see :ref:`the introduction to inventory<intro_inventory>`; for more details on ansible-vault, see :ref:`the full Ansible Vault documentation<vault>`.
+
+Now that you understand the basics of commands, playbooks, and inventory, it's time to explore some more complex Ansible Network examples.
diff --git a/docs/docsite/rst/network/getting_started/first_playbook.rst b/docs/docsite/rst/network/getting_started/first_playbook.rst
new file mode 100644
index 0000000..15a4ed1
--- /dev/null
+++ b/docs/docsite/rst/network/getting_started/first_playbook.rst
@@ -0,0 +1,212 @@
+
+.. _first_network_playbook:
+
+***************************************************
+Run Your First Command and Playbook
+***************************************************
+
+Put the concepts you learned to work with this quick tutorial. Install Ansible, execute a network configuration command manually, execute the same command with Ansible, then create a playbook so you can execute the command any time on multiple network devices.
+
+.. contents::
+ :local:
+
+Prerequisites
+==================================================
+
+Before you work through this tutorial you need:
+
+- Ansible 2.10 (or higher) installed
+- One or more network devices that are compatible with Ansible
+- Basic Linux command line knowledge
+- Basic knowledge of network switch & router configuration
+
+Install Ansible
+==================================================
+
+Install Ansible using your preferred method. See :ref:`installation_guide`. Then return to this tutorial.
+
+Confirm the version of Ansible (must be >= 2.10):
+
+.. code-block:: bash
+
+ ansible --version
+
+
+Establish a manual connection to a managed node
+==================================================
+
+To confirm your credentials, connect to a network device manually and retrieve its configuration. Replace the sample user and device name with your real credentials. For example, for a VyOS router:
+
+.. code-block:: bash
+
+ ssh my_vyos_user@vyos.example.net
+ show config
+ exit
+
+This manual connection also establishes the authenticity of the network device, adding its RSA key fingerprint to your list of known hosts. (If you have connected to the device before, you have already established its authenticity.)
+
+
+Run your first network Ansible command
+==================================================
+
+Instead of manually connecting and running a command on the network device, you can retrieve its configuration with a single, stripped-down Ansible command:
+
+.. code-block:: bash
+
+ ansible all -i vyos.example.net, -c ansible.netcommon.network_cli -u my_vyos_user -k -m vyos.vyos.vyos_facts -e ansible_network_os=vyos.vyos.vyos
+
+The flags in this command set seven values:
+ - the host group(s) to which the command should apply (in this case, all)
+ - the inventory (-i, the device or devices to target - without the trailing comma -i points to an inventory file)
+ - the connection method (-c, the method for connecting and executing ansible)
+ - the user (-u, the username for the SSH connection)
+ - the SSH connection method (-k, please prompt for the password)
+ - the module (-m, the Ansible module to run, using the fully qualified collection name (FQCN))
+ - an extra variable ( -e, in this case, setting the network OS value)
+
+NOTE: If you use ``ssh-agent`` with ssh keys, Ansible loads them automatically. You can omit ``-k`` flag.
+
+.. note::
+
+ If you are running Ansible in a virtual environment, you will also need to add the variable ``ansible_python_interpreter=/path/to/venv/bin/python``
+
+
+Create and run your first network Ansible Playbook
+==================================================
+
+If you want to run this command every day, you can save it in a playbook and run it with ``ansible-playbook`` instead of ``ansible``. The playbook can store a lot of the parameters you provided with flags at the command line, leaving less to type at the command line. You need two files for this - a playbook and an inventory file.
+
+1. Download :download:`first_playbook.yml <sample_files/first_playbook.yml>`, which looks like this:
+
+.. literalinclude:: sample_files/first_playbook.yml
+ :language: YAML
+
+The playbook sets three of the seven values from the command line above: the group (``hosts: all``), the connection method (``connection: ansible.netcommon.network_cli``) and the module (in each task). With those values set in the playbook, you can omit them on the command line. The playbook also adds a second task to show the config output. When a module runs in a playbook, the output is held in memory for use by future tasks instead of written to the console. The debug task here lets you see the results in your shell.
+
+2. Run the playbook with the command:
+
+.. code-block:: bash
+
+ ansible-playbook -i vyos.example.net, -u ansible -k -e ansible_network_os=vyos.vyos.vyos first_playbook.yml
+
+The playbook contains one play with two tasks, and should generate output like this:
+
+.. code-block:: shell
+
+ $ ansible-playbook -i vyos.example.net, -u ansible -k -e ansible_network_os=vyos.vyos.vyos first_playbook.yml
+
+ PLAY [Network Getting Started First Playbook]
+ ***************************************************************************************************************************
+
+ TASK [Get config for VyOS devices]
+ ***************************************************************************************************************************
+ ok: [vyos.example.net]
+
+ TASK [Display the config]
+ ***************************************************************************************************************************
+ ok: [vyos.example.net] => {
+ "msg": "The hostname is vyos and the OS is VyOS 1.1.8"
+ }
+
+3. Now that you can retrieve the device config, try updating it with Ansible. Download :download:`first_playbook_ext.yml <sample_files/first_playbook_ext.yml>`, which is an extended version of the first playbook:
+
+.. literalinclude:: sample_files/first_playbook_ext.yml
+ :language: YAML
+
+The extended first playbook has five tasks in a single play. Run it with the same command you used above. The output shows you the change Ansible made to the config:
+
+.. code-block:: shell
+
+ $ ansible-playbook -i vyos.example.net, -u ansible -k -e ansible_network_os=vyos.vyos.vyos first_playbook_ext.yml
+
+ PLAY [Network Getting Started First Playbook Extended]
+ ************************************************************************************************************************************
+
+ TASK [Get config for VyOS devices]
+ **********************************************************************************************************************************
+ ok: [vyos.example.net]
+
+ TASK [Display the config]
+ *************************************************************************************************************************************
+ ok: [vyos.example.net] => {
+ "msg": "The hostname is vyos and the OS is VyOS 1.1.8"
+ }
+
+ TASK [Update the hostname]
+ *************************************************************************************************************************************
+ changed: [vyos.example.net]
+
+ TASK [Get changed config for VyOS devices]
+ *************************************************************************************************************************************
+ ok: [vyos.example.net]
+
+ TASK [Display the changed config]
+ *************************************************************************************************************************************
+ ok: [vyos.example.net] => {
+ "msg": "The new hostname is vyos-changed and the OS is VyOS 1.1.8"
+ }
+
+ PLAY RECAP
+ ************************************************************************************************************************************
+ vyos.example.net : ok=5 changed=1 unreachable=0 failed=0
+
+
+
+.. _network_gather_facts:
+
+Gathering facts from network devices
+====================================
+
+The ``gather_facts`` keyword now supports gathering network device facts in standardized key/value pairs. You can feed these network facts into further tasks to manage the network device.
+
+You can also use the new ``gather_network_resources`` parameter with the network ``*_facts`` modules (such as :ref:`arista.eos.eos_facts <ansible_collections.arista.eos.eos_facts_module>`) to return just a subset of the device configuration, as shown below.
+
+.. code-block:: yaml
+
+ - hosts: arista
+ gather_facts: True
+ gather_subset: interfaces
+ module_defaults:
+ arista.eos.eos_facts:
+ gather_network_resources: interfaces
+
+The playbook returns the following interface facts:
+
+.. code-block:: yaml
+
+ "network_resources": {
+ "interfaces": [
+ {
+ "description": "test-interface",
+ "enabled": true,
+ "mtu": "512",
+ "name": "Ethernet1"
+ },
+ {
+ "enabled": true,
+ "mtu": "3000",
+ "name": "Ethernet2"
+ },
+ {
+ "enabled": true,
+ "name": "Ethernet3"
+ },
+ {
+ "enabled": true,
+ "name": "Ethernet4"
+ },
+ {
+ "enabled": true,
+ "name": "Ethernet5"
+ },
+ {
+ "enabled": true,
+ "name": "Ethernet6"
+ },
+ ]
+ }
+
+
+Note that this returns a subset of what is returned by just setting ``gather_subset: interfaces``.
+
+You can store these facts and use them directly in another task, such as with the :ref:`eos_interfaces <ansible_collections.arista.eos.eos_interfaces_module>` resource module.
diff --git a/docs/docsite/rst/network/getting_started/index.rst b/docs/docsite/rst/network/getting_started/index.rst
new file mode 100644
index 0000000..bf9f2eb
--- /dev/null
+++ b/docs/docsite/rst/network/getting_started/index.rst
@@ -0,0 +1,34 @@
+.. _network_getting_started:
+
+**********************************
+Network Getting Started
+**********************************
+
+Ansible collections support a wide range of vendors, device types, and actions, so you can manage your entire network with a single automation tool. With Ansible, you can:
+
+- Automate repetitive tasks to speed routine network changes and free up your time for more strategic work
+- Leverage the same simple, powerful, and agentless automation tool for network tasks that operations and development use
+- Separate the data model (in a playbook or role) from the execution layer (through Ansible modules) to manage heterogeneous network devices
+- Benefit from community and vendor-generated sample playbooks and roles to help accelerate network automation projects
+- Communicate securely with network hardware over SSH or HTTPS
+
+**Who should use this guide?**
+
+This guide is intended for network engineers using Ansible for the first time. If you understand networks but have never used Ansible, work through the guide from start to finish.
+
+This guide is also useful for experienced Ansible users automating network tasks for the first time. You can use Ansible commands, playbooks and modules to configure hubs, switches, routers, bridges and other network devices. But network modules are different from Linux/Unix and Windows modules, and you must understand some network-specific concepts to succeed. If you understand Ansible but have never automated a network task, start with the second section.
+
+This guide introduces basic Ansible concepts and guides you through your first Ansible commands, playbooks and inventory entries.
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Getting Started Guide
+
+ basic_concepts
+ network_differences
+ first_playbook
+ first_inventory
+ network_roles
+ intermediate_concepts
+ network_connection_options
+ network_resources
diff --git a/docs/docsite/rst/network/getting_started/intermediate_concepts.rst b/docs/docsite/rst/network/getting_started/intermediate_concepts.rst
new file mode 100644
index 0000000..3496f22
--- /dev/null
+++ b/docs/docsite/rst/network/getting_started/intermediate_concepts.rst
@@ -0,0 +1,39 @@
+*****************
+Beyond the basics
+*****************
+
+This page introduces some concepts that help you manage your Ansible workflow with directory structure and source control. Like the Basic Concepts at the beginning of this guide, these intermediate concepts are common to all uses of Ansible.
+
+.. contents::
+ :local:
+
+
+A typical Ansible filetree
+==========================
+
+Ansible expects to find certain files in certain places. As you expand your inventory and create and run more network playbooks, keep your files organized in your working Ansible project directory like this:
+
+.. code-block:: console
+
+ .
+ ├── backup
+ │   ├── vyos.example.net_config.2018-02-08@11:10:15
+ │   ├── vyos.example.net_config.2018-02-12@08:22:41
+ ├── first_playbook.yml
+ ├── inventory
+ ├── group_vars
+ │   ├── vyos.yml
+ │   └── eos.yml
+ ├── roles
+ │   ├── static_route
+ │   └── system
+ ├── second_playbook.yml
+ └── third_playbook.yml
+
+The ``backup`` directory and the files in it get created when you run modules like ``vyos_config`` with the ``backup: yes`` parameter.
+
+
+Tracking changes to inventory and playbooks: source control with git
+====================================================================
+
+As you expand your inventory, roles and playbooks, you should place your Ansible projects under source control. We recommend ``git`` for source control. ``git`` provides an audit trail, letting you track changes, roll back mistakes, view history and share the workload of managing, maintaining and expanding your Ansible ecosystem. There are plenty of tutorials and guides to using ``git`` available.
diff --git a/docs/docsite/rst/network/getting_started/network_connection_options.rst b/docs/docsite/rst/network/getting_started/network_connection_options.rst
new file mode 100644
index 0000000..bdfb93c
--- /dev/null
+++ b/docs/docsite/rst/network/getting_started/network_connection_options.rst
@@ -0,0 +1,48 @@
+.. _network_connection_options:
+
+***************************************
+Working with network connection options
+***************************************
+
+Network modules can support multiple connection protocols, such as ``ansible.netcommon.network_cli``, ``ansible.netcommon.netconf``, and ``ansible.netcommon.httpapi``. These connections include some common options you can set to control how the connection to your network device behaves.
+
+Common options are:
+
+* ``become`` and ``become_method`` as described in :ref:`privilege_escalation`.
+* ``network_os`` - set to match your network platform you are communicating with. See the :ref:`platform-specific <platform_options>` pages.
+* ``remote_user`` as described in :ref:`connection_set_user`.
+* Timeout options - ``persistent_command_timeout``, ``persistent_connect_timeout``, and ``timeout``.
+
+.. _timeout_options:
+
+Setting timeout options
+=======================
+
+When communicating with a remote device, you have control over how long Ansible maintains the connection to that device, as well as how long Ansible waits for a command to complete on that device. Each of these options can be set as variables in your playbook files, environment variables, or settings in your :ref:`ansible.cfg file <ansible_configuration_settings>`.
+
+For example, the three options for controlling the connection timeout are as follows.
+
+Using vars (per task):
+
+.. code-block:: yaml
+
+ - name: save running-config
+ cisco.ios.ios_command:
+ commands: copy running-config startup-config
+ vars:
+ ansible_command_timeout: 30
+
+Using the environment variable:
+
+.. code-block:: bash
+
+ $export ANSIBLE_PERSISTENT_COMMAND_TIMEOUT=30
+
+Using the global configuration (in :file:`ansible.cfg`)
+
+.. code-block:: ini
+
+ [persistent_connection]
+ command_timeout = 30
+
+See :ref:`ansible_variable_precedence` for details on the relative precedence of each of these variables. See the individual connection type to understand each option.
diff --git a/docs/docsite/rst/network/getting_started/network_differences.rst b/docs/docsite/rst/network/getting_started/network_differences.rst
new file mode 100644
index 0000000..2ae583f
--- /dev/null
+++ b/docs/docsite/rst/network/getting_started/network_differences.rst
@@ -0,0 +1,68 @@
+************************************************************
+How Network Automation is Different
+************************************************************
+
+Network automation uses the basic Ansible concepts, but there are important differences in how the network modules work. This introduction prepares you to understand the exercises in this guide.
+
+.. contents::
+ :local:
+
+Execution on the control node
+================================================================================
+
+Unlike most Ansible modules, network modules do not run on the managed nodes. From a user's point of view, network modules work like any other modules. They work with ad hoc commands, playbooks, and roles. Behind the scenes, however, network modules use a different methodology than the other (Linux/Unix and Windows) modules use. Ansible is written and executed in Python. Because the majority of network devices can not run Python, the Ansible network modules are executed on the Ansible control node, where ``ansible`` or ``ansible-playbook`` runs.
+
+Network modules also use the control node as a destination for backup files, for those modules that offer a ``backup`` option. With Linux/Unix modules, where a configuration file already exists on the managed node(s), the backup file gets written by default in the same directory as the new, changed file. Network modules do not update configuration files on the managed nodes, because network configuration is not written in files. Network modules write backup files on the control node, usually in the `backup` directory under the playbook root directory.
+
+Multiple communication protocols
+================================================================================
+
+Because network modules execute on the control node instead of on the managed nodes, they can support multiple communication protocols. The communication protocol (XML over SSH, CLI over SSH, API over HTTPS) selected for each network module depends on the platform and the purpose of the module. Some network modules support only one protocol; some offer a choice. The most common protocol is CLI over SSH. You set the communication protocol with the ``ansible_connection`` variable:
+
+.. csv-table::
+ :header: "Value of ansible_connection", "Protocol", "Requires", "Persistent?"
+ :widths: 30, 10, 10, 10
+
+ "ansible.netcommon.network_cli", "CLI over SSH", "network_os setting", "yes"
+ "ansible.netcommon.netconf", "XML over SSH", "network_os setting", "yes"
+ "ansible.netcommon.httpapi", "API over HTTP/HTTPS", "network_os setting", "yes"
+ "local", "depends on provider", "provider setting", "no"
+
+.. note::
+ ``ansible.netcommon.httpapi`` deprecates ``eos_eapi`` and ``nxos_nxapi``. See :ref:`httpapi_plugins` for details and an example.
+
+The ``ansible_connection: local`` has been deprecated. Please use one of the persistent connection types listed above instead. With persistent connections, you can define the hosts and credentials only once, rather than in every task. You also need to set the ``network_os`` variable for the specific network platform you are communicating with. For more details on using each connection type on various platforms, see the :ref:`platform-specific <platform_options>` pages.
+
+
+Collections organized by network platform
+================================================================================
+
+A network platform is a set of network devices with a common operating system that can be managed by an Ansible collection, for example:
+
+- Arista: `arista.eos <https://galaxy.ansible.com/arista/eos>`_
+- Cisco: `cisco.ios <https://galaxy.ansible.com/cisco/ios>`_, `cisco.iosxr <https://galaxy.ansible.com/cisco/iosxr>`_, `cisco.nxos <https://galaxy.ansible.com/cisco/nxos>`_
+- Juniper: `junipernetworks.junos <https://galaxy.ansible.com/junipernetworks/junos>`_
+- VyOS `vyos.vyos <https://galaxy.ansible.com/vyos/vyos>`_
+
+All modules within a network platform share certain requirements. Some network platforms have specific differences - see the :ref:`platform-specific <platform_options>` documentation for details.
+
+.. _privilege_escalation:
+
+Privilege Escalation: ``enable`` mode, ``become``, and ``authorize``
+================================================================================
+
+Several network platforms support privilege escalation, where certain tasks must be done by a privileged user. On network devices this is called the ``enable`` mode (the equivalent of ``sudo`` in \*nix administration). Ansible network modules offer privilege escalation for those network devices that support it. For details of which platforms support ``enable`` mode, with examples of how to use it, see the :ref:`platform-specific <platform_options>` documentation.
+
+Using ``become`` for privilege escalation
+-----------------------------------------
+
+Use the top-level Ansible parameter ``become: yes`` with ``become_method: enable`` to run a task, play, or playbook with escalated privileges on any network platform that supports privilege escalation. You must use either ``connection: network_cli`` or ``connection: httpapi`` with ``become: yes`` with ``become_method: enable``. If you are using ``network_cli`` to connect Ansible to your network devices, a ``group_vars`` file would look like:
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: cisco.ios.ios
+ ansible_become: yes
+ ansible_become_method: enable
+
+For more information, see :ref:`Become and Networks<become_network>`
diff --git a/docs/docsite/rst/network/getting_started/network_resources.rst b/docs/docsite/rst/network/getting_started/network_resources.rst
new file mode 100644
index 0000000..a69aba9
--- /dev/null
+++ b/docs/docsite/rst/network/getting_started/network_resources.rst
@@ -0,0 +1,47 @@
+
+.. _network_resources:
+
+************************
+Resources and next steps
+************************
+
+.. contents::
+ :local:
+
+Documents
+=========
+
+Read more about Ansible for Network Automation:
+
+- :ref:`Network Platform Options <platform_options>`
+- Network Automation on the `Ansible website <https://www.ansible.com/overview/networking>`_
+- Ansible Network `Blog posts <https://www.ansible.com/blog/topic/networks>`_
+
+Events (on video and in person)
+===============================
+
+All sessions at Ansible events are recorded and include many Network-related topics (use Filter by Category to view only Network topics). You can also join us for future events in your area. See:
+
+- `Recorded AnsibleFests <https://www.ansible.com/resources/videos/ansiblefest>`_
+- `Recorded AnsibleAutomates <https://www.ansible.com/resources/webinars-training>`_
+- `Upcoming Ansible Events <https://www.ansible.com/community/events>`_ page.
+
+GitHub repos
+============
+
+Ansible hosts module code, examples, demonstrations, and other content on GitHub. Anyone with a GitHub account is able to create Pull Requests (PRs) or issues on these repos:
+
+- `Network-Automation <https://github.com/network-automation>`_ is an open community for all things network automation. Have an idea, some playbooks, or roles to share? Email ansible-network@redhat.com and we will add you as a contributor to the repository.
+
+- `Ansible collections <https://github.com/ansible-collections>`_ is the main repository for Ansible-maintained and community collections, including collections for network devices.
+
+
+
+Chat channels
+=============
+
+Got questions? Chat with us on:
+
+* the ``#ansible-network`` channel (using Matrix at ansible.im or using IRC at `irc.libera.chat <https://libera.chat/>`_)
+
+* `Ansible Network Slack <https://join.slack.com/t/ansiblenetwork/shared_invite/zt-3zeqmhhx-zuID9uJqbbpZ2KdVeTwvzw>`_ - Network & Security Automation Slack community. Check out the #devel channel for discussions on module and plugin development.
diff --git a/docs/docsite/rst/network/getting_started/network_roles.rst b/docs/docsite/rst/network/getting_started/network_roles.rst
new file mode 100644
index 0000000..4ffb833
--- /dev/null
+++ b/docs/docsite/rst/network/getting_started/network_roles.rst
@@ -0,0 +1,267 @@
+
+.. _using_network_roles:
+
+*************************
+Use Ansible network roles
+*************************
+
+Roles are sets of Ansible defaults, files, tasks, templates, variables, and other Ansible components that work together. As you saw on :ref:`first_network_playbook`, moving from a command to a playbook makes it easy to run multiple tasks and repeat the same tasks in the same order. Moving from a playbook to a role makes it even easier to reuse and share your ordered tasks. You can look at :ref:`Ansible Galaxy <ansible_galaxy>`, which lets you share your roles and use others' roles, either directly or as inspiration.
+
+.. contents::
+ :local:
+
+Understanding roles
+===================
+
+So what exactly is a role, and why should you care? Ansible roles are basically playbooks broken up into a known file structure. Moving to roles from a playbook makes sharing, reading, and updating your Ansible workflow easier. Users can write their own roles. So for example, you don't have to write your own DNS playbook. Instead, you specify a DNS server and a role to configure it for you.
+
+To simplify your workflow even further, the Ansible Network team has written a series of roles for common network use cases. Using these roles means you don't have to reinvent the wheel. Instead of writing and maintaining your own ``create_vlan`` playbooks or roles, you can concentrate on designing, codifying and maintaining the parser templates that describe your network topologies and inventory, and let Ansible's network roles do the work. See the `network-related roles <https://galaxy.ansible.com/ansible-network>`_ on Ansible Galaxy.
+
+A sample DNS playbook
+---------------------
+
+To demonstrate the concept of what a role is, the example ``playbook.yml`` below is a single YAML file containing a two-task playbook. This Ansible Playbook configures the hostname on a Cisco IOS XE device, then it configures the DNS (domain name system) servers.
+
+.. code-block:: yaml
+
+ ---
+ - name: configure cisco routers
+ hosts: routers
+ connection: ansible.netcommon.network_cli
+ gather_facts: no
+ vars:
+ dns: "8.8.8.8 8.8.4.4"
+
+ tasks:
+ - name: configure hostname
+ cisco.ios.ios_config:
+ lines: hostname {{ inventory_hostname }}
+
+ - name: configure DNS
+ cisco.ios.ios_config:
+ lines: ip name-server {{dns}}
+
+If you run this playbook using the ``ansible-playbook`` command, you'll see the output below. This example used ``-l`` option to limit the playbook to only executing on the **rtr1** node.
+
+.. code-block:: bash
+
+ [user@ansible ~]$ ansible-playbook playbook.yml -l rtr1
+
+ PLAY [configure cisco routers] *************************************************
+
+ TASK [configure hostname] ******************************************************
+ changed: [rtr1]
+
+ TASK [configure DNS] ***********************************************************
+ changed: [rtr1]
+
+ PLAY RECAP *********************************************************************
+ rtr1 : ok=2 changed=2 unreachable=0 failed=0
+
+
+This playbook configured the hostname and DNS servers. You can verify that configuration on the Cisco IOS XE **rtr1** router:
+
+.. code-block:: bash
+
+ rtr1#sh run | i name
+ hostname rtr1
+ ip name-server 8.8.8.8 8.8.4.4
+
+Convert the playbook into a role
+---------------------------------
+
+The next step is to convert this playbook into a reusable role. You can create the directory structure manually, or you can use ``ansible-galaxy init`` to create the standard framework for a role.
+
+.. code-block:: bash
+
+ [user@ansible ~]$ ansible-galaxy init system-demo
+ [user@ansible ~]$ cd system-demo/
+ [user@ansible system-demo]$ tree
+ .
+ ├── defaults
+ │ └── main.yml
+ ├── files
+ ├── handlers
+ │ └── main.yml
+ ├── meta
+ │ └── main.yml
+ ├── README.md
+ ├── tasks
+ │ └── main.yml
+ ├── templates
+ ├── tests
+ │ ├── inventory
+ │ └── test.yml
+ └── vars
+ └── main.yml
+
+This first demonstration uses only the **tasks** and **vars** directories. The directory structure would look as follows:
+
+.. code-block:: bash
+
+ [user@ansible system-demo]$ tree
+ .
+ ├── tasks
+ │ └── main.yml
+ └── vars
+ └── main.yml
+
+Next, move the content of the ``vars`` and ``tasks`` sections from the original Ansible Playbook into the role. First, move the two tasks into the ``tasks/main.yml`` file:
+
+.. code-block:: bash
+
+ [user@ansible system-demo]$ cat tasks/main.yml
+ ---
+ - name: configure hostname
+ cisco.ios.ios_config:
+ lines: hostname {{ inventory_hostname }}
+
+ - name: configure DNS
+ cisco.ios.ios_config:
+ lines: ip name-server {{dns}}
+
+Next, move the variables into the ``vars/main.yml`` file:
+
+.. code-block:: bash
+
+ [user@ansible system-demo]$ cat vars/main.yml
+ ---
+ dns: "8.8.8.8 8.8.4.4"
+
+Finally, modify the original Ansible Playbook to remove the ``tasks`` and ``vars`` sections and add the keyword ``roles`` with the name of the role, in this case ``system-demo``. You'll have this playbook:
+
+.. code-block:: yaml
+
+ ---
+ - name: configure cisco routers
+ hosts: routers
+ connection: ansible.netcommon.network_cli
+ gather_facts: no
+
+ roles:
+ - system-demo
+
+To summarize, this demonstration now has a total of three directories and three YAML files. There is the ``system-demo`` folder, which represents the role. This ``system-demo`` contains two folders, ``tasks`` and ``vars``. There is a ``main.yml`` is each respective folder. The ``vars/main.yml`` contains the variables from ``playbook.yml``. The ``tasks/main.yml`` contains the tasks from ``playbook.yml``. The ``playbook.yml`` file has been modified to call the role rather than specifying vars and tasks directly. Here is a tree of the current working directory:
+
+.. code-block:: bash
+
+ [user@ansible ~]$ tree
+ .
+ ├── playbook.yml
+ └── system-demo
+ ├── tasks
+ │ └── main.yml
+ └── vars
+ └── main.yml
+
+Running the playbook results in identical behavior with slightly different output:
+
+.. code-block:: bash
+
+ [user@ansible ~]$ ansible-playbook playbook.yml -l rtr1
+
+ PLAY [configure cisco routers] *************************************************
+
+ TASK [system-demo : configure hostname] ****************************************
+ ok: [rtr1]
+
+ TASK [system-demo : configure DNS] *********************************************
+ ok: [rtr1]
+
+ PLAY RECAP *********************************************************************
+ rtr1 : ok=2 changed=0 unreachable=0 failed=0
+
+As seen above each task is now prepended with the role name, in this case ``system-demo``. When running a playbook that contains several roles, this will help pinpoint where a task is being called from. This playbook returned ``ok`` instead of ``changed`` because it has identical behavior for the single file playbook we started from.
+
+As before, the playbook will generate the following configuration on a Cisco IOS-XE router:
+
+.. code-block:: bash
+
+ rtr1#sh run | i name
+ hostname rtr1
+ ip name-server 8.8.8.8 8.8.4.4
+
+
+This is why Ansible roles can be simply thought of as deconstructed playbooks. They are simple, effective and reusable. Now another user can simply include the ``system-demo`` role instead of having to create a custom "hard coded" playbook.
+
+Variable precedence
+-------------------
+
+What if you want to change the DNS servers? You aren't expected to change the ``vars/main.yml`` within the role structure. Ansible has many places where you can specify variables for a given play. See :ref:`playbooks_variables` for details on variables and precedence. There are actually 21 places to put variables. While this list can seem overwhelming at first glance, the vast majority of use cases only involve knowing the spot for variables of least precedence and how to pass variables with most precedence. See :ref:`ansible_variable_precedence` for more guidance on where you should put variables.
+
+Lowest precedence
+^^^^^^^^^^^^^^^^^
+
+The lowest precedence is the ``defaults`` directory within a role. This means all the other 20 locations you could potentially specify the variable will all take higher precedence than ``defaults``, no matter what. To immediately give the vars from the ``system-demo`` role the least precedence, rename the ``vars`` directory to ``defaults``.
+
+.. code-block:: bash
+
+ [user@ansible system-demo]$ mv vars defaults
+ [user@ansible system-demo]$ tree
+ .
+ ├── defaults
+ │ └── main.yml
+ ├── tasks
+ │ └── main.yml
+
+Add a new ``vars`` section to the playbook to override the default behavior (where the variable ``dns`` is set to 8.8.8.8 and 8.8.4.4). For this demonstration, set ``dns`` to 1.1.1.1, so ``playbook.yml`` becomes:
+
+.. code-block:: yaml
+
+ ---
+ - name: configure cisco routers
+ hosts: routers
+ connection: ansible.netcommon.network_cli
+ gather_facts: no
+ vars:
+ dns: 1.1.1.1
+ roles:
+ - system-demo
+
+Run this updated playbook on **rtr2**:
+
+.. code-block:: bash
+
+ [user@ansible ~]$ ansible-playbook playbook.yml -l rtr2
+
+The configuration on the **rtr2** Cisco router will look as follows:
+
+.. code-block:: bash
+
+ rtr2#sh run | i name-server
+ ip name-server 1.1.1.1
+
+The variable configured in the playbook now has precedence over the ``defaults`` directory. In fact, any other spot you configure variables would win over the values in the ``defaults`` directory.
+
+Highest precedence
+^^^^^^^^^^^^^^^^^^
+
+Specifying variables in the ``defaults`` directory within a role will always take the lowest precedence, while specifying ``vars`` as extra vars with the ``-e`` or ``--extra-vars=`` will always take the highest precedence, no matter what. Re-running the playbook with the ``-e`` option overrides both the ``defaults`` directory (8.8.4.4 and 8.8.8.8) as well as the newly created ``vars`` within the playbook that contains the 1.1.1.1 dns server.
+
+.. code-block:: bash
+
+ [user@ansible ~]$ ansible-playbook playbook.yml -e "dns=192.168.1.1" -l rtr3
+
+The result on the Cisco IOS XE router will only contain the highest precedence setting of 192.168.1.1:
+
+.. code-block:: bash
+
+ rtr3#sh run | i name-server
+ ip name-server 192.168.1.1
+
+How is this useful? Why should you care? Extra vars are commonly used by network operators to override defaults. A powerful example of this is with the Job Template Survey feature on AWX or the :ref:`ansible_platform`. It is possible through the web UI to prompt a network operator to fill out parameters with a Web form. This can be really simple for non-technical playbook writers to execute a playbook using their Web browser.
+
+
+Update an installed role
+------------------------
+
+The Ansible Galaxy page for a role lists all available versions. To update a locally installed role to a new or different version, use the ``ansible-galaxy install`` command with the version and ``--force`` option. You may also need to manually update any dependent roles to support this version. See the role **Read Me** tab in Galaxy for dependent role minimum version requirements.
+
+.. code-block:: bash
+
+ [user@ansible]$ ansible-galaxy install mynamespace.my_role,v2.7.1 --force
+
+.. seealso::
+
+ `Ansible Galaxy documentation <https://galaxy.ansible.com/docs/>`_
+ Ansible Galaxy user guide
diff --git a/docs/docsite/rst/network/getting_started/sample_files/first_playbook.yml b/docs/docsite/rst/network/getting_started/sample_files/first_playbook.yml
new file mode 100644
index 0000000..908b89f
--- /dev/null
+++ b/docs/docsite/rst/network/getting_started/sample_files/first_playbook.yml
@@ -0,0 +1,15 @@
+---
+
+- name: Network Getting Started First Playbook
+ connection: ansible.netcommon.network_cli
+ gather_facts: false
+ hosts: all
+ tasks:
+
+ - name: Get config for VyOS devices
+ vyos.vyos.vyos_facts:
+ gather_subset: all
+
+ - name: Display the config
+ debug:
+ msg: "The hostname is {{ ansible_net_hostname }} and the OS is {{ ansible_net_version }}"
diff --git a/docs/docsite/rst/network/getting_started/sample_files/first_playbook_ext.yml b/docs/docsite/rst/network/getting_started/sample_files/first_playbook_ext.yml
new file mode 100644
index 0000000..2d5f6a5
--- /dev/null
+++ b/docs/docsite/rst/network/getting_started/sample_files/first_playbook_ext.yml
@@ -0,0 +1,29 @@
+---
+
+- name: Network Getting Started First Playbook Extended
+ connection: ansible.netcommon.network_cli
+ gather_facts: false
+ hosts: all
+ tasks:
+
+ - name: Get config for VyOS devices
+ vyos.vyos.vyos_facts:
+ gather_subset: all
+
+ - name: Display the config
+ debug:
+ msg: "The hostname is {{ ansible_net_hostname }} and the OS is {{ ansible_net_version }}"
+
+ - name: Update the hostname
+ vyos.vyos.vyos_config:
+ backup: yes
+ lines:
+ - set system host-name vyos-changed
+
+ - name: Get changed config for VyOS devices
+ vyos.vyos.vyos_facts:
+ gather_subset: all
+
+ - name: Display the changed config
+ debug:
+ msg: "The new hostname is {{ ansible_net_hostname }} and the OS is {{ ansible_net_version }}"
diff --git a/docs/docsite/rst/network/index.rst b/docs/docsite/rst/network/index.rst
new file mode 100644
index 0000000..2575639
--- /dev/null
+++ b/docs/docsite/rst/network/index.rst
@@ -0,0 +1,20 @@
+:orphan:
+
+.. _network_guide:
+
+******************************
+Ansible for Network Automation
+******************************
+
+Ansible Network modules extend the benefits of simple, powerful, agentless automation to network administrators and teams. Ansible Network modules can configure your network stack, test and validate existing network state, and discover and correct network configuration drift.
+
+If you're new to Ansible, or new to using Ansible for network management, start with :ref:`network_getting_started`. If you are already familiar with network automation with Ansible, see :ref:`network_advanced`.
+
+For documentation on using a particular network module, consult the :ref:`list of all network modules<network_modules>`. Network modules for various hardware are supported by different teams including the hardware vendors themselves, volunteers from the Ansible community, and the Ansible Network Team.
+
+.. toctree::
+ :maxdepth: 3
+
+ getting_started/index
+ user_guide/index
+ dev_guide/index
diff --git a/docs/docsite/rst/network/user_guide/cli_parsing.rst b/docs/docsite/rst/network/user_guide/cli_parsing.rst
new file mode 100644
index 0000000..5b6b40e
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/cli_parsing.rst
@@ -0,0 +1,744 @@
+.. _cli_parsing:
+
+*****************************************
+Parsing semi-structured text with Ansible
+*****************************************
+
+The :ref:`cli_parse <ansible_collections.ansible.utils.cli_parse_module>` module parses semi-structured data such as network configurations into structured data to allow programmatic use of the data from that device. You can pull information from a network device and update a CMDB in one playbook. Use cases include automated troubleshooting, creating dynamic documentation, updating IPAM (IP address management) tools and so on.
+
+
+.. contents::
+ :local:
+
+
+Understanding the CLI parser
+=============================
+
+The `ansible.utils <https://galaxy.ansible.com/ansible/utils>`_ collection version 1.0.0 or later includes the :ref:`cli_parse <ansible_collections.ansible.utils.cli_parse_module>` module that can run CLI commands and parse the semi-structured text output. You can use the ``cli_parse`` module on a device, host, or platform that only supports a command-line interface and the commands issued return semi-structured text. The ``cli_parse`` module can either run a CLI command on a device and return a parsed result or can simply parse any text document. The ``cli_parse`` module includes cli_parser plugins to interface with a variety of parsing engines.
+
+Why parse the text?
+--------------------
+
+Parsing semi-structured data such as network configurations into structured data allows programmatic use of the data from that device. Use cases include automated troubleshooting, creating dynamic documentation, updating IPAM (IP address management) tools and so on. You may prefer to do this with Ansible natively to take advantage of native Ansible constructs such as:
+
+- The ``when`` clause to conditionally run other tasks or roles
+- The ``assert`` module to check configuration and operational state compliance
+- The ``template`` module to generate reports about configuration and operational state information
+- Templates and ``command`` or ``config`` modules to generate host, device, or platform commands or configuration
+- The current platform ``facts`` modules to supplement native facts information
+
+By parsing semi-structured text into Ansible native data structures, you can take full advantage of Ansible's network modules and plugins.
+
+
+When not to parse the text
+---------------------------
+
+You should not parse semi-structured text when:
+
+- The device, host, or platform has a RESTAPI and returns JSON.
+- Existing Ansible facts modules already return the desired data.
+- Ansible network resource modules exist for configuration management of the device and resource.
+
+Parsing the CLI
+=========================
+
+The ``cli_parse`` module includes the following cli_parsing plugins:
+
+``native``
+ The native parsing engine built into Ansible and requires no addition python libraries
+``xml``
+ Convert XML to an Ansible native data structure
+``textfsm``
+ A python module which implements a template based state machine for parsing semi-formatted text
+``ntc_templates``
+ Predefined ``textfsm`` templates packages supporting a variety of platforms and commands
+``ttp``
+ A library for semi-structured text parsing using templates, with added capabilities to simplify the process
+``pyats``
+ Uses the parsers included with the Cisco Test Automation & Validation Solution
+``jc``
+ A python module that converts the output of dozens of popular Linux/UNIX/macOS/Windows commands and file types to python dictionaries or lists of dictionaries. Note: this filter plugin can be found in the ``community.general`` collection.
+``json``
+ Converts JSON output at the CLI to an Ansible native data structure
+
+Although Ansible contains a number of plugins that can convert XML to Ansible native data structures, the ``cli_parse`` module runs the command on devices that return XML and returns the converted data in a single task.
+
+Because ``cli_parse`` uses a plugin based architecture, it can use additional parsing engines from any Ansible collection.
+
+.. note::
+
+ The ``ansible.netcommon.native`` and ``ansible.utils.json`` parsing engines are fully supported with a Red Hat Ansible Automation Platform subscription. Red Hat Ansible Automation Platform subscription support is limited to the use of the ``ntc_templates``, pyATS, ``textfsm``, ``xmltodict``, public APIs as documented.
+
+Parsing with the native parsing engine
+--------------------------------------
+
+The native parsing engine is included with the ``cli_parse`` module. It uses data captured using regular expressions to populate the parsed data structure. The native parsing engine requires a YAML template file to parse the command output.
+
+Networking example
+^^^^^^^^^^^^^^^^^^
+
+This example uses the output of a network device command and applies a native template to produce an output in Ansible structured data format.
+
+The ``show interface`` command output from the network device looks as follows:
+
+.. code-block:: console
+
+ Ethernet1/1 is up
+ admin state is up, Dedicated Interface
+ Hardware: 100/1000/10000 Ethernet, address: 5254.005a.f8bd (bia 5254.005a.f8bd)
+ MTU 1500 bytes, BW 1000000 Kbit, DLY 10 usec
+ reliability 255/255, txload 1/255, rxload 1/255
+ Encapsulation ARPA, medium is broadcast
+ Port mode is access
+ full-duplex, auto-speed
+ Beacon is turned off
+ Auto-Negotiation is turned on FEC mode is Auto
+ Input flow-control is off, output flow-control is off
+ Auto-mdix is turned off
+ Switchport monitor is off
+ EtherType is 0x8100
+ EEE (efficient-ethernet) : n/a
+ Last link flapped 4week(s) 6day(s)
+ Last clearing of "show interface" counters never
+ <...>
+
+
+Create the native template to match this output and store it as ``templates/nxos_show_interface.yaml``:
+
+.. code-block:: yaml
+
+ ---
+ - example: Ethernet1/1 is up
+ getval: '(?P<name>\S+) is (?P<oper_state>\S+)'
+ result:
+ "{{ name }}":
+ name: "{{ name }}"
+ state:
+ operating: "{{ oper_state }}"
+ shared: true
+
+ - example: admin state is up, Dedicated Interface
+ getval: 'admin state is (?P<admin_state>\S+),'
+ result:
+ "{{ name }}":
+ name: "{{ name }}"
+ state:
+ admin: "{{ admin_state }}"
+
+ - example: " Hardware: Ethernet, address: 5254.005a.f8b5 (bia 5254.005a.f8b5)"
+ getval: '\s+Hardware: (?P<hardware>.*), address: (?P<mac>\S+)'
+ result:
+ "{{ name }}":
+ hardware: "{{ hardware }}"
+ mac_address: "{{ mac }}"
+
+
+This native parser template is structured as a list of parsers, each containing the following key-value pairs:
+
+- ``example`` - An example line of the text line to be parsed
+- ``getval`` - A regular expression using named capture groups to store the extracted data
+- ``result`` - A data tree, populated as a template, from the parsed data
+- ``shared`` - (optional) The shared key makes the parsed values available to the rest of the parser entries until matched again.
+
+The following example task uses ``cli_parse`` with the native parser and the example template above to parse the ``show interface`` command from a Cisco NXOS device:
+
+.. code-block:: yaml
+
+ - name: "Run command and parse with native"
+ ansible.utils.cli_parse:
+ command: show interface
+ parser:
+ name: ansible.netcommon.native
+ set_fact: interfaces
+
+Taking a deeper dive into this task:
+
+- The ``command`` option provides the command you want to run on the device or host. Alternately, you can provide text from a previous command with the ``text`` option instead.
+- The ``parser`` option provides information specific to the parser engine.
+- The ``name`` suboption provides the fully qualified collection name (FQCN) of the parsing engine (``ansible.netcommon.native``).
+- The ``cli_parse`` module, by default, looks for the template in the templates directory as ``{{ short_os }}_{{ command }}.yaml``.
+
+ - The ``short_os`` in the template filename is derived from either the host ``ansible_network_os`` or ``ansible_distribution``.
+ - Spaces in the network or host command are replace with ``_`` in the ``command`` portion of the template filename. In this example, the ``show interfaces`` network CLI command becomes ``show_interfaces`` in the filename.
+
+.. note::
+
+ ``ansible.netcommon.native`` parsing engine is fully supported with a Red Hat Ansible Automation Platform subscription.
+
+Lastly in this task, the ``set_fact`` option sets the following ``interfaces`` fact for the device based on the now-structured data returned from ``cli_parse``:
+
+.. code-block:: yaml
+
+ Ethernet1/1:
+ hardware: 100/1000/10000 Ethernet
+ mac_address: 5254.005a.f8bd
+ name: Ethernet1/1
+ state:
+ admin: up
+ operating: up
+ Ethernet1/10:
+ hardware: 100/1000/10000 Ethernet
+ mac_address: 5254.005a.f8c6
+ <...>
+
+
+Linux example
+^^^^^^^^^^^^^
+
+You can also use the native parser to run commands and parse output from Linux hosts.
+
+The output of a sample Linux command (``ip addr show``) looks as follows:
+
+.. code-block:: bash
+
+ 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
+ link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
+ inet 127.0.0.1/8 scope host lo
+ valid_lft forever preferred_lft forever
+ inet6 ::1/128 scope host
+ valid_lft forever preferred_lft forever
+ 2: enp0s31f6: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
+ link/ether x2:6a:64:9d:84:19 brd ff:ff:ff:ff:ff:ff
+ 3: wlp2s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
+ link/ether x6:c2:44:f7:41:e0 brd ff:ff:ff:ff:ff:ff permaddr d8:f2:ca:99:5c:82
+
+Create the native template to match this output and store it as ``templates/fedora_ip_addr_show.yaml``:
+
+.. code-block:: yaml
+
+ ---
+ - example: '1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000'
+ getval: |
+ (?x) # free-spacing
+ \d+:\s # the interface index
+ (?P<name>\S+):\s # the name
+ <(?P<properties>\S+)> # the properties
+ \smtu\s(?P<mtu>\d+) # the mtu
+ .* # gunk
+ state\s(?P<state>\S+) # the state of the interface
+ result:
+ "{{ name }}":
+ name: "{{ name }}"
+ loopback: "{{ 'LOOPBACK' in stats.split(',') }}"
+ up: "{{ 'UP' in properties.split(',') }}"
+ carrier: "{{ not 'NO-CARRIER' in properties.split(',') }}"
+ broadcast: "{{ 'BROADCAST' in properties.split(',') }}"
+ multicast: "{{ 'MULTICAST' in properties.split(',') }}"
+ state: "{{ state|lower() }}"
+ mtu: "{{ mtu }}"
+ shared: True
+
+ - example: 'inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0'
+ getval: |
+ (?x) # free-spacing
+ \s+inet\s(?P<inet>([0-9]{1,3}\.){3}[0-9]{1,3}) # the ip address
+ /(?P<bits>\d{1,2}) # the mask bits
+ result:
+ "{{ name }}":
+ ip_address: "{{ inet }}"
+ mask_bits: "{{ bits }}"
+
+.. note::
+
+ The ``shared`` key in the parser template allows the interface name to be used in subsequent parser entries. The use of examples and free-spacing mode with the regular expressions makes the template easier to read.
+
+The following example task uses ``cli_parse`` with the native parser and the example template above to parse the Linux output:
+
+.. code-block:: yaml
+
+ - name: Run command and parse
+ ansible.utils.cli_parse:
+ command: ip addr show
+ parser:
+ name: ansible.netcommon.native
+ set_fact: interfaces
+
+This task assumes you previously gathered facts to determine the ``ansible_distribution`` needed to locate the template. Alternately, you could provide the path in the ``parser/template_path`` option.
+
+
+Lastly in this task, the ``set_fact`` option sets the following ``interfaces`` fact for the host, based on the now-structured data returned from ``cli_parse``:
+
+.. code-block:: yaml
+
+ lo:
+ broadcast: false
+ carrier: true
+ ip_address: 127.0.0.1
+ mask_bits: 8
+ mtu: 65536
+ multicast: false
+ name: lo
+ state: unknown
+ up: true
+ enp64s0u1:
+ broadcast: true
+ carrier: true
+ ip_address: 192.168.86.83
+ mask_bits: 24
+ mtu: 1500
+ multicast: true
+ name: enp64s0u1
+ state: up
+ up: true
+ <...>
+
+
+Parsing JSON
+-------------
+
+Although Ansible will natively convert serialized JSON to Ansible native data when recognized, you can also use the ``cli_parse`` module for this conversion.
+
+Example task:
+
+.. code-block:: yaml
+
+ - name: "Run command and parse as json"
+ ansible.utils.cli_parse:
+ command: show interface | json
+ parser:
+ name: ansible.utils.json
+ register: interfaces
+
+Taking a deeper dive into this task:
+
+- The ``show interface | json`` command is issued on the device.
+- The output is set as the ``interfaces`` fact for the device.
+- JSON support is provided primarily for playbook consistency.
+
+.. note::
+
+ The use of ``ansible.netcommon.json`` is fully supported with a Red Hat Ansible Automation Platform subscription
+
+Parsing with ntc_templates
+----------------------------
+
+The ``ntc_templates`` python library includes pre-defined ``textfsm`` templates for parsing a variety of network device commands output.
+
+Example task:
+
+.. code-block:: yaml
+
+ - name: "Run command and parse with ntc_templates"
+ ansible.utils.cli_parse:
+ command: show interface
+ parser:
+ name: ansible.netcommon.ntc_templates
+ set_fact: interfaces
+
+Taking a deeper dive into this task:
+
+- The ``ansible_network_os`` of the device is converted to the ntc_template format ``cisco_nxos``. Alternately, you can provide the ``os`` with the ``parser/os`` option instead.
+- The ``cisco_nxos_show_interface.textfsm`` template, included with the ``ntc_templates`` package, parses the output.
+- See `the ntc_templates README <https://github.com/networktocode/ntc-templates/blob/master/README.md>`_ for additional information about the ``ntc_templates`` python library.
+
+.. note::
+
+ Red Hat Ansible Automation Platform subscription support is limited to the use of the ``ntc_templates`` public APIs as documented.
+
+
+This task and and the predefined template sets the following fact as the ``interfaces`` fact for the host:
+
+.. code-block:: yaml
+
+ interfaces:
+ - address: 5254.005a.f8b5
+ admin_state: up
+ bandwidth: 1000000 Kbit
+ bia: 5254.005a.f8b5
+ delay: 10 usec
+ description: ''
+ duplex: full-duplex
+ encapsulation: ARPA
+ hardware_type: Ethernet
+ input_errors: ''
+ input_packets: ''
+ interface: mgmt0
+ ip_address: 192.168.101.14/24
+ last_link_flapped: ''
+ link_status: up
+ mode: ''
+ mtu: '1500'
+ output_errors: ''
+ output_packets: ''
+ speed: 1000 Mb/s
+ - address: 5254.005a.f8bd
+ admin_state: up
+ bandwidth: 1000000 Kbit
+ bia: 5254.005a.f8bd
+ delay: 10 usec
+
+
+Parsing with pyATS
+----------------------
+
+``pyATS`` is part of the Cisco Test Automation & Validation Solution. It includes many predefined parsers for a number of network platforms and commands. You can use the predefined parsers that are part of the ``pyATS`` package with the ``cli_parse`` module.
+
+Example task:
+
+.. code-block:: yaml
+
+ - name: "Run command and parse with pyats"
+ ansible.utils.cli_parse:
+ command: show interface
+ parser:
+ name: ansible.netcommon.pyats
+ set_fact: interfaces
+
+
+Taking a deeper dive into this task:
+
+- The ``cli_parse`` modules converts the ``ansible_network_os`` automatically (in this example, ``ansible_network_os`` set to ``cisco.nxos.nxos``, converts to ``nxos`` for pyATS. Alternately, you can set the OS with the ``parser/os`` option instead.
+- Using a combination of the command and OS, the pyATS selects the following parser: https://pubhub.devnetcloud.com/media/genie-feature-browser/docs/#/parsers/show%2520interface.
+- The ``cli_parse`` module sets ``cisco.ios.ios`` to ``iosxe`` for pyATS. You can override this with the ``parser/os`` option.
+- ``cli_parse`` only uses the predefined parsers in pyATS. See the `pyATS documentation <https://developer.cisco.com/docs/pyats/>`_ and the full list of `pyATS included parsers <https://pubhub.devnetcloud.com/media/genie-feature-browser/docs/#/parsers>`_.
+
+.. note::
+
+ Red Hat Ansible Automation Platform subscription support is limited to the use of the pyATS public APIs as documented.
+
+
+This task sets the following fact as the ``interfaces`` fact for the host:
+
+.. code-block:: yaml
+
+ mgmt0:
+ admin_state: up
+ auto_mdix: 'off'
+ auto_negotiate: true
+ bandwidth: 1000000
+ counters:
+ in_broadcast_pkts: 3
+ in_multicast_pkts: 1652395
+ in_octets: 556155103
+ in_pkts: 2236713
+ in_unicast_pkts: 584259
+ rate:
+ in_rate: 320
+ in_rate_pkts: 0
+ load_interval: 1
+ out_rate: 48
+ out_rate_pkts: 0
+ rx: true
+ tx: true
+ delay: 10
+ duplex_mode: full
+ enabled: true
+ encapsulations:
+ encapsulation: arpa
+ ethertype: '0x0000'
+ ipv4:
+ 192.168.101.14/24:
+ ip: 192.168.101.14
+ prefix_length: '24'
+ link_state: up
+ <...>
+
+
+Parsing with textfsm
+---------------------
+
+``textfsm`` is a Python module which implements a template-based state machine for parsing semi-formatted text.
+
+The following sample ``textfsm`` template is stored as ``templates/nxos_show_interface.textfsm``
+
+.. code-block:: text
+
+
+ Value Required INTERFACE (\S+)
+ Value LINK_STATUS (.+?)
+ Value ADMIN_STATE (.+?)
+ Value HARDWARE_TYPE (.\*)
+ Value ADDRESS ([a-zA-Z0-9]+.[a-zA-Z0-9]+.[a-zA-Z0-9]+)
+ Value BIA ([a-zA-Z0-9]+.[a-zA-Z0-9]+.[a-zA-Z0-9]+)
+ Value DESCRIPTION (.\*)
+ Value IP_ADDRESS (\d+\.\d+\.\d+\.\d+\/\d+)
+ Value MTU (\d+)
+ Value MODE (\S+)
+ Value DUPLEX (.+duplex?)
+ Value SPEED (.+?)
+ Value INPUT_PACKETS (\d+)
+ Value OUTPUT_PACKETS (\d+)
+ Value INPUT_ERRORS (\d+)
+ Value OUTPUT_ERRORS (\d+)
+ Value BANDWIDTH (\d+\s+\w+)
+ Value DELAY (\d+\s+\w+)
+ Value ENCAPSULATION (\w+)
+ Value LAST_LINK_FLAPPED (.+?)
+
+ Start
+ ^\S+\s+is.+ -> Continue.Record
+ ^${INTERFACE}\s+is\s+${LINK_STATUS},\sline\sprotocol\sis\s${ADMIN_STATE}$$
+ ^${INTERFACE}\s+is\s+${LINK_STATUS}$$
+ ^admin\s+state\s+is\s+${ADMIN_STATE},
+ ^\s+Hardware(:|\s+is)\s+${HARDWARE_TYPE},\s+address(:|\s+is)\s+${ADDRESS}(.*bia\s+${BIA})*
+ ^\s+Description:\s+${DESCRIPTION}
+ ^\s+Internet\s+Address\s+is\s+${IP_ADDRESS}
+ ^\s+Port\s+mode\s+is\s+${MODE}
+ ^\s+${DUPLEX}, ${SPEED}(,|$$)
+ ^\s+MTU\s+${MTU}.\*BW\s+${BANDWIDTH}.\*DLY\s+${DELAY}
+ ^\s+Encapsulation\s+${ENCAPSULATION}
+ ^\s+${INPUT_PACKETS}\s+input\s+packets\s+\d+\s+bytes\s\*$$
+ ^\s+${INPUT_ERRORS}\s+input\s+error\s+\d+\s+short\s+frame\s+\d+\s+overrun\s+\d+\s+underrun\s+\d+\s+ignored\s\*$$
+ ^\s+${OUTPUT_PACKETS}\s+output\s+packets\s+\d+\s+bytes\s\*$$
+ ^\s+${OUTPUT_ERRORS}\s+output\s+error\s+\d+\s+collision\s+\d+\s+deferred\s+\d+\s+late\s+collision\s\*$$
+ ^\s+Last\s+link\s+flapped\s+${LAST_LINK_FLAPPED}\s\*$$
+
+The following task uses the example template for ``textfsm`` with the ``cli_parse`` module.
+
+.. code-block:: yaml
+
+ - name: "Run command and parse with textfsm"
+ ansible.utils.cli_parse:
+ command: show interface
+ parser:
+ name: ansible.utils.textfsm
+ set_fact: interfaces
+
+Taking a deeper dive into this task:
+
+- The ``ansible_network_os`` for the device (``cisco.nxos.nxos``) is converted to ``nxos``. Alternately you can provide the OS in the ``parser/os`` option instead.
+- The textfsm template name defaulted to ``templates/nxos_show_interface.textfsm`` using a combination of the OS and command run. Alternately you can override the generated template path with the ``parser/template_path`` option.
+- See the `textfsm README <https://github.com/google/textfsm>`_ for details.
+- ``textfsm`` was previously made available as a filter plugin. Ansible users should transition to the ``cli_parse`` module.
+
+.. note::
+
+ Red Hat Ansible Automation Platform subscription support is limited to the use of the ``textfsm`` public APIs as documented.
+
+This task sets the following fact as the ``interfaces`` fact for the host:
+
+.. code-block:: yaml
+
+ - ADDRESS: X254.005a.f8b5
+ ADMIN_STATE: up
+ BANDWIDTH: 1000000 Kbit
+ BIA: X254.005a.f8b5
+ DELAY: 10 usec
+ DESCRIPTION: ''
+ DUPLEX: full-duplex
+ ENCAPSULATION: ARPA
+ HARDWARE_TYPE: Ethernet
+ INPUT_ERRORS: ''
+ INPUT_PACKETS: ''
+ INTERFACE: mgmt0
+ IP_ADDRESS: 192.168.101.14/24
+ LAST_LINK_FLAPPED: ''
+ LINK_STATUS: up
+ MODE: ''
+ MTU: '1500'
+ OUTPUT_ERRORS: ''
+ OUTPUT_PACKETS: ''
+ SPEED: 1000 Mb/s
+ - ADDRESS: X254.005a.f8bd
+ ADMIN_STATE: up
+ BANDWIDTH: 1000000 Kbit
+ BIA: X254.005a.f8bd
+
+
+Parsing with TTP
+-----------------
+
+TTP is a Python library for semi-structured text parsing using templates. TTP uses a jinja-like syntax to limit the need for regular expressions. Users familiar with jinja templating may find the TTP template syntax familiar.
+
+The following is an example TTP template stored as ``templates/nxos_show_interface.ttp``:
+
+.. code-block:: jinja
+
+ {{ interface }} is {{ state }}
+ admin state is {{ admin_state }}{{ ignore(".\*") }}
+
+The following task uses this template to parse the ``show interface`` command output:
+
+.. code-block:: yaml
+
+ - name: "Run command and parse with ttp"
+ ansible.utils.cli_parse:
+ command: show interface
+ parser:
+ name: ansible.utils.ttp
+ set_fact: interfaces
+
+Taking a deeper dive in this task:
+
+- The default template path ``templates/nxos_show_interface.ttp`` was generated using the ``ansible_network_os`` for the host and ``command`` provided.
+- TTP supports several additional variables that will be passed to the parser. These include:
+
+ - ``parser/vars/ttp_init`` - Additional parameter passed when the parser is initialized.
+ - ``parser/vars/ttp_results`` - Additional parameters used to influence the parser output.
+ - ``parser/vars/ttp_vars`` - Additional variables made available in the template.
+
+- See the `TTP documentation <https://ttp.readthedocs.io>`_ for details.
+
+
+The task sets the follow fact as the ``interfaces`` fact for the host:
+
+.. code-block:: yaml
+
+ - admin_state: up,
+ interface: mgmt0
+ state: up
+ - admin_state: up,
+ interface: Ethernet1/1
+ state: up
+ - admin_state: up,
+ interface: Ethernet1/2
+ state: up
+
+
+Parsing with JC
+-----------------
+
+JC is a python library that converts the output of dozens of common Linux/UNIX/macOS/Windows command-line tools and file types to python dictionaries or lists of dictionaries for easier parsing. JC is available as a filter plugin in the ``community.general`` collection.
+
+The following is an example using JC to parse the output of the ``dig`` command:
+
+.. code-block:: yaml
+
+ - name: "Run dig command and parse with jc"
+ hosts: ubuntu
+ tasks:
+ - shell: dig example.com
+ register: result
+ - set_fact:
+ myvar: "{{ result.stdout | community.general.jc('dig') }}"
+ - debug:
+ msg: "The IP is: {{ myvar[0].answer[0].data }}"
+
+- The JC project and documentation can be found `here <https://github.com/kellyjonbrazil/jc/>`_.
+- See this `blog entry <https://blog.kellybrazil.com/2020/08/30/parsing-command-output-in-ansible-with-jc/>`_ for more information.
+
+
+Converting XML
+-----------------
+
+Although Ansible contains a number of plugins that can convert XML to Ansible native data structures, the ``cli_parse`` module runs the command on devices that return XML and returns the converted data in a single task.
+
+This example task runs the ``show interface`` command and parses the output as XML:
+
+.. code-block:: yaml
+
+ - name: "Run command and parse as xml"
+ ansible.utils.cli_parse:
+ command: show interface | xml
+ parser:
+ name: ansible.utils.xml
+ set_fact: interfaces
+
+.. note::
+
+ Red Hat Ansible Automation Platform subscription support is limited to the use of the ``xmltodict`` public APIs as documented.
+
+This task sets the ``interfaces`` fact for the host based on this returned output:
+
+.. code-block:: yaml
+
+ nf:rpc-reply:
+ '@xmlns': http://www.cisco.com/nxos:1.0:if_manager
+ '@xmlns:nf': urn:ietf:params:xml:ns:netconf:base:1.0
+ nf:data:
+ show:
+ interface:
+ __XML__OPT_Cmd_show_interface_quick:
+ __XML__OPT_Cmd_show_interface___readonly__:
+ __readonly__:
+ TABLE_interface:
+ ROW_interface:
+ - admin_state: up
+ encapsulation: ARPA
+ eth_autoneg: 'on'
+ eth_bia_addr: x254.005a.f8b5
+ eth_bw: '1000000'
+
+
+Advanced use cases
+===================
+
+The ``cli_parse`` module supports several features to support more complex uses cases.
+
+Provide a full template path
+-----------------------------
+
+Use the ``template_path`` option to override the default template path in the task:
+
+.. code-block:: yaml
+
+ - name: "Run command and parse with native"
+ ansible.utils.cli_parse:
+ command: show interface
+ parser:
+ name: ansible.netcommon.native
+ template_path: /home/user/templates/filename.yaml
+
+
+Provide command to parser different than the command run
+-----------------------------------------------------------
+
+Use the ``command`` suboption for the ``parser`` to configure the command the parser expects if it is different from the command ``cli_parse`` runs:
+
+.. code-block:: yaml
+
+ - name: "Run command and parse with native"
+ ansible.utils.cli_parse:
+ command: sho int
+ parser:
+ name: ansible.netcommon.native
+ command: show interface
+
+Provide a custom OS value
+--------------------------------
+
+Use the ``os`` suboption to the parser to directly set the OS instead of using ``ansible_network_os`` or ``ansible_distribution`` to generate the template path or with the specified parser engine:
+
+.. code-block:: yaml
+
+ - name: Use ios instead of iosxe for pyats
+ ansible.utils.cli_parse:
+ command: show something
+ parser:
+ name: ansible.netcommon.pyats
+ os: ios
+
+ - name: Use linux instead of fedora from ansible_distribution
+ ansible.utils.cli_parse:
+ command: ps -ef
+ parser:
+ name: ansible.netcommon.native
+ os: linux
+
+
+Parse existing text
+--------------------
+
+Use the ``text`` option instead of ``command`` to parse text collected earlier in the playbook.
+
+.. code-block:: yaml
+
+ # using /home/user/templates/filename.yaml
+ - name: "Parse text from previous task"
+ ansible.utils.cli_parse:
+ text: "{{ output['stdout'] }}"
+ parser:
+ name: ansible.netcommon.native
+ template_path: /home/user/templates/filename.yaml
+
+ # using /home/user/templates/filename.yaml
+ - name: "Parse text from file"
+ ansible.utils.cli_parse:
+ text: "{{ lookup('file', 'path/to/file.txt') }}"
+ parser:
+ name: ansible.netcommon.native
+ template_path: /home/user/templates/filename.yaml
+
+ # using templates/nxos_show_version.yaml
+ - name: "Parse text from previous task"
+ ansible.utils.cli_parse:
+ text: "{{ sho_version['stdout'] }}"
+ parser:
+ name: ansible.netcommon.native
+ os: nxos
+ command: show version
+
+
+.. seealso::
+
+ * :ref:`develop_cli_parse_plugins`
diff --git a/docs/docsite/rst/network/user_guide/faq.rst b/docs/docsite/rst/network/user_guide/faq.rst
new file mode 100644
index 0000000..cb43ac2
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/faq.rst
@@ -0,0 +1,76 @@
+.. _network_faq:
+
+*******************
+Ansible Network FAQ
+*******************
+
+.. contents:: Topics
+
+.. _network_faq_performance:
+
+How can I improve performance for network playbooks?
+====================================================
+
+.. _network_faq_strategy_free:
+
+Consider ``strategy: free`` if you are running on multiple hosts
+---------------------------------------------------------------------------------
+
+The ``strategy`` plugin tells Ansible how to order multiple tasks on multiple hosts. :ref:`Strategy<strategy_plugins>` is set at the playbook level.
+
+The default strategy is ``linear``. With strategy set to ``linear``, Ansible waits until the current task has run on all hosts before starting the next task on any host. Ansible may have forks free, but will not use them until all hosts have completed the current task. If each task in your playbook must succeed on all hosts before you run the next task, use the ``linear`` strategy.
+
+Using the ``free`` strategy, Ansible uses available forks to execute tasks on each host as quickly as possible. Even if an earlier task is still running on one host, Ansible executes later tasks on other hosts. The ``free`` strategy uses available forks more efficiently. If your playbook stalls on each task, waiting for one slow host, consider using ``strategy: free`` to boost overall performance.
+
+.. _network_faq_limit_show_running:
+
+Execute ``show running`` only if you absolutely must
+---------------------------------------------------------------------------------
+
+The ``show running`` command is the most resource-intensive command to execute on a network device, because of the way queries are handled by the network OS. Using the command in your Ansible playbook will slow performance significantly, especially on large devices; repeating it will multiply the performance hit. If you have a playbook that checks the running config, then executes changes, then checks the running config again, you should expect that playbook to be very slow.
+
+.. _network_faq_limit_ProxyCommand:
+
+Use ``ProxyCommand`` only if you absolutely must
+---------------------------------------------------------------------------------
+
+Network modules support the use of a :ref:`proxy or jump host<network_delegate_to_vs_ProxyCommand>` with the ``ProxyCommand`` parameter. However, when you use a jump host, Ansible must open a new SSH connection for every task, even if you are using a persistent connection type (``network_cli`` or ``netconf``). To maximize the performance benefits of the persistent connection types introduced in version 2.5, avoid using jump hosts whenever possible.
+
+.. _network_faq_set_forks:
+
+Set ``--forks`` to match your needs
+---------------------------------------------------------------------------------
+
+Every time Ansible runs a task, it forks its own process. The ``--forks`` parameter defines the number of concurrent tasks - if you retain the default setting, which is ``--forks=5``, and you are running a playbook on 10 hosts, five of those hosts will have to wait until a fork is available. Of course, the more forks you allow, the more memory and processing power Ansible will use. Since most network tasks are run on the control host, this means your laptop can quickly become cpu- or memory-bound.
+
+.. _network_faq_redacted_output:
+
+Why is my output sometimes replaced with ``********``?
+======================================================
+
+Ansible replaces any string marked ``no_log``, including passwords, with ``********`` in Ansible output. This is done by design, to protect your sensitive data. Most users are happy to have their passwords redacted. However, Ansible replaces every string that matches your password with ``********``. If you use a common word for your password, this can be a problem. For example, if you choose ``Admin`` as your password, Ansible will replace every instance of the word ``Admin`` with ``********`` in your output. This may make your output harder to read. To avoid this problem, select a secure password that will not occur elsewhere in your Ansible output.
+
+.. _network_faq_no_abbreviations_with_config:
+
+Why do the ``*_config`` modules always return ``changed=true`` with abbreviated commands?
+=========================================================================================
+
+When you issue commands directly on a network device, you can use abbreviated commands. For example, ``int g1/0/11`` and ``interface GigabitEthernet1/0/11`` do the same thing; ``shut`` and ``shutdown`` do the same thing. Ansible Network ``*_command`` modules work with abbreviations, because they run commands through the network OS.
+
+When committing configuration, however, the network OS converts abbreviations into long-form commands. Whether you use ``shut`` or ``shutdown`` on ``GigabitEthernet1/0/11``, the result in the configuration is the same: ``shutdown``.
+
+Ansible Network ``*_config`` modules compare the text of the commands you specify in ``lines`` to the text in the configuration. If you use ``shut`` in the ``lines`` section of your task, and the configuration reads ``shutdown``, the module returns ``changed=true`` even though the configuration is already correct. Your task will update the configuration every time it runs.
+
+To avoid this problem, use long-form commands with the ``*_config`` modules:
+
+
+.. code-block:: yaml
+
+ ---
+ - hosts: all
+ gather_facts: no
+ tasks:
+ - cisco.ios.ios_config:
+ lines:
+ - shutdown
+ parents: interface GigabitEthernet1/0/11
diff --git a/docs/docsite/rst/network/user_guide/index.rst b/docs/docsite/rst/network/user_guide/index.rst
new file mode 100644
index 0000000..306a627
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/index.rst
@@ -0,0 +1,26 @@
+.. _network_advanced:
+
+**********************************
+Network Advanced Topics
+**********************************
+
+Once you have mastered the basics of network automation with Ansible, as presented in :ref:`network_getting_started`, use this guide understand platform-specific details, optimization, and troubleshooting tips for Ansible for network automation.
+
+**Who should use this guide?**
+
+This guide is intended for network engineers using Ansible for automation. It covers advanced topics. If you understand networks and Ansible, this guide is for you. You may read through the entire guide if you choose, or use the links below to find the specific information you need.
+
+If you're new to Ansible, or new to using Ansible for network automation, start with the :ref:`network_getting_started`.
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Advanced Topics
+
+ network_resource_modules
+ network_best_practices_2.5
+ cli_parsing
+ validate
+ network_debug_troubleshooting
+ network_working_with_command_output
+ faq
+ platform_index
diff --git a/docs/docsite/rst/network/user_guide/network_best_practices_2.5.rst b/docs/docsite/rst/network/user_guide/network_best_practices_2.5.rst
new file mode 100644
index 0000000..4b236ce
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/network_best_practices_2.5.rst
@@ -0,0 +1,483 @@
+.. _network-best-practices:
+
+************************
+Ansible Network Examples
+************************
+
+This document describes some examples of using Ansible to manage your network infrastructure.
+
+.. contents::
+ :local:
+
+Prerequisites
+=============
+
+This example requires the following:
+
+* **Ansible 2.10** (or higher) installed. See :ref:`intro_installation_guide` for more information.
+* One or more network devices that are compatible with Ansible.
+* Basic understanding of YAML :ref:`yaml_syntax`.
+* Basic understanding of Jinja2 templates. See :ref:`playbooks_templating` for more information.
+* Basic Linux command line use.
+* Basic knowledge of network switch & router configurations.
+
+
+Groups and variables in an inventory file
+=========================================
+
+An ``inventory`` file is a YAML or INI-like configuration file that defines the mapping of hosts into groups.
+
+In our example, the inventory file defines the groups ``eos``, ``ios``, ``vyos`` and a "group of groups" called ``switches``. Further details about subgroups and inventory files can be found in the :ref:`Ansible inventory Group documentation <subgroups>`.
+
+Because Ansible is a flexible tool, there are a number of ways to specify connection information and credentials. We recommend using the ``[my_group:vars]`` capability in your inventory file.
+
+.. code-block:: ini
+
+ [all:vars]
+ # these defaults can be overridden for any group in the [group:vars] section
+ ansible_connection=ansible.netcommon.network_cli
+ ansible_user=ansible
+
+ [switches:children]
+ eos
+ ios
+ vyos
+
+ [eos]
+ veos01 ansible_host=veos-01.example.net
+ veos02 ansible_host=veos-02.example.net
+ veos03 ansible_host=veos-03.example.net
+ veos04 ansible_host=veos-04.example.net
+
+ [eos:vars]
+ ansible_become=yes
+ ansible_become_method=enable
+ ansible_network_os=arista.eos.eos
+ ansible_user=my_eos_user
+ ansible_password=my_eos_password
+
+ [ios]
+ ios01 ansible_host=ios-01.example.net
+ ios02 ansible_host=ios-02.example.net
+ ios03 ansible_host=ios-03.example.net
+
+ [ios:vars]
+ ansible_become=yes
+ ansible_become_method=enable
+ ansible_network_os=cisco.ios.ios
+ ansible_user=my_ios_user
+ ansible_password=my_ios_password
+
+ [vyos]
+ vyos01 ansible_host=vyos-01.example.net
+ vyos02 ansible_host=vyos-02.example.net
+ vyos03 ansible_host=vyos-03.example.net
+
+ [vyos:vars]
+ ansible_network_os=vyos.vyos.vyos
+ ansible_user=my_vyos_user
+ ansible_password=my_vyos_password
+
+If you use ssh-agent, you do not need the ``ansible_password`` lines. If you use ssh keys, but not ssh-agent, and you have multiple keys, specify the key to use for each connection in the ``[group:vars]`` section with ``ansible_ssh_private_key_file=/path/to/correct/key``. For more information on ``ansible_ssh_`` options see :ref:`behavioral_parameters`.
+
+.. FIXME FUTURE Gundalow - Link to network auth & proxy page (to be written)
+
+.. warning:: Never store passwords in plain text.
+
+Ansible vault for password encryption
+-------------------------------------
+
+The "Vault" feature of Ansible allows you to keep sensitive data such as passwords or keys in encrypted files, rather than as plain text in your playbooks or roles. These vault files can then be distributed or placed in source control. See :ref:`playbooks_vault` for more information.
+
+Here's what it would look like if you specified your SSH passwords (encrypted with Ansible Vault) among your variables:
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: vyos.vyos.vyos
+ ansible_user: my_vyos_user
+ ansible_ssh_pass: !vault |
+ $ANSIBLE_VAULT;1.1;AES256
+ 39336231636137663964343966653162353431333566633762393034646462353062633264303765
+ 6331643066663534383564343537343334633031656538370a333737656236393835383863306466
+ 62633364653238323333633337313163616566383836643030336631333431623631396364663533
+ 3665626431626532630a353564323566316162613432373738333064366130303637616239396438
+ 9853
+
+Common inventory variables
+--------------------------
+
+The following variables are common for all platforms in the inventory, though they can be overwritten for a particular inventory group or host.
+
+:ansible_connection:
+
+ Ansible uses the ansible-connection setting to determine how to connect to a remote device. When working with Ansible Networking, set this to an appropriate network connection option, such as``ansible.netcommon.network_cli``, so Ansible treats the remote node as a network device with a limited execution environment. Without this setting, Ansible would attempt to use ssh to connect to the remote and execute the Python script on the network device, which would fail because Python generally isn't available on network devices.
+:ansible_network_os:
+ Informs Ansible which Network platform this hosts corresponds to. This is required when using the ``ansible.netcommon.*`` connection options.
+:ansible_user: The user to connect to the remote device (switch) as. Without this the user that is running ``ansible-playbook`` would be used.
+ Specifies which user on the network device the connection
+:ansible_password:
+ The corresponding password for ``ansible_user`` to log in as. If not specified SSH key will be used.
+:ansible_become:
+ If enable mode (privilege mode) should be used, see the next section.
+:ansible_become_method:
+ Which type of `become` should be used, for ``network_cli`` the only valid choice is ``enable``.
+
+Privilege escalation
+--------------------
+
+Certain network platforms, such as Arista EOS and Cisco IOS, have the concept of different privilege modes. Certain network modules, such as those that modify system state including users, will only work in high privilege states. Ansible supports ``become`` when using ``connection: ansible.netcommon.network_cli``. This allows privileges to be raised for the specific tasks that need them. Adding ``become: yes`` and ``become_method: enable`` informs Ansible to go into privilege mode before executing the task, as shown here:
+
+.. code-block:: ini
+
+ [eos:vars]
+ ansible_connection=ansible.netcommon.network_cli
+ ansible_network_os=arista.eos.eos
+ ansible_become=yes
+ ansible_become_method=enable
+
+For more information, see the :ref:`using become with network modules<become_network>` guide.
+
+
+Jump hosts
+----------
+
+If the Ansible Controller does not have a direct route to the remote device and you need to use a Jump Host, please see the :ref:`Ansible Network Proxy Command <network_delegate_to_vs_ProxyCommand>` guide for details on how to achieve this.
+
+Example 1: collecting facts and creating backup files with a playbook
+=====================================================================
+
+Ansible facts modules gather system information 'facts' that are available to the rest of your playbook.
+
+Ansible Networking ships with a number of network-specific facts modules. In this example, we use the ``_facts`` modules :ref:`arista.eos.eos_facts <ansible_collections.arista.eos.eos_facts_module>`, :ref:`cisco.ios.ios_facts <ansible_collections.cisco.ios.ios_facts_module>` and :ref:`vyos.vyos.vyos_facts <ansible_collections.vyos.vyos.vyos_facts_module>` to connect to the remote networking device. As the credentials are not explicitly passed with module arguments, Ansible uses the username and password from the inventory file.
+
+Ansible's "Network Fact modules" gather information from the system and store the results in facts prefixed with ``ansible_net_``. The data collected by these modules is documented in the `Return Values` section of the module docs, in this case :ref:`arista.eos.eos_facts <ansible_collections.arista.eos.eos_facts_module>` and :ref:`vyos.vyos.vyos_facts <ansible_collections.vyos.vyos.vyos_facts_module>`. We can use the facts, such as ``ansible_net_version`` late on in the "Display some facts" task.
+
+To ensure we call the correct mode (``*_facts``) the task is conditionally run based on the group defined in the inventory file, for more information on the use of conditionals in Ansible Playbooks see :ref:`the_when_statement`.
+
+In this example, we will create an inventory file containing some network switches, then run a playbook to connect to the network devices and return some information about them.
+
+Step 1: Creating the inventory
+------------------------------
+
+First, create a file called ``inventory``, containing:
+
+.. code-block:: ini
+
+ [switches:children]
+ eos
+ ios
+ vyos
+
+ [eos]
+ eos01.example.net
+
+ [ios]
+ ios01.example.net
+
+ [vyos]
+ vyos01.example.net
+
+
+Step 2: Creating the playbook
+-----------------------------
+
+Next, create a playbook file called ``facts-demo.yml`` containing the following:
+
+.. code-block:: yaml
+
+ - name: "Demonstrate connecting to switches"
+ hosts: switches
+ gather_facts: no
+
+ tasks:
+ ###
+ # Collect data
+ #
+ - name: Gather facts (eos)
+ arista.eos.eos_facts:
+ when: ansible_network_os == 'arista.eos.eos'
+
+ - name: Gather facts (ios)
+ cisco.ios.ios_facts:
+ when: ansible_network_os == 'cisco.ios.ios'
+
+ - name: Gather facts (vyos)
+ vyos.vyos.vyos_facts:
+ when: ansible_network_os == 'vyos.vyos.vyos'
+
+ ###
+ # Demonstrate variables
+ #
+ - name: Display some facts
+ debug:
+ msg: "The hostname is {{ ansible_net_hostname }} and the OS is {{ ansible_net_version }}"
+
+ - name: Facts from a specific host
+ debug:
+ var: hostvars['vyos01.example.net']
+
+ - name: Write facts to disk using a template
+ copy:
+ content: |
+ #jinja2: lstrip_blocks: True
+ EOS device info:
+ {% for host in groups['eos'] %}
+ Hostname: {{ hostvars[host].ansible_net_hostname }}
+ Version: {{ hostvars[host].ansible_net_version }}
+ Model: {{ hostvars[host].ansible_net_model }}
+ Serial: {{ hostvars[host].ansible_net_serialnum }}
+ {% endfor %}
+
+ IOS device info:
+ {% for host in groups['ios'] %}
+ Hostname: {{ hostvars[host].ansible_net_hostname }}
+ Version: {{ hostvars[host].ansible_net_version }}
+ Model: {{ hostvars[host].ansible_net_model }}
+ Serial: {{ hostvars[host].ansible_net_serialnum }}
+ {% endfor %}
+
+ VyOS device info:
+ {% for host in groups['vyos'] %}
+ Hostname: {{ hostvars[host].ansible_net_hostname }}
+ Version: {{ hostvars[host].ansible_net_version }}
+ Model: {{ hostvars[host].ansible_net_model }}
+ Serial: {{ hostvars[host].ansible_net_serialnum }}
+ {% endfor %}
+ dest: /tmp/switch-facts
+ run_once: yes
+
+ ###
+ # Get running configuration
+ #
+
+ - name: Backup switch (eos)
+ arista.eos.eos_config:
+ backup: yes
+ register: backup_eos_location
+ when: ansible_network_os == 'arista.eos.eos'
+
+ - name: backup switch (vyos)
+ vyos.vyos.vyos_config:
+ backup: yes
+ register: backup_vyos_location
+ when: ansible_network_os == 'vyos.vyos.vyos'
+
+ - name: Create backup dir
+ file:
+ path: "/tmp/backups/{{ inventory_hostname }}"
+ state: directory
+ recurse: yes
+
+ - name: Copy backup files into /tmp/backups/ (eos)
+ copy:
+ src: "{{ backup_eos_location.backup_path }}"
+ dest: "/tmp/backups/{{ inventory_hostname }}/{{ inventory_hostname }}.bck"
+ when: ansible_network_os == 'arista.eos.eos'
+
+ - name: Copy backup files into /tmp/backups/ (vyos)
+ copy:
+ src: "{{ backup_vyos_location.backup_path }}"
+ dest: "/tmp/backups/{{ inventory_hostname }}/{{ inventory_hostname }}.bck"
+ when: ansible_network_os == 'vyos.vyos.vyos'
+
+Step 3: Running the playbook
+----------------------------
+
+To run the playbook, run the following from a console prompt:
+
+.. code-block:: console
+
+ ansible-playbook -i inventory facts-demo.yml
+
+This should return output similar to the following:
+
+.. code-block:: console
+
+ PLAY RECAP
+ eos01.example.net : ok=7 changed=2 unreachable=0 failed=0
+ ios01.example.net : ok=7 changed=2 unreachable=0 failed=0
+ vyos01.example.net : ok=6 changed=2 unreachable=0 failed=0
+
+Step 4: Examining the playbook results
+--------------------------------------
+
+Next, look at the contents of the file we created containing the switch facts:
+
+.. code-block:: console
+
+ cat /tmp/switch-facts
+
+You can also look at the backup files:
+
+.. code-block:: console
+
+ find /tmp/backups
+
+
+If `ansible-playbook` fails, please follow the debug steps in :ref:`network_debug_troubleshooting`.
+
+
+.. _network-independent-examples:
+
+Example 2: simplifying playbooks with platform-independent modules
+==================================================================
+
+(This example originally appeared in the `Deep Dive on cli_command for Network Automation <https://www.ansible.com/blog/deep-dive-on-cli-command-for-network-automation>`_ blog post by Sean Cavanaugh -`@IPvSean <https://github.com/IPvSean>`_).
+
+If you have two or more network platforms in your environment, you can use the platform-independent modules to simplify your playbooks. You can use platform-independent modules such as ``ansible.netcommon.cli_command`` or ``ansible.netcommon.cli_config`` in place of the platform-specific modules such as ``arista.eos.eos_config``, ``cisco.ios.ios_config``, and ``junipernetworks.junos.junos_config``. This reduces the number of tasks and conditionals you need in your playbooks.
+
+.. note::
+ Platform-independent modules require the :ref:`ansible.netcommon.network_cli <ansible_collections.ansible.netcommon.network_cli_connection>` connection plugin.
+
+
+Sample playbook with platform-specific modules
+----------------------------------------------
+
+This example assumes three platforms, Arista EOS, Cisco NXOS, and Juniper JunOS. Without the platform-independent modules, a sample playbook might contain the following three tasks with platform-specific commands:
+
+.. code-block:: yaml
+
+ ---
+ - name: Run Arista command
+ arista.eos.eos_command:
+ commands: show ip int br
+ when: ansible_network_os == 'arista.eos.eos'
+
+ - name: Run Cisco NXOS command
+ cisco.nxos.nxos_command:
+ commands: show ip int br
+ when: ansible_network_os == 'cisco.nxos.nxos'
+
+ - name: Run Vyos command
+ vyos.vyos.vyos_command:
+ commands: show interface
+ when: ansible_network_os == 'vyos.vyos.vyos'
+
+Simplified playbook with ``cli_command`` platform-independent module
+--------------------------------------------------------------------
+
+You can replace these platform-specific modules with the platform-independent ``ansible.netcommon.cli_command`` module as follows:
+
+.. code-block:: yaml
+
+ ---
+ - hosts: network
+ gather_facts: false
+ connection: ansible.netcommon.network_cli
+
+ tasks:
+ - name: Run cli_command on Arista and display results
+ block:
+ - name: Run cli_command on Arista
+ ansible.netcommon.cli_command:
+ command: show ip int br
+ register: result
+
+ - name: Display result to terminal window
+ debug:
+ var: result.stdout_lines
+ when: ansible_network_os == 'arista.eos.eos'
+
+ - name: Run cli_command on Cisco IOS and display results
+ block:
+ - name: Run cli_command on Cisco IOS
+ ansible.netcommon.cli_command:
+ command: show ip int br
+ register: result
+
+ - name: Display result to terminal window
+ debug:
+ var: result.stdout_lines
+ when: ansible_network_os == 'cisco.ios.ios'
+
+ - name: Run cli_command on Vyos and display results
+ block:
+ - name: Run cli_command on Vyos
+ ansible.netcommon.cli_command:
+ command: show interfaces
+ register: result
+
+ - name: Display result to terminal window
+ debug:
+ var: result.stdout_lines
+ when: ansible_network_os == 'vyos.vyos.vyos'
+
+
+If you use groups and group_vars by platform type, this playbook can be further simplified to :
+
+.. code-block:: yaml
+
+ ---
+ - name: Run command and print to terminal window
+ hosts: routers
+ gather_facts: false
+
+ tasks:
+ - name: Run show command
+ ansible.netcommon.cli_command:
+ command: "{{show_interfaces}}"
+ register: command_output
+
+
+You can see a full example of this using group_vars and also a configuration backup example at `Platform-independent examples <https://github.com/network-automation/agnostic_example>`_.
+
+Using multiple prompts with the ``ansible.netcommon.cli_command``
+-------------------------------------------------------------------
+
+The ``ansible.netcommon.cli_command`` also supports multiple prompts.
+
+.. code-block:: yaml
+
+ ---
+ - name: Change password to default
+ ansible.netcommon.cli_command:
+ command: "{{ item }}"
+ prompt:
+ - "New password"
+ - "Retype new password"
+ answer:
+ - "mypassword123"
+ - "mypassword123"
+ check_all: True
+ loop:
+ - "configure"
+ - "rollback"
+ - "set system root-authentication plain-text-password"
+ - "commit"
+
+See the :ref:`ansible.netcommon.cli_command <cli_command_module>` for full documentation on this command.
+
+
+Implementation Notes
+====================
+
+
+Demo variables
+--------------
+
+Although these tasks are not needed to write data to disk, they are used in this example to demonstrate some methods of accessing facts about the given devices or a named host.
+
+Ansible ``hostvars`` allows you to access variables from a named host. Without this we would return the details for the current host, rather than the named host.
+
+For more information, see :ref:`magic_variables_and_hostvars`.
+
+Get running configuration
+-------------------------
+
+The :ref:`arista.eos.eos_config <ansible_collections.arista.eos.eos_config_module>` and :ref:`vyos.vyos.vyos_config <ansible_collections.vyos.vyos.vyos_config_module>` modules have a ``backup:`` option that when set will cause the module to create a full backup of the current ``running-config`` from the remote device before any changes are made. The backup file is written to the ``backup`` folder in the playbook root directory. If the directory does not exist, it is created.
+
+To demonstrate how we can move the backup file to a different location, we register the result and move the file to the path stored in ``backup_path``.
+
+Note that when using variables from tasks in this way we use double quotes (``"``) and double curly-brackets (``{{...}}`` to tell Ansible that this is a variable.
+
+Troubleshooting
+===============
+
+If you receive an connection error please double check the inventory and playbook for typos or missing lines. If the issue still occurs follow the debug steps in :ref:`network_debug_troubleshooting`.
+
+.. seealso::
+
+ * :ref:`network_guide`
+ * :ref:`intro_inventory`
+ * :ref:`Keeping vaulted variables visible <tip_for_variables_and_vaults>`
diff --git a/docs/docsite/rst/network/user_guide/network_debug_troubleshooting.rst b/docs/docsite/rst/network/user_guide/network_debug_troubleshooting.rst
new file mode 100644
index 0000000..d0fbcd6
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/network_debug_troubleshooting.rst
@@ -0,0 +1,840 @@
+.. _network_debug_troubleshooting:
+
+***************************************
+Network Debug and Troubleshooting Guide
+***************************************
+
+This section discusses how to debug and troubleshoot network modules in Ansible.
+
+.. contents::
+ :local:
+
+
+How to troubleshoot
+===================
+
+Ansible network automation errors generally fall into one of the following categories:
+
+:Authentication issues:
+ * Not correctly specifying credentials
+ * Remote device (network switch/router) not falling back to other other authentication methods
+ * SSH key issues
+:Timeout issues:
+ * Can occur when trying to pull a large amount of data
+ * May actually be masking a authentication issue
+:Playbook issues:
+ * Use of ``delegate_to``, instead of ``ProxyCommand``. See :ref:`network proxy guide <network_delegate_to_vs_ProxyCommand>` for more information.
+
+.. warning:: ``unable to open shell``
+
+ The ``unable to open shell`` message means that the ``ansible-connection`` daemon has not been able to successfully
+ talk to the remote network device. This generally means that there is an authentication issue. See the "Authentication and connection issues" section
+ in this document for more information.
+
+.. _enable_network_logging:
+
+Enabling Networking logging and how to read the logfile
+-------------------------------------------------------
+
+**Platforms:** Any
+
+Ansible includes logging to help diagnose and troubleshoot issues regarding Ansible Networking modules.
+
+Because logging is very verbose, it is disabled by default. It can be enabled with the :envvar:`ANSIBLE_LOG_PATH` and :envvar:`ANSIBLE_DEBUG` options on the ansible-controller, that is the machine running ``ansible-playbook``.
+
+Before running ``ansible-playbook``, run the following commands to enable logging:
+
+.. code:: shell
+
+ # Specify the location for the log file
+ export ANSIBLE_LOG_PATH=~/ansible.log
+ # Enable Debug
+ export ANSIBLE_DEBUG=True
+
+ # Run with 4*v for connection level verbosity
+ ansible-playbook -vvvv ...
+
+After Ansible has finished running you can inspect the log file which has been created on the ansible-controller:
+
+.. code::
+
+ less $ANSIBLE_LOG_PATH
+
+ 2017-03-30 13:19:52,740 p=28990 u=fred | creating new control socket for host veos01:22 as user admin
+ 2017-03-30 13:19:52,741 p=28990 u=fred | control socket path is /home/fred/.ansible/pc/ca5960d27a
+ 2017-03-30 13:19:52,741 p=28990 u=fred | current working directory is /home/fred/ansible/test/integration
+ 2017-03-30 13:19:52,741 p=28990 u=fred | using connection plugin network_cli
+ ...
+ 2017-03-30 13:20:14,771 paramiko.transport userauth is OK
+ 2017-03-30 13:20:15,283 paramiko.transport Authentication (keyboard-interactive) successful!
+ 2017-03-30 13:20:15,302 p=28990 u=fred | ssh connection done, setting terminal
+ 2017-03-30 13:20:15,321 p=28990 u=fred | ssh connection has completed successfully
+ 2017-03-30 13:20:15,322 p=28990 u=fred | connection established to veos01 in 0:00:22.580626
+
+
+From the log notice:
+
+* ``p=28990`` Is the PID (Process ID) of the ``ansible-connection`` process
+* ``u=fred`` Is the user `running` ansible, not the remote-user you are attempting to connect as
+* ``creating new control socket for host veos01:22 as user admin`` host:port as user
+* ``control socket path is`` location on disk where the persistent connection socket is created
+* ``using connection plugin network_cli`` Informs you that persistent connection is being used
+* ``connection established to veos01 in 0:00:22.580626`` Time taken to obtain a shell on the remote device
+
+
+.. note:: Port None ``creating new control socket for host veos01:None``
+
+ If the log reports the port as ``None`` this means that the default port is being used.
+ A future Ansible release will improve this message so that the port is always logged.
+
+Because the log files are verbose, you can use grep to look for specific information. For example, once you have identified the ``pid`` from the ``creating new control socket for host`` line you can search for other connection log entries:
+
+.. code:: shell
+
+ grep "p=28990" $ANSIBLE_LOG_PATH
+
+
+Enabling Networking device interaction logging
+----------------------------------------------
+
+**Platforms:** Any
+
+Ansible includes logging of device interaction in the log file to help diagnose and troubleshoot
+issues regarding Ansible Networking modules. The messages are logged in the file pointed to by the ``log_path`` configuration
+option in the Ansible configuration file or by setting the :envvar:`ANSIBLE_LOG_PATH`.
+
+.. warning::
+ The device interaction messages consist of command executed on the target device and the returned response. Since this
+ log data can contain sensitive information including passwords in plain text it is disabled by default.
+ Additionally, in order to prevent accidental leakage of data, a warning will be shown on every task with this
+ setting enabled, specifying which host has it enabled and where the data is being logged.
+
+Be sure to fully understand the security implications of enabling this option. The device interaction logging can be enabled either globally by setting in configuration file or by setting environment or enabled on per task basis by passing a special variable to the task.
+
+Before running ``ansible-playbook`` run the following commands to enable logging:
+
+.. code-block:: text
+
+ # Specify the location for the log file
+ export ANSIBLE_LOG_PATH=~/ansible.log
+
+
+Enable device interaction logging for a given task
+
+.. code-block:: yaml
+
+ - name: get version information
+ cisco.ios.ios_command:
+ commands:
+ - show version
+ vars:
+ ansible_persistent_log_messages: True
+
+
+To make this a global setting, add the following to your ``ansible.cfg`` file:
+
+.. code-block:: ini
+
+ [persistent_connection]
+ log_messages = True
+
+or enable the environment variable `ANSIBLE_PERSISTENT_LOG_MESSAGES`:
+
+.. code-block:: text
+
+ # Enable device interaction logging
+ export ANSIBLE_PERSISTENT_LOG_MESSAGES=True
+
+If the task is failing on connection initialization itself, you should enable this option
+globally. If an individual task is failing intermittently this option can be enabled for that task itself to find the root cause.
+
+After Ansible has finished running you can inspect the log file which has been created on the ansible-controller
+
+.. note:: Be sure to fully understand the security implications of enabling this option as it can log sensitive
+ information in log file thus creating security vulnerability.
+
+
+Isolating an error
+------------------
+
+**Platforms:** Any
+
+As with any effort to troubleshoot it's important to simplify the test case as much as possible.
+
+For Ansible this can be done by ensuring you are only running against one remote device:
+
+* Using ``ansible-playbook --limit switch1.example.net...``
+* Using an ad hoc ``ansible`` command
+
+`ad hoc` refers to running Ansible to perform some quick command using ``/usr/bin/ansible``, rather than the orchestration language, which is ``/usr/bin/ansible-playbook``. In this case we can ensure connectivity by attempting to execute a single command on the remote device:
+
+.. code-block:: text
+
+ ansible -m arista.eos.eos_command -a 'commands=?' -i inventory switch1.example.net -e 'ansible_connection=ansible.netcommon.network_cli' -u admin -k
+
+In the above example, we:
+
+* connect to ``switch1.example.net`` specified in the inventory file ``inventory``
+* use the module ``arista.eos.eos_command``
+* run the command ``?``
+* connect using the username ``admin``
+* inform the ``ansible`` command to prompt for the SSH password by specifying ``-k``
+
+If you have SSH keys configured correctly, you don't need to specify the ``-k`` parameter.
+
+If the connection still fails you can combine it with the enable_network_logging parameter. For example:
+
+.. code-block:: text
+
+ # Specify the location for the log file
+ export ANSIBLE_LOG_PATH=~/ansible.log
+ # Enable Debug
+ export ANSIBLE_DEBUG=True
+ # Run with ``-vvvv`` for connection level verbosity
+ ansible -m arista.eos.eos_command -a 'commands=?' -i inventory switch1.example.net -e 'ansible_connection=ansible.netcommon.network_cli' -u admin -k
+
+Then review the log file and find the relevant error message in the rest of this document.
+
+.. For details on other ways to authenticate, see LINKTOAUTHHOWTODOCS.
+
+.. _socket_path_issue:
+
+Troubleshooting socket path issues
+==================================
+
+**Platforms:** Any
+
+The ``Socket path does not exist or cannot be found`` and ``Unable to connect to socket`` messages indicate that the socket used to communicate with the remote network device is unavailable or does not exist.
+
+For example:
+
+.. code-block:: none
+
+ fatal: [spine02]: FAILED! => {
+ "changed": false,
+ "failed": true,
+ "module_stderr": "Traceback (most recent call last):\n File \"/tmp/ansible_TSqk5J/ansible_modlib.zip/ansible/module_utils/connection.py\", line 115, in _exec_jsonrpc\nansible.module_utils.connection.ConnectionError: Socket path XX does not exist or cannot be found. See Troubleshooting socket path issues in the Network Debug and Troubleshooting Guide\n",
+ "module_stdout": "",
+ "msg": "MODULE FAILURE",
+ "rc": 1
+ }
+
+or
+
+.. code-block:: none
+
+ fatal: [spine02]: FAILED! => {
+ "changed": false,
+ "failed": true,
+ "module_stderr": "Traceback (most recent call last):\n File \"/tmp/ansible_TSqk5J/ansible_modlib.zip/ansible/module_utils/connection.py\", line 123, in _exec_jsonrpc\nansible.module_utils.connection.ConnectionError: Unable to connect to socket XX. See Troubleshooting socket path issues in Network Debug and Troubleshooting Guide\n",
+ "module_stdout": "",
+ "msg": "MODULE FAILURE",
+ "rc": 1
+ }
+
+Suggestions to resolve:
+
+#. Verify that you have write access to the socket path described in the error message.
+
+#. Follow the steps detailed in :ref:`enable network logging <enable_network_logging>`.
+
+If the identified error message from the log file is:
+
+.. code-block:: yaml
+
+ 2017-04-04 12:19:05,670 p=18591 u=fred | command timeout triggered, timeout value is 30 secs
+
+or
+
+.. code-block:: yaml
+
+ 2017-04-04 12:19:05,670 p=18591 u=fred | persistent connection idle timeout triggered, timeout value is 30 secs
+
+Follow the steps detailed in :ref:`timeout issues <timeout_issues>`
+
+
+.. _unable_to_open_shell:
+
+Category "Unable to open shell"
+===============================
+
+
+**Platforms:** Any
+
+The ``unable to open shell`` message means that the ``ansible-connection`` daemon has not been able to successfully talk to the remote network device. This generally means that there is an authentication issue. It is a "catch all" message, meaning you need to enable :ref:`logging <a_note_about_logging>` to find the underlying issues.
+
+
+
+For example:
+
+.. code-block:: none
+
+ TASK [prepare_eos_tests : enable cli on remote device] **************************************************
+ fatal: [veos01]: FAILED! => {"changed": false, "failed": true, "msg": "unable to open shell"}
+
+
+or:
+
+
+.. code-block:: none
+
+ TASK [ios_system : configure name_servers] *************************************************************
+ task path:
+ fatal: [ios-csr1000v]: FAILED! => {
+ "changed": false,
+ "failed": true,
+ "msg": "unable to open shell",
+ }
+
+Suggestions to resolve:
+
+Follow the steps detailed in enable_network_logging_.
+
+Once you've identified the error message from the log file, the specific solution can be found in the rest of this document.
+
+
+
+Error: "[Errno -2] Name or service not known"
+---------------------------------------------
+
+**Platforms:** Any
+
+Indicates that the remote host you are trying to connect to can not be reached
+
+For example:
+
+.. code-block:: yaml
+
+ 2017-04-04 11:39:48,147 p=15299 u=fred | control socket path is /home/fred/.ansible/pc/ca5960d27a
+ 2017-04-04 11:39:48,147 p=15299 u=fred | current working directory is /home/fred/git/ansible-inc/stable-2.3/test/integration
+ 2017-04-04 11:39:48,147 p=15299 u=fred | using connection plugin network_cli
+ 2017-04-04 11:39:48,340 p=15299 u=fred | connecting to host veos01 returned an error
+ 2017-04-04 11:39:48,340 p=15299 u=fred | [Errno -2] Name or service not known
+
+
+Suggestions to resolve:
+
+* If you are using the ``provider:`` options ensure that its suboption ``host:`` is set correctly.
+* If you are not using ``provider:`` nor top-level arguments ensure your inventory file is correct.
+
+
+
+
+
+Error: "Authentication failed"
+------------------------------
+
+**Platforms:** Any
+
+Occurs if the credentials (username, passwords, or ssh keys) passed to ``ansible-connection`` (through ``ansible`` or ``ansible-playbook``) can not be used to connect to the remote device.
+
+
+
+For example:
+
+.. code-block:: yaml
+
+ <ios01> ESTABLISH CONNECTION FOR USER: cisco on PORT 22 TO ios01
+ <ios01> Authentication failed.
+
+
+Suggestions to resolve:
+
+If you are specifying credentials through ``password:`` (either directly or through ``provider:``) or the environment variable `ANSIBLE_NET_PASSWORD` it is possible that ``paramiko`` (the Python SSH library that Ansible uses) is using ssh keys, and therefore the credentials you are specifying are being ignored. To find out if this is the case, disable "look for keys". This can be done like this:
+
+.. code-block:: yaml
+
+ export ANSIBLE_PARAMIKO_LOOK_FOR_KEYS=False
+
+To make this a permanent change, add the following to your ``ansible.cfg`` file:
+
+.. code-block:: ini
+
+ [paramiko_connection]
+ look_for_keys = False
+
+
+Error: "connecting to host <hostname> returned an error" or "Bad address"
+-------------------------------------------------------------------------
+
+This may occur if the SSH fingerprint hasn't been added to Paramiko's (the Python SSH library) know hosts file.
+
+When using persistent connections with Paramiko, the connection runs in a background process. If the host doesn't already have a valid SSH key, by default Ansible will prompt to add the host key. This will cause connections running in background processes to fail.
+
+For example:
+
+.. code-block:: yaml
+
+ 2017-04-04 12:06:03,486 p=17981 u=fred | using connection plugin network_cli
+ 2017-04-04 12:06:04,680 p=17981 u=fred | connecting to host veos01 returned an error
+ 2017-04-04 12:06:04,682 p=17981 u=fred | (14, 'Bad address')
+ 2017-04-04 12:06:33,519 p=17981 u=fred | number of connection attempts exceeded, unable to connect to control socket
+ 2017-04-04 12:06:33,520 p=17981 u=fred | persistent_connect_interval=1, persistent_connect_retries=30
+
+
+Suggestions to resolve:
+
+Use ``ssh-keyscan`` to pre-populate the known_hosts. You need to ensure the keys are correct.
+
+.. code-block:: shell
+
+ ssh-keyscan veos01
+
+
+or
+
+You can tell Ansible to automatically accept the keys
+
+Environment variable method:
+
+.. code-block:: shell
+
+ export ANSIBLE_PARAMIKO_HOST_KEY_AUTO_ADD=True
+ ansible-playbook ...
+
+``ansible.cfg`` method:
+
+ansible.cfg
+
+.. code-block:: ini
+
+ [paramiko_connection]
+ host_key_auto_add = True
+
+
+
+.. warning: Security warning
+
+ Care should be taken before accepting keys.
+
+Error: "No authentication methods available"
+--------------------------------------------
+
+For example:
+
+.. code-block:: yaml
+
+ 2017-04-04 12:19:05,670 p=18591 u=fred | creating new control socket for host veos01:None as user admin
+ 2017-04-04 12:19:05,670 p=18591 u=fred | control socket path is /home/fred/.ansible/pc/ca5960d27a
+ 2017-04-04 12:19:05,670 p=18591 u=fred | current working directory is /home/fred/git/ansible-inc/ansible-workspace-2/test/integration
+ 2017-04-04 12:19:05,670 p=18591 u=fred | using connection plugin network_cli
+ 2017-04-04 12:19:06,606 p=18591 u=fred | connecting to host veos01 returned an error
+ 2017-04-04 12:19:06,606 p=18591 u=fred | No authentication methods available
+ 2017-04-04 12:19:35,708 p=18591 u=fred | connect retry timeout expired, unable to connect to control socket
+ 2017-04-04 12:19:35,709 p=18591 u=fred | persistent_connect_retry_timeout is 15 secs
+
+
+Suggestions to resolve:
+
+No password or SSH key supplied
+
+Clearing Out Persistent Connections
+-----------------------------------
+
+**Platforms:** Any
+
+In Ansible 2.3, persistent connection sockets are stored in ``~/.ansible/pc`` for all network devices. When an Ansible playbook runs, the persistent socket connection is displayed when verbose output is specified.
+
+``<switch> socket_path: /home/fred/.ansible/pc/f64ddfa760``
+
+To clear out a persistent connection before it times out (the default timeout is 30 seconds
+of inactivity), simple delete the socket file.
+
+
+.. _timeout_issues:
+
+Timeout issues
+==============
+
+Persistent connection idle timeout
+----------------------------------
+
+By default, ``ANSIBLE_PERSISTENT_CONNECT_TIMEOUT`` is set to 30 (seconds). You may see the following error if this value is too low:
+
+.. code-block:: yaml
+
+ 2017-04-04 12:19:05,670 p=18591 u=fred | persistent connection idle timeout triggered, timeout value is 30 secs
+
+Suggestions to resolve:
+
+Increase value of persistent connection idle timeout:
+
+.. code-block:: sh
+
+ export ANSIBLE_PERSISTENT_CONNECT_TIMEOUT=60
+
+To make this a permanent change, add the following to your ``ansible.cfg`` file:
+
+.. code-block:: ini
+
+ [persistent_connection]
+ connect_timeout = 60
+
+Command timeout
+---------------
+
+By default, ``ANSIBLE_PERSISTENT_COMMAND_TIMEOUT`` is set to 30 (seconds). Prior versions of Ansible had this value set to 10 seconds by default.
+You may see the following error if this value is too low:
+
+
+.. code-block:: yaml
+
+ 2017-04-04 12:19:05,670 p=18591 u=fred | command timeout triggered, timeout value is 30 secs
+
+Suggestions to resolve:
+
+* Option 1 (Global command timeout setting):
+ Increase value of command timeout in configuration file or by setting environment variable.
+
+ .. code-block:: yaml
+
+ export ANSIBLE_PERSISTENT_COMMAND_TIMEOUT=60
+
+ To make this a permanent change, add the following to your ``ansible.cfg`` file:
+
+ .. code-block:: ini
+
+ [persistent_connection]
+ command_timeout = 60
+
+* Option 2 (Per task command timeout setting):
+ Increase command timeout per task basis. All network modules support a
+ timeout value that can be set on a per task basis.
+ The timeout value controls the amount of time in seconds before the
+ task will fail if the command has not returned.
+
+ For local connection type:
+
+ .. FIXME: Detail error here
+
+ Suggestions to resolve:
+
+ Some modules support a ``timeout`` option, which is different to the ``timeout`` keyword for tasks.
+
+ .. code-block:: yaml
+
+ - name: save running-config
+ cisco.ios.ios_command:
+ commands: copy running-config startup-config
+ provider: "{{ cli }}"
+ timeout: 30
+
+
+ Suggestions to resolve:
+
+ If the module does not support the ``timeout`` option directly, most networking connection plugins can enable similar functionality with the ``ansible_command_timeout`` variable.
+
+ .. code-block:: yaml
+
+ - name: save running-config
+ cisco.ios.ios_command:
+ commands: copy running-config startup-config
+ vars:
+ ansible_command_timeout: 60
+
+Some operations take longer than the default 30 seconds to complete. One good
+example is saving the current running config on IOS devices to startup config.
+In this case, changing the timeout value from the default 30 seconds to 60
+seconds will prevent the task from failing before the command completes
+successfully.
+
+Persistent connection retry timeout
+-----------------------------------
+
+By default, ``ANSIBLE_PERSISTENT_CONNECT_RETRY_TIMEOUT`` is set to 15 (seconds). You may see the following error if this value is too low:
+
+.. code-block:: yaml
+
+ 2017-04-04 12:19:35,708 p=18591 u=fred | connect retry timeout expired, unable to connect to control socket
+ 2017-04-04 12:19:35,709 p=18591 u=fred | persistent_connect_retry_timeout is 15 secs
+
+Suggestions to resolve:
+
+Increase the value of the persistent connection idle timeout.
+Note: This value should be greater than the SSH timeout value (the timeout value under the defaults
+section in the configuration file) and less than the value of the persistent
+connection idle timeout (connect_timeout).
+
+.. code-block:: yaml
+
+ export ANSIBLE_PERSISTENT_CONNECT_RETRY_TIMEOUT=30
+
+To make this a permanent change, add the following to your ``ansible.cfg`` file:
+
+.. code-block:: ini
+
+ [persistent_connection]
+ connect_retry_timeout = 30
+
+
+Timeout issue due to platform specific login menu with ``network_cli`` connection type
+--------------------------------------------------------------------------------------
+
+In Ansible 2.9 and later, the network_cli connection plugin configuration options are added
+to handle the platform specific login menu. These options can be set as group/host or tasks
+variables.
+
+Example: Handle single login menu prompts with host variables
+
+.. code-block:: console
+
+ $cat host_vars/<hostname>.yaml
+ ---
+ ansible_terminal_initial_prompt:
+ - "Connect to a host"
+ ansible_terminal_initial_answer:
+ - "3"
+
+Example: Handle remote host multiple login menu prompts with host variables
+
+.. code-block:: console
+
+ $cat host_vars/<inventory-hostname>.yaml
+ ---
+ ansible_terminal_initial_prompt:
+ - "Press any key to enter main menu"
+ - "Connect to a host"
+ ansible_terminal_initial_answer:
+ - "\\r"
+ - "3"
+ ansible_terminal_initial_prompt_checkall: True
+
+To handle multiple login menu prompts:
+
+* The values of ``ansible_terminal_initial_prompt`` and ``ansible_terminal_initial_answer`` should be a list.
+* The prompt sequence should match the answer sequence.
+* The value of ``ansible_terminal_initial_prompt_checkall`` should be set to ``True``.
+
+.. note:: If all the prompts in sequence are not received from remote host at the time connection initialization it will result in a timeout.
+
+
+Playbook issues
+===============
+
+This section details issues are caused by issues with the Playbook itself.
+
+Error: "Unable to enter configuration mode"
+-------------------------------------------
+
+**Platforms:** Arista EOS and Cisco IOS
+
+This occurs when you attempt to run a task that requires privileged mode in a user mode shell.
+
+For example:
+
+.. code-block:: console
+
+ TASK [ios_system : configure name_servers] *****************************************************************************
+ task path:
+ fatal: [ios-csr1000v]: FAILED! => {
+ "changed": false,
+ "failed": true,
+ "msg": "unable to enter configuration mode",
+ }
+
+Suggestions to resolve:
+
+ Use ``connection: ansible.netcommon.network_cli`` and ``become: yes``
+
+
+Proxy Issues
+============
+
+ .. _network_delegate_to_vs_ProxyCommand:
+
+delegate_to vs ProxyCommand
+---------------------------
+
+In order to use a bastion or intermediate jump host to connect to network devices over ``cli``
+transport, network modules support the use of ``ProxyCommand``.
+
+To use ``ProxyCommand``, configure the proxy settings in the Ansible inventory
+file to specify the proxy host.
+
+.. code-block:: ini
+
+ [nxos]
+ nxos01
+ nxos02
+
+ [nxos:vars]
+ ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+With the configuration above, simply build and run the playbook as normal with
+no additional changes necessary. The network module will now connect to the
+network device by first connecting to the host specified in
+``ansible_ssh_common_args``, which is ``bastion01`` in the above example.
+
+You can also set the proxy target for all hosts by using environment variables.
+
+.. code-block:: sh
+
+ export ANSIBLE_SSH_ARGS='-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+Using bastion/jump host with netconf connection
+-----------------------------------------------
+
+Enabling jump host setting
+--------------------------
+
+
+Bastion/jump host with netconf connection can be enabled by:
+ - Setting Ansible variable ``ansible_netconf_ssh_config`` either to ``True`` or custom ssh config file path
+ - Setting environment variable ``ANSIBLE_NETCONF_SSH_CONFIG`` to ``True`` or custom ssh config file path
+ - Setting ``ssh_config = 1`` or ``ssh_config = <ssh-file-path>`` under ``netconf_connection`` section
+
+If the configuration variable is set to 1 the proxycommand and other ssh variables are read from
+default ssh config file (~/.ssh/config).
+
+If the configuration variable is set to file path the proxycommand and other ssh variables are read
+from the given custom ssh file path
+
+Example ssh config file (~/.ssh/config)
+---------------------------------------
+
+.. code-block:: ini
+
+ Host jumphost
+ HostName jumphost.domain.name.com
+ User jumphost-user
+ IdentityFile "/path/to/ssh-key.pem"
+ Port 22
+
+ # Note: Due to the way that Paramiko reads the SSH Config file,
+ # you need to specify the NETCONF port that the host uses.
+ # In other words, it does not automatically use ansible_port
+ # As a result you need either:
+
+ Host junos01
+ HostName junos01
+ ProxyCommand ssh -W %h:22 jumphost
+
+ # OR
+
+ Host junos01
+ HostName junos01
+ ProxyCommand ssh -W %h:830 jumphost
+
+ # Depending on the netconf port used.
+
+Example Ansible inventory file
+
+.. code-block:: ini
+
+ [junos]
+ junos01
+
+ [junos:vars]
+ ansible_connection=ansible.netcommon.netconf
+ ansible_network_os=junipernetworks.junos.junos
+ ansible_user=myuser
+ ansible_password=!vault...
+
+
+.. note:: Using ``ProxyCommand`` with passwords through variables
+
+ By design, SSH doesn't support providing passwords through environment variables.
+ This is done to prevent secrets from leaking out, for example in ``ps`` output.
+
+ We recommend using SSH Keys, and if needed an ssh-agent, rather than passwords, where ever possible.
+
+Miscellaneous Issues
+====================
+
+
+Intermittent failure while using ``ansible.netcommon.network_cli`` connection type
+------------------------------------------------------------------------------------
+
+If the command prompt received in response is not matched correctly within
+the ``ansible.netcommon.network_cli`` connection plugin the task might fail intermittently with truncated
+response or with the error message ``operation requires privilege escalation``.
+Starting in 2.7.1 a new buffer read timer is added to ensure prompts are matched properly
+and a complete response is send in output. The timer default value is 0.2 seconds and
+can be adjusted on a per task basis or can be set globally in seconds.
+
+Example Per task timer setting
+
+.. code-block:: yaml
+
+ - name: gather ios facts
+ cisco.ios.ios_facts:
+ gather_subset: all
+ register: result
+ vars:
+ ansible_buffer_read_timeout: 2
+
+
+To make this a global setting, add the following to your ``ansible.cfg`` file:
+
+.. code-block:: ini
+
+ [persistent_connection]
+ buffer_read_timeout = 2
+
+This timer delay per command executed on remote host can be disabled by setting the value to zero.
+
+
+Task failure due to mismatched error regex within command response using ``ansible.netcommon.network_cli`` connection type
+----------------------------------------------------------------------------------------------------------------------------
+
+In Ansible 2.9 and later, the ``ansible.netcommon.network_cli`` connection plugin configuration options are added
+to handle the stdout and stderr regex to identify if the command execution response consist
+of a normal response or an error response. These options can be set group/host variables or as
+tasks variables.
+
+Example: For mismatched error response
+
+.. code-block:: yaml
+
+ - name: fetch logs from remote host
+ cisco.ios.ios_command:
+ commands:
+ - show logging
+
+
+Playbook run output:
+
+.. code-block:: console
+
+ TASK [first fetch logs] ********************************************************
+ fatal: [ios01]: FAILED! => {
+ "changed": false,
+ "msg": "RF Name:\r\n\r\n <--nsip-->
+ \"IPSEC-3-REPLAY_ERROR: Test log\"\r\n*Aug 1 08:36:18.483: %SYS-7-USERLOG_DEBUG:
+ Message from tty578(user id: ansible): test\r\nan-ios-02#"}
+
+Suggestions to resolve:
+
+Modify the error regex for individual task.
+
+.. code-block:: yaml
+
+ - name: fetch logs from remote host
+ cisco.ios.ios_command:
+ commands:
+ - show logging
+ vars:
+ ansible_terminal_stderr_re:
+ - pattern: 'connection timed out'
+ flags: 're.I'
+
+The terminal plugin regex options ``ansible_terminal_stderr_re`` and ``ansible_terminal_stdout_re`` have
+``pattern`` and ``flags`` as keys. The value of the ``flags`` key should be a value that is accepted by
+the ``re.compile`` python method.
+
+
+Intermittent failure while using ``ansible.netcommon.network_cli`` connection type due to slower network or remote target host
+----------------------------------------------------------------------------------------------------------------------------------
+
+In Ansible 2.9 and later, the ``ansible.netcommon.network_cli`` connection plugin configuration option is added to control
+the number of attempts to connect to a remote host. The default number of attempts is three.
+After every retry attempt the delay between retries is increased by power of 2 in seconds until either the
+maximum attempts are exhausted or either the ``persistent_command_timeout`` or ``persistent_connect_timeout`` timers are triggered.
+
+To make this a global setting, add the following to your ``ansible.cfg`` file:
+
+.. code-block:: ini
+
+ [persistent_connection]
+ network_cli_retries = 5
diff --git a/docs/docsite/rst/network/user_guide/network_resource_modules.rst b/docs/docsite/rst/network/user_guide/network_resource_modules.rst
new file mode 100644
index 0000000..1d048f5
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/network_resource_modules.rst
@@ -0,0 +1,196 @@
+.. _resource_modules:
+
+************************
+Network Resource Modules
+************************
+
+Ansible network resource modules simplify and standardize how you manage different network devices. Network devices separate configuration into sections (such as interfaces and VLANs) that apply to a network service. Ansible network resource modules take advantage of this to allow you to configure subsections or *resources* within the network device configuration. Network resource modules provide a consistent experience across different network devices.
+
+
+.. contents::
+ :local:
+
+Network resource module states
+===============================
+
+You use the network resource modules by assigning a state to what you want the module to do. The resource modules support the following states:
+
+merged
+ Ansible merges the on-device configuration with the provided configuration in the task.
+
+replaced
+ Ansible replaces the on-device configuration subsection with the provided configuration subsection in the task.
+
+overridden
+ Ansible overrides the on-device configuration for the resource with the provided configuration in the task. Use caution with this state as you could remove your access to the device (for example, by overriding the management interface configuration).
+
+deleted
+ Ansible deletes the on-device configuration subsection and restores any default settings.
+
+gathered
+ Ansible displays the resource details gathered from the network device and accessed with the ``gathered`` key in the result.
+
+rendered
+ Ansible renders the provided configuration in the task in the device-native format (for example, Cisco IOS CLI). Ansible returns this rendered configuration in the ``rendered`` key in the result. Note this state does not communicate with the network device and can be used offline.
+
+parsed
+ Ansible parses the configuration from the ``running_config`` option into Ansible structured data in the ``parsed`` key in the result. Note this does not gather the configuration from the network device so this state can be used offline.
+
+Using network resource modules
+==============================
+
+This example configures the L3 interface resource on a Cisco IOS device, based on different state settings.
+
+ .. code-block:: yaml
+
+ - name: configure l3 interface
+ cisco.ios.ios_l3_interfaces:
+ config: "{{ config }}"
+ state: <state>
+
+The following table shows an example of how an initial resource configuration changes with this task for different states.
+
++-----------------------------------------+------------------------------------+-----------------------------------------+
+| Resource starting configuration | task-provided configuration (YAML) | Final resource configuration on device |
++=========================================+====================================+=========================================+
+| .. code-block:: text | .. code-block:: yaml | *merged* |
+| | | .. code-block:: text |
+| interface loopback100 | config: | |
+| ip address 10.10.1.100 255.255.255.0 | - ipv6: | interface loopback100 |
+| ipv6 address FC00:100/64 | - address: fc00::100/64 | ip address 10.10.1.100 255.255.255.0|
+| | - address: fc00::101/64 | ipv6 address FC00:100/64 |
+| | name: loopback100 | ipv6 address FC00:101/64 |
+| | +-----------------------------------------+
+| | | *replaced* |
+| | | .. code-block:: text |
+| | | |
+| | | interface loopback100 |
+| | | no ip address |
+| | | ipv6 address FC00:100/64 |
+| | | ipv6 address FC00:101/64 |
+| | +-----------------------------------------+
+| | | *overridden* |
+| | | Incorrect use case. This would remove |
+| | | all interfaces from the device |
+| | | (including the mgmt interface) except |
+| | | the configured loopback100 |
+| | +-----------------------------------------+
+| | | *deleted* |
+| | | .. code-block:: text |
+| | | |
+| | | interface loopback100 |
+| | | no ip address |
++-----------------------------------------+------------------------------------+-----------------------------------------+
+
+Network resource modules return the following details:
+
+* The *before* state - the existing resource configuration before the task was executed.
+* The *after* state - the new resource configuration that exists on the network device after the task was executed.
+* Commands - any commands configured on the device.
+
+.. code-block:: yaml
+
+ ok: [nxos101] =>
+ result:
+ after:
+ contact: IT Support
+ location: Room E, Building 6, Seattle, WA 98134
+ users:
+ - algorithm: md5
+ group: network-admin
+ localized_key: true
+ password: '0x73fd9a2cc8c53ed3dd4ed8f4ff157e69'
+ privacy_password: '0x73fd9a2cc8c53ed3dd4ed8f4ff157e69'
+ username: admin
+ before:
+ contact: IT Support
+ location: Room E, Building 5, Seattle HQ
+ users:
+ - algorithm: md5
+ group: network-admin
+ localized_key: true
+ password: '0x73fd9a2cc8c53ed3dd4ed8f4ff157e69'
+ privacy_password: '0x73fd9a2cc8c53ed3dd4ed8f4ff157e69'
+ username: admin
+ changed: true
+ commands:
+ - snmp-server location Room E, Building 6, Seattle, WA 98134
+ failed: false
+
+
+Example: Verifying the network device configuration has not changed
+====================================================================
+
+The following playbook uses the :ref:`arista.eos.eos_l3_interfaces <ansible_collections.arista.eos.eos_l3_interfaces_module>` module to gather a subset of the network device configuration (Layer 3 interfaces only) and verifies the information is accurate and has not changed. This playbook passes the results of :ref:`arista.eos.eos_facts <ansible_collections.arista.eos.eos_facts_module>` directly to the ``arista.eos.eos_l3_interfaces`` module.
+
+
+.. code-block:: yaml
+
+ - name: Example of facts being pushed right back to device.
+ hosts: arista
+ gather_facts: false
+ tasks:
+ - name: grab arista eos facts
+ arista.eos.eos_facts:
+ gather_subset: min
+ gather_network_resources: l3_interfaces
+
+ - name: Ensure that the IP address information is accurate.
+ arista.eos.eos_l3_interfaces:
+ config: "{{ ansible_network_resources['l3_interfaces'] }}"
+ register: result
+
+ - name: Ensure config did not change.
+ assert:
+ that: not result.changed
+
+Example: Acquiring and updating VLANs on a network device
+==========================================================
+
+This example shows how you can use resource modules to:
+
+#. Retrieve the current configuration on a network device.
+#. Save that configuration locally.
+#. Update that configuration and apply it to the network device.
+
+This example uses the ``cisco.ios.ios_vlans`` resource module to retrieve and update the VLANs on an IOS device.
+
+1. Retrieve the current IOS VLAN configuration:
+
+.. code-block:: yaml
+
+ - name: Gather VLAN information as structured data
+ cisco.ios.ios_facts:
+ gather_subset:
+ - '!all'
+ - '!min'
+ gather_network_resources:
+ - 'vlans'
+
+2. Store the VLAN configuration locally:
+
+.. code-block:: yaml
+
+ - name: Store VLAN facts to host_vars
+ copy:
+ content: "{{ ansible_network_resources | to_nice_yaml }}"
+ dest: "{{ playbook_dir }}/host_vars/{{ inventory_hostname }}"
+
+3. Modify the stored file to update the VLAN configuration locally.
+
+4. Merge the updated VLAN configuration with the existing configuration on the device:
+
+.. code-block:: yaml
+
+ - name: Make VLAN config changes by updating stored facts on the controller.
+ cisco.ios.ios_vlans:
+ config: "{{ vlans }}"
+ state: merged
+ tags: update_config
+
+.. seealso::
+
+ `Network Features in Ansible 2.9 <https://www.ansible.com/blog/network-features-coming-soon-in-ansible-engine-2.9>`_
+ A introductory blog post on network resource modules.
+ `Deep Dive into Network Resource Modules <https://www.ansible.com/deep-dive-into-ansible-network-resource-module>`_
+ A deeper dive presentation into network resource modules.
diff --git a/docs/docsite/rst/network/user_guide/network_working_with_command_output.rst b/docs/docsite/rst/network/user_guide/network_working_with_command_output.rst
new file mode 100644
index 0000000..6215df9
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/network_working_with_command_output.rst
@@ -0,0 +1,126 @@
+.. _networking_working_with_command_output:
+
+**********************************************************
+Working with command output and prompts in network modules
+**********************************************************
+
+.. contents::
+ :local:
+
+Conditionals in networking modules
+===================================
+
+Ansible allows you to use conditionals to control the flow of your playbooks. Ansible networking command modules use the following unique conditional statements.
+
+* ``eq`` - Equal
+* ``neq`` - Not equal
+* ``gt`` - Greater than
+* ``ge`` - Greater than or equal
+* ``lt`` - Less than
+* ``le`` - Less than or equal
+* ``contains`` - Object contains specified item
+
+
+Conditional statements evaluate the results from the commands that are
+executed remotely on the device. Once the task executes the command
+set, the ``wait_for`` argument can be used to evaluate the results before
+returning control to the Ansible playbook.
+
+For example:
+
+.. code-block:: yaml
+
+ ---
+ - name: wait for interface to be admin enabled
+ arista.eos.eos_command:
+ commands:
+ - show interface Ethernet4 | json
+ wait_for:
+ - "result[0].interfaces.Ethernet4.interfaceStatus eq connected"
+
+In the above example task, the command :code:`show interface Ethernet4 | json`
+is executed on the remote device and the results are evaluated. If
+the path
+:code:`(result[0].interfaces.Ethernet4.interfaceStatus)` is not equal to
+"connected", then the command is retried. This process continues
+until either the condition is satisfied or the number of retries has
+expired (by default, this is 10 retries at 1 second intervals).
+
+The commands module can also evaluate more than one set of command
+results in an interface. For instance:
+
+.. code-block:: yaml
+
+ ---
+ - name: wait for interfaces to be admin enabled
+ arista.eos.eos_command:
+ commands:
+ - show interface Ethernet4 | json
+ - show interface Ethernet5 | json
+ wait_for:
+ - "result[0].interfaces.Ethernet4.interfaceStatus eq connected"
+ - "result[1].interfaces.Ethernet5.interfaceStatus eq connected"
+
+In the above example, two commands are executed on the
+remote device, and the results are evaluated. By specifying the result
+index value (0 or 1), the correct result output is checked against the
+conditional.
+
+The ``wait_for`` argument must always start with result and then the
+command index in ``[]``, where ``0`` is the first command in the commands list,
+``1`` is the second command, ``2`` is the third and so on.
+
+
+Handling prompts in network modules
+===================================
+
+Network devices may require that you answer a prompt before performing a change on the device. Individual network modules such as :ref:`cisco.ios.ios_command <ansible_collections.cisco.ios.ios_command_module>` and :ref:`cisco.nxos.nxos_command <ansible_collections.cisco.nxos.nxos_command_module>` can handle this with a ``prompt`` parameter.
+
+.. note::
+
+ ``prompt`` is a Python regex. If you add special characters such as ``?`` in the ``prompt`` value, the prompt won't match and you will get a timeout. To avoid this, ensure that the ``prompt`` value is a Python regex that matches the actual device prompt. Any special characters must be handled correctly in the ``prompt`` regex.
+
+You can also use the :ref:`ansible.netcommon.cli_command <ansible_collections.ansible.netcommon.cli_command_module>` to handle multiple prompts.
+
+.. code-block:: yaml
+
+ ---
+ - 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'
+
+You must list the prompt and the answers in the same order (that is, prompt[0] is answered by answer[0]).
+
+In the above example, ``check_all: True`` ensures that the task gives the matching answer to each prompt. Without that setting, a task with multiple prompts would give the first answer to every prompt.
+
+In the following example, the second answer would be ignored and ``y`` would be the answer given to both prompts. That is, this task only works because both answers are identical. Also notice again that ``prompt`` must be a Python regex, which is why the ``?`` is escaped in the first prompt.
+
+.. code-block:: yaml
+
+ ---
+ - name: reboot ios device
+ ansible.netcommon.cli_command:
+ command: reload
+ prompt:
+ - Save\?
+ - confirm
+ answer:
+ - y
+ - y
+
+.. seealso::
+
+ `Rebooting network devices with Ansible <https://www.ansible.com/blog/rebooting-network-devices-with-ansible>`_
+ Examples using ``wait_for``, ``wait_for_connection``, and ``prompt`` for network devices.
+
+ `Deep dive on cli_command <https://www.ansible.com/blog/deep-dive-on-cli-command-for-network-automation>`_
+ Detailed overview of how to use the ``cli_command``.
diff --git a/docs/docsite/rst/network/user_guide/platform_ce.rst b/docs/docsite/rst/network/user_guide/platform_ce.rst
new file mode 100644
index 0000000..1949174
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_ce.rst
@@ -0,0 +1,213 @@
+.. _ce_platform_options:
+
+***************************************
+CloudEngine OS Platform Options
+***************************************
+
+CloudEngine CE OS is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection and supports multiple connections. This page offers details on how each connection works in Ansible and how to use it.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ========================================== =========================
+ .. CLI NETCONF
+
+
+ ==================== ========================================== =========================
+ Protocol SSH XML over SSH
+
+ Credentials uses SSH keys / SSH-agent if present uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password accepts ``-u myuser -k`` if using password
+
+ Indirect Access via a bastion (jump host) via a bastion (jump host)
+
+ Connection Settings ``ansible_connection:`` ``ansible_connection:``
+ ``ansible.netcommon.network_cli`` ``ansible.netcommon.netconf``
+
+ |enable_mode| not supported by ce OS not supported by ce OS
+
+ Returned Data Format Refer to individual module documentation Refer to individual module documentation
+ ==================== ========================================== =========================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.netconf`` or ``ansible_connection=ansible.netcommon.network_cli`` instead.
+
+Using CLI in Ansible
+====================
+
+Example CLI inventory ``[ce:vars]``
+--------------------------------------
+
+.. code-block:: yaml
+
+ [ce:vars]
+ ansible_connection=ansible.netcommon.network_cli
+ ansible_network_os=community.network.ce
+ ansible_user=myuser
+ ansible_password=!vault...
+ ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords via environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Retrieve CE OS version
+ community.network.ce_command:
+ commands: display version
+ when: ansible_network_os == 'community.network.ce'
+
+
+Using NETCONF in Ansible
+========================
+
+Enabling NETCONF
+----------------
+
+Before you can use NETCONF to connect to a switch, you must:
+
+- install the ``ncclient`` python package on your control node(s) with ``pip install ncclient``
+- enable NETCONF on the CloudEngine OS device(s)
+
+To enable NETCONF on a new switch using Ansible, use the ``community.network.ce_config`` module with the CLI connection. Set up your platform-level variables just like in the CLI example above, then run a playbook task like this:
+
+.. code-block:: yaml
+
+ - name: Enable NETCONF
+ connection: ansible.netcommon.network_cli
+ community.network.ce_config:
+ lines:
+ - snetconf server enable
+ when: ansible_network_os == 'community.network.ce'
+
+Once NETCONF is enabled, change your variables to use the NETCONF connection.
+
+Example NETCONF inventory ``[ce:vars]``
+------------------------------------------
+
+.. code-block:: yaml
+
+ [ce:vars]
+ ansible_connection=ansible.netcommon.netconf
+ ansible_network_os=community.network.ce
+ ansible_user=myuser
+ ansible_password=!vault |
+ ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+Example NETCONF task
+--------------------
+
+.. code-block:: yaml
+
+ - name: Create a vlan, id is 50(ce)
+ community.network.ce_vlan:
+ vlan_id: 50
+ name: WEB
+ when: ansible_network_os == 'community.network.ce'
+
+
+Notes
+========================
+
+Modules that work with ``ansible.netcommon.network_cli``
+---------------------------------------------------------
+
+.. code-block:: yaml
+
+ community.network.ce_acl_interface
+ community.network.ce_command
+ community.network.ce_config
+ community.network.ce_evpn_bgp
+ community.network.ce_evpn_bgp_rr
+ community.network.ce_evpn_global
+ community.network.ce_facts
+ community.network.ce_mlag_interface
+ community.network.ce_mtu
+ community.network.ce_netstream_aging
+ community.network.ce_netstream_export
+ community.network.ce_netstream_global
+ community.network.ce_netstream_template
+ community.network.ce_ntp_auth
+ community.network.ce_rollback
+ community.network.ce_snmp_contact
+ community.network.ce_snmp_location
+ community.network.ce_snmp_traps
+ community.network.ce_startup
+ community.network.ce_stp
+ community.network.ce_vxlan_arp
+ community.network.ce_vxlan_gateway
+ community.network.ce_vxlan_global
+
+
+Modules that work with ``ansible.netcommon.netconf``
+-----------------------------------------------------
+
+.. code-block:: yaml
+
+ community.network.ce_aaa_server
+ community.network.ce_aaa_server_host
+ community.network.ce_acl
+ community.network.ce_acl_advance
+ community.network.ce_bfd_global
+ community.network.ce_bfd_session
+ community.network.ce_bfd_view
+ community.network.ce_bgp
+ community.network.ce_bgp_af
+ community.network.ce_bgp_neighbor
+ community.network.ce_bgp_neighbor_af
+ community.network.ce_dldp
+ community.network.ce_dldp_interface
+ community.network.ce_eth_trunk
+ community.network.ce_evpn_bd_vni
+ community.network.ce_file_copy
+ community.network.ce_info_center_debug
+ community.network.ce_info_center_global
+ community.network.ce_info_center_log
+ community.network.ce_info_center_trap
+ community.network.ce_interface
+ community.network.ce_interface_ospf
+ community.network.ce_ip_interface
+ community.network.ce_lacp
+ community.network.ce_link_status
+ community.network.ce_lldp
+ community.network.ce_lldp_interface
+ community.network.ce_mlag_config
+ community.network.ce_netconf
+ community.network.ce_ntp
+ community.network.ce_ospf
+ community.network.ce_ospf_vrf
+ community.network.ce_reboot
+ community.network.ce_sflow
+ community.network.ce_snmp_community
+ community.network.ce_snmp_target_host
+ community.network.ce_snmp_user
+ community.network.ce_static_route
+ community.network.ce_static_route_bfd
+ community.network.ce_switchport
+ community.network.ce_vlan
+ community.network.ce_vrf
+ community.network.ce_vrf_af
+ community.network.ce_vrf_interface
+ community.network.ce_vrrp
+ community.network.ce_vxlan_tunnel
+ community.network.ce_vxlan_vap
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_cnos.rst b/docs/docsite/rst/network/user_guide/platform_cnos.rst
new file mode 100644
index 0000000..0044847
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_cnos.rst
@@ -0,0 +1,78 @@
+.. _cnos_platform_options:
+
+***************************************
+CNOS Platform Options
+***************************************
+
+CNOS is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection and supports Enable Mode (Privilege Escalation). This page offers details on how to use Enable Mode on CNOS in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| supported: use ``ansible_become: yes``
+ with ``ansible_become_method: enable``
+ and ``ansible_become_password:``
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.network_cli`` instead.
+
+Using CLI in Ansible
+================================================================================
+
+Example CLI ``group_vars/cnos.yml``
+--------------------------------------------------------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: community.network.cnos
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_become: yes
+ ansible_become_method: enable
+ ansible_become_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Retrieve CNOS OS version
+ community.network.cnos_command:
+ commands: show version
+ when: ansible_network_os == 'community.network.cnos'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_dellos10.rst b/docs/docsite/rst/network/user_guide/platform_dellos10.rst
new file mode 100644
index 0000000..cdffdd5
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_dellos10.rst
@@ -0,0 +1,80 @@
+.. _dellos10_platform_options:
+
+***************************************
+Dell OS10 Platform Options
+***************************************
+
+The `dellemc.os10 <https://galaxy.ansible.com/dellemc_networking/os10>`_ collection supports Enable Mode (Privilege Escalation). This page offers details on how to use Enable Mode on OS10 in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access through a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| supported: use ``ansible_become: yes``
+ with ``ansible_become_method: enable``
+ and ``ansible_become_password:``
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.network_cli`` instead.
+
+
+Using CLI in Ansible
+================================================================================
+
+Example CLI ``group_vars/dellos10.yml``
+---------------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: dellemc.os10.os10
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_become: yes
+ ansible_become_method: enable
+ ansible_become_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config (dellos10)
+ dellemc.os10.os10_config:
+ backup: yes
+ register: backup_dellos10_location
+ when: ansible_network_os == 'dellemc.os10.os10'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_dellos6.rst b/docs/docsite/rst/network/user_guide/platform_dellos6.rst
new file mode 100644
index 0000000..ae8083d
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_dellos6.rst
@@ -0,0 +1,79 @@
+.. _dellos6_platform_options:
+
+***************************************
+Dell OS6 Platform Options
+***************************************
+
+The `dellemc.os6 <https://github.com/ansible-collections/dellemc.os6>`_ collection supports Enable Mode (Privilege Escalation). This page offers details on how to use Enable Mode on OS6 in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access through a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| supported: use ``ansible_become: yes``
+ with ``ansible_become_method: enable``
+ and ``ansible_become_password:``
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.network_cli`` instead.
+
+Using CLI in Ansible
+================================================================================
+
+Example CLI ``group_vars/dellos6.yml``
+--------------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: dellemc.os6.os6
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_become: yes
+ ansible_become_method: enable
+ ansible_become_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config (dellos6)
+ dellemc.os6.os6_config:
+ backup: yes
+ register: backup_dellso6_location
+ when: ansible_network_os == 'dellemc.os6.os6'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_dellos9.rst b/docs/docsite/rst/network/user_guide/platform_dellos9.rst
new file mode 100644
index 0000000..ac1f52f
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_dellos9.rst
@@ -0,0 +1,79 @@
+.. _dellos9_platform_options:
+
+***************************************
+Dell OS9 Platform Options
+***************************************
+
+The `dellemc.os9 <https://github.com/ansible-collections/dellemc.os9>`_ collection supports Enable Mode (Privilege Escalation). This page offers details on how to use Enable Mode on OS9 in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access through a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| supported: use ``ansible_become: yes``
+ with ``ansible_become_method: enable``
+ and ``ansible_become_password:``
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.network_cli`` instead.
+
+Using CLI in Ansible
+================================================================================
+
+Example CLI ``group_vars/dellos9.yml``
+--------------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: dellemc.os9.os9
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_become: yes
+ ansible_become_method: enable
+ ansible_become_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config (dellos9)
+ dellemc.os9.os9_config:
+ backup: yes
+ register: backup_dellos9_location
+ when: ansible_network_os == 'dellemc.os9.os9'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_enos.rst b/docs/docsite/rst/network/user_guide/platform_enos.rst
new file mode 100644
index 0000000..3cf17c3
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_enos.rst
@@ -0,0 +1,80 @@
+.. _enos_platform_options:
+
+***************************************
+ENOS Platform Options
+***************************************
+
+ENOS is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection and supports Enable Mode (Privilege Escalation). This page offers details on how to use Enable Mode on ENOS in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| supported: use ``ansible_become: yes``
+ with ``ansible_become_method: enable``
+ and ``ansible_become_password:``
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
++---------------------------+-----------------------------------------------+
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.network_cli`` instead.
+
+Using CLI in Ansible
+================================================================================
+
+Example CLI ``group_vars/enos.yml``
+--------------------------------------------------------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: community.network.enos
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_become: yes
+ ansible_become_method: enable
+ ansible_become_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Retrieve ENOS OS version
+ community.network.enos_command:
+ commands: show version
+ when: ansible_network_os == 'community.network.enos'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_eos.rst b/docs/docsite/rst/network/user_guide/platform_eos.rst
new file mode 100644
index 0000000..588118e
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_eos.rst
@@ -0,0 +1,140 @@
+.. _eos_platform_options:
+
+***************************************
+EOS Platform Options
+***************************************
+
+The `Arista EOS <https://galaxy.ansible.com/arista/eos>`_ collection supports multiple connections. This page offers details on how each connection works in Ansible and how to use it.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ========================================== ===========================
+ .. CLI eAPI
+ ==================== ========================================== ===========================
+ Protocol SSH HTTP(S)
+
+ Credentials uses SSH keys / SSH-agent if present uses HTTPS certificates if
+ present
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host) through a web proxy
+
+ Connection Settings ``ansible_connection:`` ``ansible_connection:``
+ ``ansible.netcommon.network_cli`` ``ansible.netcommon.httpapi``
+
+
+ |enable_mode| supported: |br| supported: |br|
+
+ * use ``ansible_become: yes`` * ``httpapi``
+ with ``ansible_become_method: enable`` uses ``ansible_become: yes``
+ with ``ansible_become_method: enable``
+
+ Returned Data Format ``stdout[0].`` ``stdout[0].messages[0].``
+ ==================== ========================================== ===========================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.network_cli`` or ``ansible_connection: ansible.netcommon.httpapi`` instead.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/eos.yml``
+----------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: arista.eos.eos
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_become: yes
+ ansible_become_method: enable
+ ansible_become_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config (eos)
+ arista.eos.eos_config:
+ backup: yes
+ register: backup_eos_location
+ when: ansible_network_os == 'arista.eos.eos'
+
+
+
+Using eAPI in Ansible
+=====================
+
+Enabling eAPI
+-------------
+
+Before you can use eAPI to connect to a switch, you must enable eAPI. To enable eAPI on a new switch with Ansible, use the ``arista.eos.eos_eapi`` module through the CLI connection. Set up ``group_vars/eos.yml`` just like in the CLI example above, then run a playbook task like this:
+
+.. code-block:: yaml
+
+ - name: Enable eAPI
+ arista.eos.eos_eapi:
+ enable_http: yes
+ enable_https: yes
+ become: true
+ become_method: enable
+ when: ansible_network_os == 'arista.eos.eos'
+
+You can find more options for enabling HTTP/HTTPS connections in the :ref:`arista.eos.eos_eapi <ansible_collections.arista.eos.eos_eapi_module>` module documentation.
+
+Once eAPI is enabled, change your ``group_vars/eos.yml`` to use the eAPI connection.
+
+Example eAPI ``group_vars/eos.yml``
+-----------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.httpapi
+ ansible_network_os: arista.eos.eos
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_become: yes
+ ansible_become_method: enable
+ proxy_env:
+ http_proxy: http://proxy.example.com:8080
+
+- If you are accessing your host directly (not through a web proxy) you can remove the ``proxy_env`` configuration.
+- If you are accessing your host through a web proxy using ``https``, change ``http_proxy`` to ``https_proxy``.
+
+
+Example eAPI task
+-----------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config (eos)
+ arista.eos.eos_config:
+ backup: yes
+ register: backup_eos_location
+ environment: "{{ proxy_env }}"
+ when: ansible_network_os == 'arista.eos.eos'
+
+In this example the ``proxy_env`` variable defined in ``group_vars`` gets passed to the ``environment`` option of the module in the task.
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_eric_eccli.rst b/docs/docsite/rst/network/user_guide/platform_eric_eccli.rst
new file mode 100644
index 0000000..8e8bef0
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_eric_eccli.rst
@@ -0,0 +1,73 @@
+.. _eic_eccli_platform_options:
+
+***************************************
+ERIC_ECCLI Platform Options
+***************************************
+
+Extreme ERIC_ECCLI is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection and only supports CLI connections today. This page offers details on how to use ``ansible.netcommon.network_cli`` on ERIC_ECCLI in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| not supported by ERIC_ECCLI
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+ERIC_ECCLI does not support ``ansible_connection: local``. You must use ``ansible_connection: ansible.netcommon.network_cli``.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/eric_eccli.yml``
+-----------------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: community.network.eric_eccli
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: run show version on remote devices (eric_eccli)
+ community.network.eric_eccli_command:
+ commands: show version
+ when: ansible_network_os == 'community.network.eric_eccli'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_exos.rst b/docs/docsite/rst/network/user_guide/platform_exos.rst
new file mode 100644
index 0000000..2e74be5
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_exos.rst
@@ -0,0 +1,108 @@
+.. _exos_platform_options:
+
+***************************************
+EXOS Platform Options
+***************************************
+
+Extreme EXOS is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection and supports multiple connections. This page offers details on how each connection works in Ansible and how to use it.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+
+.. table::
+ :class: documentation-table
+
+ ==================== ========================================== =========================
+ .. CLI EXOS-API
+ ==================== ========================================== =========================
+ Protocol SSH HTTP(S)
+
+ Credentials uses SSH keys / SSH-agent if present uses HTTPS certificates if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host) through a web proxy
+
+ Connection Settings ``ansible_connection:`` ``ansible_connection:``
+ ``ansible.netcommon.network_cli`` ``ansible.netcommon.httpapi``
+
+ |enable_mode| not supported by EXOS not supported by EXOS
+
+ Returned Data Format ``stdout[0].`` ``stdout[0].messages[0].``
+ ==================== ========================================== =========================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+EXOS does not support ``ansible_connection: local``. You must use ``ansible_connection: ansible.netcommon.network_cli`` or ``ansible_connection: ansible.netcommon.httpapi``.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/exos.yml``
+-----------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: community.network.exos
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Retrieve EXOS OS version
+ community.network.exos_command:
+ commands: show version
+ when: ansible_network_os == 'community.network.exos'
+
+
+
+Using EXOS-API in Ansible
+=========================
+
+Example EXOS-API ``group_vars/exos.yml``
+----------------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.httpapi
+ ansible_network_os: community.network.exos
+ ansible_user: myuser
+ ansible_password: !vault...
+ proxy_env:
+ http_proxy: http://proxy.example.com:8080
+
+- If you are accessing your host directly (not through a web proxy) you can remove the ``proxy_env`` configuration.
+- If you are accessing your host through a web proxy using ``https``, change ``http_proxy`` to ``https_proxy``.
+
+
+Example EXOS-API task
+---------------------
+
+.. code-block:: yaml
+
+ - name: Retrieve EXOS OS version
+ community.network.exos_command:
+ commands: show version
+ when: ansible_network_os == 'community.network.exos'
+
+In this example the ``proxy_env`` variable defined in ``group_vars`` gets passed to the ``environment`` option of the module used in the task.
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_frr.rst b/docs/docsite/rst/network/user_guide/platform_frr.rst
new file mode 100644
index 0000000..0261250
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_frr.rst
@@ -0,0 +1,73 @@
+.. _frr_platform_options:
+
+***************************************
+FRR Platform Options
+***************************************
+
+The `FRR <https://galaxy.ansible.com/frr/frr>`_ collection supports the ``ansible.netcommon.network_cli`` connection. This section provides details on how to use this connection for Free Range Routing (FRR).
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| not supported
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/frr.yml``
+----------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: frr.frr.frr
+ ansible_user: frruser
+ ansible_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+- The ``ansible_user`` should be a part of the ``frrvty`` group and should have the default shell set to ``/bin/vtysh``.
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Gather FRR facts
+ frr.frr.frr_facts:
+ gather_subset:
+ - config
+ - hardware
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_icx.rst b/docs/docsite/rst/network/user_guide/platform_icx.rst
new file mode 100644
index 0000000..ee87b76
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_icx.rst
@@ -0,0 +1,77 @@
+.. _icx_platform_options:
+
+***************************************
+ICX Platform Options
+***************************************
+
+ICX is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection supports Enable Mode (Privilege Escalation). This page offers details on how to use Enable Mode on ICX in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| supported: use ``ansible_become: yes`` with
+ ``ansible_become_method: enable`` and ``ansible_become_password:``
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/icx.yml``
+----------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: community.network.icx
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_become: yes
+ ansible_become_method: enable
+ ansible_become_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config (icx)
+ community.network.icx_config:
+ backup: yes
+ register: backup_icx_location
+ when: ansible_network_os == 'community.network.icx'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_index.rst b/docs/docsite/rst/network/user_guide/platform_index.rst
new file mode 100644
index 0000000..f9a8bc5
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_index.rst
@@ -0,0 +1,124 @@
+.. _platform_options:
+
+****************
+Platform Options
+****************
+
+Some Ansible Network platforms support multiple connection types, privilege escalation (``enable`` mode), or other options. The pages in this section offer standardized guides to understanding available options on each network platform. We welcome contributions from community-maintained platforms to this section.
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Platform Options
+
+ platform_ce
+ platform_cnos
+ platform_dellos6
+ platform_dellos9
+ platform_dellos10
+ platform_enos
+ platform_eos
+ platform_eric_eccli
+ platform_exos
+ platform_frr
+ platform_icx
+ platform_ios
+ platform_iosxr
+ platform_ironware
+ platform_junos
+ platform_meraki
+ platform_netvisor
+ platform_nos
+ platform_nxos
+ platform_routeros
+ platform_slxos
+ platform_voss
+ platform_vyos
+ platform_weos4
+ platform_netconf_enabled
+
+.. _settings_by_platform:
+
+Settings by Platform
+================================
+
+.. raw:: html
+
+ <style>
+ /* Style for this single table. Add delimiters between header columns */
+ table#network-platform-table thead tr th.head {
+ border-left-width: 1px;
+ border-left-color: rgb(225, 228, 229);
+ border-left-style: solid;
+ }
+ </style>
+
+.. table::
+ :name: network-platform-table
+
+ =============================== ================================ =========== ======= ======= ===========
+ .. ``ansible_connection:`` settings available
+ ----------------------------------------------------------------- ------------------------------------------
+ Network OS ``ansible_network_os:`` network_cli netconf httpapi local
+ =============================== ================================ =========== ======= ======= ===========
+ `Arista EOS`_ `[†]`_ ``arista.eos.eos`` ✓ ✓ ✓
+ `Ciena SAOS6`_ ``ciena.saos6.saos6`` ✓ ✓
+ `Cisco ASA`_ `[†]`_ ``cisco.asa.asa`` ✓ ✓
+ `Cisco IOS`_ `[†]`_ ``cisco.ios.ios`` ✓ ✓
+ `Cisco IOS XR`_ `[†]`_ ``cisco.iosxr.iosxr`` ✓ ✓
+ `Cisco NX-OS`_ `[†]`_ ``cisco.nxos.nxos`` ✓ ✓ ✓
+ `Cloudengine OS`_ ``community.network.ce`` ✓ ✓ ✓
+ `Dell OS6`_ ``dellemc.os6.os6`` ✓ ✓
+ `Dell OS9`_ ``dellemc.os9.os9`` ✓ ✓
+ `Dell OS10`_ ``dellemc.os10.os10`` ✓ ✓
+ `Ericsson ECCLI`_ ``community.network.eric_eccli`` ✓ ✓
+ `Extreme EXOS`_ ``community.network.exos`` ✓ ✓
+ `Extreme IronWare`_ ``community.network.ironware`` ✓ ✓
+ `Extreme NOS`_ ``community.network.nos`` ✓
+ `Extreme SLX-OS`_ ``community.network.slxos`` ✓
+ `Extreme VOSS`_ ``community.network.voss`` ✓
+ `F5 BIG-IP`_ ✓
+ `F5 BIG-IQ`_ ✓
+ `Junos OS`_ `[†]`_ ``junipernetworks.junos.junos`` ✓ ✓ ✓
+ `Lenovo CNOS`_ ``community.network.cnos`` ✓ ✓
+ `Lenovo ENOS`_ ``community.network.enos`` ✓ ✓
+ `Meraki`_ ✓
+ `MikroTik RouterOS`_ ``community.network.routeros`` ✓
+ `Nokia SR OS`_ ✓
+ `Pluribus Netvisor`_ ``community.network.netvisor`` ✓
+ `Ruckus ICX`_ ``community.network.icx`` ✓
+ `VyOS`_ `[†]`_ ``vyos.vyos.vyos`` ✓ ✓
+ `Westermo WeOS 4`_ ``community.network.weos4`` ✓
+ OS that supports Netconf `[†]`_ ``<network-os>`` ✓ ✓
+ =============================== ================================ =========== ======= ======= ===========
+
+.. _Arista EOS: https://galaxy.ansible.com/arista/eos
+.. _Ciena SAOS6: https://galaxy.ansible.com/ciena/saos6
+.. _Cisco ASA: https://galaxy.ansible.com/cisco/asa
+.. _Cisco IOS: https://galaxy.ansible.com/cisco/ios
+.. _Cisco IOS XR: https://galaxy.ansible.com/cisco/iosxr
+.. _Cisco NX-OS: https://galaxy.ansible.com/cisco/nxos
+.. _Cloudengine OS: https://galaxy.ansible.com/community/network
+.. _Dell OS6: https://github.com/ansible-collections/dellemc.os6
+.. _Dell OS9: https://github.com/ansible-collections/dellemc.os9
+.. _Dell OS10: https://galaxy.ansible.com/dellemc/os10
+.. _Ericsson ECCLI: https://galaxy.ansible.com/community/network
+.. _Extreme EXOS: https://galaxy.ansible.com/community/network
+.. _Extreme IronWare: https://galaxy.ansible.com/community/network
+.. _Extreme NOS: https://galaxy.ansible.com/community/network
+.. _Extreme SLX-OS: https://galaxy.ansible.com/community/network
+.. _Extreme VOSS: https://galaxy.ansible.com/community/network
+.. _F5 BIG-IP: https://galaxy.ansible.com/f5networks/f5_modules
+.. _F5 BIG-IQ: https://galaxy.ansible.com/f5networks/f5_modules
+.. _Junos OS: https://galaxy.ansible.com/junipernetworks/junos
+.. _Lenovo CNOS: https://galaxy.ansible.com/community/network
+.. _Lenovo ENOS: https://galaxy.ansible.com/community/network
+.. _Meraki: https://galaxy.ansible.com/cisco/meraki
+.. _MikroTik RouterOS: https://galaxy.ansible.com/community/network
+.. _Nokia SR OS: https://galaxy.ansible.com/community/network
+.. _Pluribus Netvisor: https://galaxy.ansible.com/community/network
+.. _Ruckus ICX: https://galaxy.ansible.com/community/network
+.. _VyOS: https://galaxy.ansible.com/vyos/vyos
+.. _Westermo WeOS 4: https://galaxy.ansible.com/community/network
+.. _`[†]`:
+
+**[†]** Maintained by Ansible Network Team
diff --git a/docs/docsite/rst/network/user_guide/platform_ios.rst b/docs/docsite/rst/network/user_guide/platform_ios.rst
new file mode 100644
index 0000000..c7bd9ab
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_ios.rst
@@ -0,0 +1,79 @@
+.. _ios_platform_options:
+
+***************************************
+IOS Platform Options
+***************************************
+
+The `Cisco IOS <https://galaxy.ansible.com/cisco/ios>`_ collection supports Enable Mode (Privilege Escalation). This page offers details on how to use Enable Mode on IOS in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| supported: use ``ansible_become: yes`` with
+ ``ansible_become_method: enable`` and ``ansible_become_password:``
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.network_cli`` instead.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/ios.yml``
+----------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: cisco.ios.ios
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_become: yes
+ ansible_become_method: enable
+ ansible_become_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config (ios)
+ cisco.ios.ios_config:
+ backup: yes
+ register: backup_ios_location
+ when: ansible_network_os == 'cisco.ios.ios'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_iosxr.rst b/docs/docsite/rst/network/user_guide/platform_iosxr.rst
new file mode 100644
index 0000000..30e4995
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_iosxr.rst
@@ -0,0 +1,130 @@
+.. _iosxr_platform_options:
+
+***************************************
+IOS-XR Platform Options
+***************************************
+
+The `Cisco IOS-XR collection <https://galaxy.ansible.com/cisco/iosxr>`_ supports multiple connections. This page offers details on how each connection works in Ansible and how to use it.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ========================================== =========================
+ .. CLI NETCONF
+
+ only for modules ``iosxr_banner``,
+ ``iosxr_interface``, ``iosxr_logging``,
+ ``iosxr_system``, ``iosxr_user``
+ ==================== ========================================== =========================
+ Protocol SSH XML over SSH
+
+ Credentials uses SSH keys / SSH-agent if present uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host) by a bastion (jump host)
+
+ Connection Settings ``ansible_connection:`` ``ansible_connection:``
+ ``ansible.netcommon.network_cli`` ``ansible.netcommon.netconf``
+
+ |enable_mode| not supported not supported
+
+ Returned Data Format Refer to individual module documentation Refer to individual module documentation
+ ==================== ========================================== =========================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.network_cli`` or ``ansible_connection: ansible.netcommon.netconf`` instead.
+
+Using CLI in Ansible
+====================
+
+Example CLI inventory ``[iosxr:vars]``
+--------------------------------------
+
+.. code-block:: yaml
+
+ [iosxr:vars]
+ ansible_connection=ansible.netcommon.network_cli
+ ansible_network_os=cisco.iosxr.iosxr
+ ansible_user=myuser
+ ansible_password=!vault...
+ ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Retrieve IOS-XR version
+ cisco.iosxr.iosxr_command:
+ commands: show version
+ when: ansible_network_os == 'cisco.iosxr.iosxr'
+
+
+Using NETCONF in Ansible
+========================
+
+Enabling NETCONF
+----------------
+
+Before you can use NETCONF to connect to a switch, you must:
+
+- install the ``ncclient`` python package on your control node(s) with ``pip install ncclient``
+- enable NETCONF on the Cisco IOS-XR device(s)
+
+To enable NETCONF on a new switch via Ansible, use the ``cisco.iosxr.iosxr_netconf`` module through the CLI connection. Set up your platform-level variables just like in the CLI example above, then run a playbook task like this:
+
+.. code-block:: yaml
+
+ - name: Enable NETCONF
+ connection: ansible.netcommon.network_cli
+ cisco.iosxr.iosxr_netconf:
+ when: ansible_network_os == 'cisco.iosxr.iosxr'
+
+Once NETCONF is enabled, change your variables to use the NETCONF connection.
+
+Example NETCONF inventory ``[iosxr:vars]``
+------------------------------------------
+
+.. code-block:: yaml
+
+ [iosxr:vars]
+ ansible_connection=ansible.netcommon.netconf
+ ansible_network_os=cisco.iosxr.iosxr
+ ansible_user=myuser
+ ansible_password=!vault |
+ ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+Example NETCONF task
+--------------------
+
+.. code-block:: yaml
+
+ - name: Configure hostname and domain-name
+ cisco.iosxr.iosxr_system:
+ hostname: iosxr01
+ domain_name: test.example.com
+ domain_search:
+ - ansible.com
+ - redhat.com
+ - cisco.com
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_ironware.rst b/docs/docsite/rst/network/user_guide/platform_ironware.rst
new file mode 100644
index 0000000..dbb2c41
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_ironware.rst
@@ -0,0 +1,80 @@
+.. _ironware_platform_options:
+
+***************************************
+IronWare Platform Options
+***************************************
+
+IronWare is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection and supports Enable Mode (Privilege Escalation). This page offers details on how to use Enable Mode on IronWare in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| supported: use ``ansible_become: yes``
+ with ``ansible_become_method: enable``
+ and ``ansible_become_password:``
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.network_cli`` instead.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/mlx.yml``
+----------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: community.network.ironware
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_become: yes
+ ansible_become_method: enable
+ ansible_become_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config (ironware)
+ community.network.ironware_config:
+ backup: yes
+ register: backup_ironware_location
+ when: ansible_network_os == 'community.network.ironware'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_junos.rst b/docs/docsite/rst/network/user_guide/platform_junos.rst
new file mode 100644
index 0000000..08cf8fc
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_junos.rst
@@ -0,0 +1,129 @@
+.. _junos_platform_options:
+
+***************************************
+Junos OS Platform Options
+***************************************
+
+The `Juniper Junos OS <https://galaxy.ansible.com/junipernetworks/junos>`_ supports multiple connections. This page offers details on how each connection works in Ansible and how to use it.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ========================================== =========================
+ .. CLI NETCONF
+
+ ``junos_netconf`` & ``junos_command`` all modules except ``junos_netconf``,
+ modules only which enables NETCONF
+ ==================== ========================================== =========================
+ Protocol SSH XML over SSH
+
+ Credentials uses SSH keys / SSH-agent if present uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host) by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ``ansible_connection:
+ ``ansible.netcommon.network_cli`` ``ansible.netcommon.netconf``
+
+ |enable_mode| not supported by Junos OS not supported by Junos OS
+
+ Returned Data Format ``stdout[0].`` * json: ``result[0]['software-information'][0]['host-name'][0]['data'] foo lo0``
+ * text: ``result[1].interface-information[0].physical-interface[0].name[0].data foo lo0``
+ * xml: ``result[1].rpc-reply.interface-information[0].physical-interface[0].name[0].data foo lo0``
+ ==================== ========================================== =========================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.network_cli`` or ``ansible_connection: ansible.netcommon.netconf`` instead.
+
+Using CLI in Ansible
+====================
+
+Example CLI inventory ``[junos:vars]``
+--------------------------------------
+
+.. code-block:: yaml
+
+ [junos:vars]
+ ansible_connection=ansible.netcommon.network_cli
+ ansible_network_os=junipernetworks.junos.junos
+ ansible_user=myuser
+ ansible_password=!vault...
+ ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Retrieve Junos OS version
+ junipernetworks.junos.junos_command:
+ commands: show version
+ when: ansible_network_os == 'junipernetworks.junos.junos'
+
+
+Using NETCONF in Ansible
+========================
+
+Enabling NETCONF
+----------------
+
+Before you can use NETCONF to connect to a switch, you must:
+
+- install the ``ncclient`` python package on your control node(s) with ``pip install ncclient``
+- enable NETCONF on the Junos OS device(s)
+
+To enable NETCONF on a new switch through Ansible, use the ``junipernetworks.junos.junos_netconf`` module through the CLI connection. Set up your platform-level variables just like in the CLI example above, then run a playbook task like this:
+
+.. code-block:: yaml
+
+ - name: Enable NETCONF
+ connection: ansible.netcommon.network_cli
+ junipernetworks.junos.junos_netconf:
+ when: ansible_network_os == 'junipernetworks.junos.junos'
+
+Once NETCONF is enabled, change your variables to use the NETCONF connection.
+
+Example NETCONF inventory ``[junos:vars]``
+------------------------------------------
+
+.. code-block:: yaml
+
+ [junos:vars]
+ ansible_connection=ansible.netcommon.netconf
+ ansible_network_os=junipernetworks.junos.junos
+ ansible_user=myuser
+ ansible_password=!vault |
+ ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+Example NETCONF task
+--------------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config (junos)
+ junipernetworks.junos.junos_config:
+ backup: yes
+ register: backup_junos_location
+ when: ansible_network_os == 'junipernetworks.junos.junos'
+
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_meraki.rst b/docs/docsite/rst/network/user_guide/platform_meraki.rst
new file mode 100644
index 0000000..e51ca5b
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_meraki.rst
@@ -0,0 +1,44 @@
+.. _meraki_platform_options:
+
+***************************************
+Meraki Platform Options
+***************************************
+
+The `cisco.meraki <https://galaxy.ansible.com/cisco/meraki>`_ collection only supports the ``local`` connection type at this time.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. Dashboard API
+ ==================== ==========================================
+ Protocol HTTP(S)
+
+ Credentials uses API key from Dashboard
+
+ Connection Settings ``ansible_connection: localhost``
+
+ Returned Data Format ``data.``
+ ==================== ==========================================
+
+
+Example Meraki task
+-------------------
+
+.. code-block:: yaml
+
+ cisco.meraki.meraki_organization:
+ auth_key: abc12345
+ org_name: YourOrg
+ state: present
+ delegate_to: localhost
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst b/docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst
new file mode 100644
index 0000000..e481ed6
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst
@@ -0,0 +1,133 @@
+.. _netconf_enabled_platform_options:
+
+***************************************
+Netconf enabled Platform Options
+***************************************
+
+This page offers details on how the netconf connection works in Ansible and how to use it.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. NETCONF
+
+ all modules except ``junos_netconf``,
+ which enables NETCONF
+ ==================== ==========================================
+ Protocol XML over SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access through a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.netconf``
+ ==================== ==========================================
+
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.netconf`` instead.
+
+Using NETCONF in Ansible
+========================
+
+Enabling NETCONF
+----------------
+
+Before you can use NETCONF to connect to a switch, you must:
+
+- install the ``ncclient`` Python package on your control node(s) with ``pip install ncclient``
+- enable NETCONF on the Junos OS device(s)
+
+To enable NETCONF on a new switch through Ansible, use the platform specific module through the CLI connection or set it manually.
+For example set up your platform-level variables just like in the CLI example above, then run a playbook task like this:
+
+.. code-block:: yaml
+
+ - name: Enable NETCONF
+ connection: ansible.netcommon.network_cli
+ junipernetworks.junos.junos_netconf:
+ when: ansible_network_os == 'junipernetworks.junos.junos'
+
+Once NETCONF is enabled, change your variables to use the NETCONF connection.
+
+Example NETCONF inventory ``[junos:vars]``
+------------------------------------------
+
+.. code-block:: yaml
+
+ [junos:vars]
+ ansible_connection=ansible.netcommon.netconf
+ ansible_network_os=junipernetworks.junos.junos
+ ansible_user=myuser
+ ansible_password=!vault |
+
+
+Example NETCONF task
+--------------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config
+ junipernetworks.junos.netconf_config:
+ backup: yes
+ register: backup_junos_location
+
+Example NETCONF task with configurable variables
+------------------------------------------------
+
+.. code-block:: yaml
+
+ - name: configure interface while providing different private key file path
+ junipernetworks.junos.netconf_config:
+ backup: yes
+ register: backup_junos_location
+ vars:
+ ansible_private_key_file: /home/admin/.ssh/newprivatekeyfile
+
+Note: For netconf connection plugin configurable variables see :ref:`ansible.netcommon.netconf <ansible_collections.ansible.netcommon.netconf_connection>`.
+
+Bastion/Jumphost configuration
+------------------------------
+To use a jump host to connect to a NETCONF enabled device you must set the ``ANSIBLE_NETCONF_SSH_CONFIG`` environment variable.
+
+``ANSIBLE_NETCONF_SSH_CONFIG`` can be set to either:
+ - 1 or TRUE (to trigger the use of the default SSH config file ~/.ssh/config)
+ - The absolute path to a custom SSH config file.
+
+The SSH config file should look something like:
+
+.. code-block:: ini
+
+ Host *
+ proxycommand ssh -o StrictHostKeyChecking=no -W %h:%p jumphost-username@jumphost.fqdn.com
+ StrictHostKeyChecking no
+
+Authentication for the jump host must use key based authentication.
+
+You can either specify the private key used in the SSH config file:
+
+.. code-block:: ini
+
+ IdentityFile "/absolute/path/to/private-key.pem"
+
+Or you can use an ssh-agent.
+
+ansible_network_os auto-detection
+---------------------------------
+
+If ``ansible_network_os`` is not specified for a host, then Ansible will attempt to automatically detect what ``network_os`` plugin to use.
+
+``ansible_network_os`` auto-detection can also be triggered by using ``auto`` as the ``ansible_network_os``. (Note: Previously ``default`` was used instead of ``auto``).
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_netvisor.rst b/docs/docsite/rst/network/user_guide/platform_netvisor.rst
new file mode 100644
index 0000000..648e9c1
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_netvisor.rst
@@ -0,0 +1,78 @@
+.. _netvisor_platform_options:
+
+**********************************
+Pluribus NETVISOR Platform Options
+**********************************
+
+Pluribus NETVISOR Ansible is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection and only supports CLI connections today. ``httpapi`` modules may be added in future.
+This page offers details on how to use ``ansible.netcommon.network_cli`` on NETVISOR in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| not supported by NETVISOR
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+Pluribus NETVISOR does not support ``ansible_connection: local``. You must use ``ansible_connection: ansible.netcommon.network_cli``.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/netvisor.yml``
+---------------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: community.netcommon.netvisor
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Create access list
+ community.network.pn_access_list:
+ pn_name: "foo"
+ pn_scope: "local"
+ state: "present"
+ register: acc_list
+ when: ansible_network_os == 'community.network.netvisor'
+
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_nos.rst b/docs/docsite/rst/network/user_guide/platform_nos.rst
new file mode 100644
index 0000000..6bc244c
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_nos.rst
@@ -0,0 +1,76 @@
+.. _nos_platform_options:
+
+***************************************
+NOS Platform Options
+***************************************
+
+Extreme NOS is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection and only supports CLI connections today. ``httpapi`` modules may be added in future.
+This page offers details on how to use ``ansible.netcommon.network_cli`` on NOS in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: community.netcommon.network_cli``
+
+ |enable_mode| not supported by NOS
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+NOS does not support ``ansible_connection: local``. You must use ``ansible_connection: ansible.netcommon.network_cli``.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/nos.yml``
+----------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: community.network.nos
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Get version information (nos)
+ community.network.nos_command:
+ commands: "show version"
+ register: show_ver
+ when: ansible_network_os == 'community.network.nos'
+
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_nxos.rst b/docs/docsite/rst/network/user_guide/platform_nxos.rst
new file mode 100644
index 0000000..3794cfc
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_nxos.rst
@@ -0,0 +1,166 @@
+.. _nxos_platform_options:
+
+***************************************
+NXOS Platform Options
+***************************************
+
+The `Cisco NXOS <https://galaxy.ansible.com/cisco/nxos>`_ supports multiple connections. This page offers details on how each connection works in Ansible and how to use it.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ========================================== =========================
+ .. CLI NX-API
+ ==================== ========================================== =========================
+ Protocol SSH HTTP(S)
+
+ Credentials uses SSH keys / SSH-agent if present uses HTTPS certificates if
+ present
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host) by a web proxy
+
+ Connection Settings ``ansible_connection:`` ``ansible_connection:``
+ ``ansible.netcommon.network_cli`` ``ansible.netcommon.httpapi``
+
+ |enable_mode| supported: use ``ansible_become: yes`` not supported by NX-API
+ with ``ansible_become_method: enable``
+ and ``ansible_become_password:``
+
+ Returned Data Format ``stdout[0].`` ``stdout[0].messages[0].``
+ ==================== ========================================== =========================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation) |br| supported as of 2.5.3
+
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.network_cli`` or ``ansible_connection: ansible.netcommon.httpapi`` instead.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/nxos.yml``
+-----------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: cisco.nxos.nxos
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_become: yes
+ ansible_become_method: enable
+ ansible_become_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config (nxos)
+ cisco.nxos.nxos_config:
+ backup: yes
+ register: backup_nxos_location
+ when: ansible_network_os == 'cisco.nxos.nxos'
+
+
+
+Using NX-API in Ansible
+=======================
+
+Enabling NX-API
+---------------
+
+Before you can use NX-API to connect to a switch, you must enable NX-API. To enable NX-API on a new switch through Ansible, use the ``nxos_nxapi`` module through the CLI connection. Set up group_vars/nxos.yml just like in the CLI example above, then run a playbook task like this:
+
+.. code-block:: yaml
+
+ - name: Enable NX-API
+ cisco.nxos.nxos_nxapi:
+ enable_http: yes
+ enable_https: yes
+ when: ansible_network_os == 'cisco.nxos.nxos'
+
+To find out more about the options for enabling HTTP/HTTPS and local http see the :ref:`nxos_nxapi <nxos_nxapi_module>` module documentation.
+
+Once NX-API is enabled, change your ``group_vars/nxos.yml`` to use the NX-API connection.
+
+Example NX-API ``group_vars/nxos.yml``
+--------------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.httpapi
+ ansible_network_os: cisco.nxos.nxos
+ ansible_user: myuser
+ ansible_password: !vault...
+ proxy_env:
+ http_proxy: http://proxy.example.com:8080
+
+- If you are accessing your host directly (not through a web proxy) you can remove the ``proxy_env`` configuration.
+- If you are accessing your host through a web proxy using ``https``, change ``http_proxy`` to ``https_proxy``.
+
+
+Example NX-API task
+-------------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config (nxos)
+ cisco.nxos.nxos_config:
+ backup: yes
+ register: backup_nxos_location
+ environment: "{{ proxy_env }}"
+ when: ansible_network_os == 'cisco.nxos.nxos'
+
+In this example the ``proxy_env`` variable defined in ``group_vars`` gets passed to the ``environment`` option of the module used in the task.
+
+.. include:: shared_snippets/SSH_warning.txt
+
+Cisco Nexus platform support matrix
+===================================
+
+The following platforms and software versions have been certified by Cisco to work with this version of Ansible.
+
+.. table:: Platform / Software Minimum Requirements
+ :align: center
+
+ =================== =====================
+ Supported Platforms Minimum NX-OS Version
+ =================== =====================
+ Cisco Nexus N3k 7.0(3)I2(5) and later
+ Cisco Nexus N9k 7.0(3)I2(5) and later
+ Cisco Nexus N5k 7.3(0)N1(1) and later
+ Cisco Nexus N6k 7.3(0)N1(1) and later
+ Cisco Nexus N7k 7.3(0)D1(1) and later
+ Cisco Nexus MDS 8.4(1) and later (Please see individual module documentation for compatibility)
+ =================== =====================
+
+.. table:: Platform Models
+ :align: center
+
+ ======== ==============================================
+ Platform Description
+ ======== ==============================================
+ N3k Support includes N30xx, N31xx and N35xx models
+ N5k Support includes all N5xxx models
+ N6k Support includes all N6xxx models
+ N7k Support includes all N7xxx models
+ N9k Support includes all N9xxx models
+ MDS Support includes all MDS 9xxx models
+ ======== ==============================================
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_routeros.rst b/docs/docsite/rst/network/user_guide/platform_routeros.rst
new file mode 100644
index 0000000..ff404e6
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_routeros.rst
@@ -0,0 +1,80 @@
+.. _routeros_platform_options:
+
+***************************************
+RouterOS Platform Options
+***************************************
+
+RouterOS is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection and only supports CLI connections today. ``httpapi`` modules may be added in future.
+This page offers details on how to use ``ansible.netcommon.network_cli`` on RouterOS in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.network.network_cli``
+
+ |enable_mode| not supported by RouterOS
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+
+RouterOS does not support ``ansible_connection: local``. You must use ``ansible_connection: ansible.netcommon.network_cli``.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/routeros.yml``
+---------------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: community.network.routeros
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_become: yes
+ ansible_become_method: enable
+ ansible_become_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+- If you are getting timeout errors you may want to add ``+cet1024w`` suffix to your username which will disable console colors, enable "dumb" mode, tell RouterOS not to try detecting terminal capabilities and set terminal width to 1024 columns. See article `Console login process <https://wiki.mikrotik.com/wiki/Manual:Console_login_process>`_ in MikroTik wiki for more information.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Display resource statistics (routeros)
+ community.network.routeros_command:
+ commands: /system resource print
+ register: routeros_resources
+ when: ansible_network_os == 'community.network.routeros'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_slxos.rst b/docs/docsite/rst/network/user_guide/platform_slxos.rst
new file mode 100644
index 0000000..4c41451
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_slxos.rst
@@ -0,0 +1,77 @@
+.. _slxos_platform_options:
+
+***************************************
+SLX-OS Platform Options
+***************************************
+
+Extreme SLX-OS is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection and only supports CLI connections today. ``httpapi`` modules may be added in future.
+This page offers details on how to use ``ansible.netcommon.network_cli`` on SLX-OS in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| not supported by SLX-OS
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+
+SLX-OS does not support ``ansible_connection: local``. You must use ``ansible_connection: ansible.netcommon.network_cli``.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/slxos.yml``
+------------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: community.network.slxos
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Backup current switch config (slxos)
+ community.network.slxos_config:
+ backup: yes
+ register: backup_slxos_location
+ when: ansible_network_os == 'community.network.slxos'
+
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_voss.rst b/docs/docsite/rst/network/user_guide/platform_voss.rst
new file mode 100644
index 0000000..172a053
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_voss.rst
@@ -0,0 +1,78 @@
+.. _voss_platform_options:
+
+***************************************
+VOSS Platform Options
+***************************************
+
+Extreme VOSS is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection and only supports CLI connections today. This page offers details on how to
+use ``ansible.netcommon.network_cli`` on VOSS in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| supported: use ``ansible_become: yes``
+ with ``ansible_become_method: enable``
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+
+VOSS does not support ``ansible_connection: local``. You must use ``ansible_connection: ansible.netcommon.network_cli``.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/voss.yml``
+-----------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: community.network.voss
+ ansible_user: myuser
+ ansible_become: yes
+ ansible_become_method: enable
+ ansible_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Retrieve VOSS info
+ community.network.voss_command:
+ commands: show sys-info
+ when: ansible_network_os == 'community.network.voss'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_vyos.rst b/docs/docsite/rst/network/user_guide/platform_vyos.rst
new file mode 100644
index 0000000..f101fe7
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_vyos.rst
@@ -0,0 +1,74 @@
+.. _vyos_platform_options:
+
+***************************************
+VyOS Platform Options
+***************************************
+
+The `VyOS <https://galaxy.ansible.com/vyos/vyos>`_ collection supports the ``ansible.netcommon.network_cli`` connection type. This page offers details on connection options to manage VyOS using Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: ansible.netcommon.network_cli``
+
+ |enable_mode| not supported
+
+ Returned Data Format Refer to individual module documentation
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+
+The ``ansible_connection: local`` has been deprecated. Please use ``ansible_connection: ansible.netcommon.network_cli`` instead.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/vyos.yml``
+-----------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: vyos.vyos.vyos
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Retrieve VyOS version info
+ vyos.vyos.vyos_command:
+ commands: show version
+ when: ansible_network_os == 'vyos.vyos.vyos'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/platform_weos4.rst b/docs/docsite/rst/network/user_guide/platform_weos4.rst
new file mode 100644
index 0000000..dd5dc83
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/platform_weos4.rst
@@ -0,0 +1,88 @@
+.. _weos4_platform_options:
+
+***************************************
+WeOS 4 Platform Options
+***************************************
+
+Westermo WeOS 4 is part of the `community.network <https://galaxy.ansible.com/community/network>`_ collection and only supports CLI connections.
+This page offers details on how to use ``ansible.netcommon.network_cli`` on WeOS 4 in Ansible.
+
+.. contents::
+ :local:
+
+Connections available
+================================================================================
+
+.. table::
+ :class: documentation-table
+
+ ==================== ==========================================
+ .. CLI
+ ==================== ==========================================
+ Protocol SSH
+
+ Credentials uses SSH keys / SSH-agent if present
+
+ accepts ``-u myuser -k`` if using password
+
+ Indirect Access by a bastion (jump host)
+
+ Connection Settings ``ansible_connection: community.netcommon.network_cli``
+
+ |enable_mode| not supported by WeOS 4
+
+ Returned Data Format ``stdout[0].``
+ ==================== ==========================================
+
+.. |enable_mode| replace:: Enable Mode |br| (Privilege Escalation)
+
+WeOS 4 does not support ``ansible_connection: local``. You must use ``ansible_connection: ansible.netcommon.network_cli``.
+
+Using CLI in Ansible
+====================
+
+Example CLI ``group_vars/weos4.yml``
+------------------------------------
+
+.. code-block:: yaml
+
+ ansible_connection: ansible.netcommon.network_cli
+ ansible_network_os: community.network.weos4
+ ansible_user: myuser
+ ansible_password: !vault...
+ ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"'
+
+
+- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_password`` configuration.
+- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration.
+- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords through environment variables.
+
+Example CLI task
+----------------
+
+.. code-block:: yaml
+
+ - name: Get version information (WeOS 4)
+ ansible.netcommon.cli_command:
+ commands: "show version"
+ register: show_ver
+ when: ansible_network_os == 'community.network.weos4'
+
+Example Configuration task
+--------------------------
+
+.. code-block:: yaml
+
+ - name: Replace configuration with file on ansible host (WeOS 4)
+ ansible.netcommon.cli_config:
+ config: "{{ lookup('file', 'westermo.conf') }}"
+ replace: "yes"
+ diff_match: exact
+ diff_replace: config
+ when: ansible_network_os == 'community.network.weos4'
+
+.. include:: shared_snippets/SSH_warning.txt
+
+.. seealso::
+
+ :ref:`timeout_options`
diff --git a/docs/docsite/rst/network/user_guide/shared_snippets/SSH_warning.txt b/docs/docsite/rst/network/user_guide/shared_snippets/SSH_warning.txt
new file mode 100644
index 0000000..27424f5
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/shared_snippets/SSH_warning.txt
@@ -0,0 +1,2 @@
+.. warning::
+ Never store passwords in plain text. We recommend using SSH keys to authenticate SSH connections. Ansible supports ssh-agent to manage your SSH keys. If you must use passwords to authenticate SSH connections, we recommend encrypting them with :ref:`Ansible Vault <playbooks_vault>`.
diff --git a/docs/docsite/rst/network/user_guide/validate.rst b/docs/docsite/rst/network/user_guide/validate.rst
new file mode 100644
index 0000000..aeda1b2
--- /dev/null
+++ b/docs/docsite/rst/network/user_guide/validate.rst
@@ -0,0 +1,164 @@
+.. _validate_data:
+
+*************************************************
+Validate data against set criteria with Ansible
+*************************************************
+
+The :ref:`validate <ansible_collections.ansible.utils.validate_module>` module validates data against your predefined criteria using a validation engine. You can pull this data from a device or file, validate it against your defined criteria, and use the results to identify configuration or operational state drift and optionally take remedial action.
+
+
+.. contents::
+ :local:
+
+Understanding the validate plugin
+==================================
+
+The `ansible.utils <https://galaxy.ansible.com/ansible/utils>`_ collection includes the :ref:`validate <ansible_collections.ansible.utils.validate_module>` module.
+
+To validate data:
+
+#. Pull in structured data or convert your data to structured format with the :ref:`cli_parse <ansible_collections.ansible.utils.cli_parse_module>` module.
+#. Define the criteria to test that data against.
+#. Select a validation engine and test the data to see if it is valid based on the selected criteria and validation engine.
+
+The structure of the data and the criteria depends on the validation engine you select. The examples here use the ``jsonschema`` validation engine provided in the `ansible.utils <https://galaxy.ansible.com/ansible/utils>`_ collection.Red Hat Ansible Automation Platform subscription supports limited use if jsonschema public APIs as documented.
+
+Structuring the data
+=====================
+
+You can pull previously structured data from a file, or use the :ref:`cli_parse <ansible_collections.ansible.utils.cli_parse_module>` module to structure your data.
+
+The following example fetches the operational state of some network (Cisco NXOS) interfaces and translates that state to structured data using the ``ansible.netcommon.pyats`` parser.
+
+.. code-block:: yaml
+
+ ---
+ - hosts: nxos
+ connection: ansible.netcommon.network_cli
+ gather_facts: false
+ vars:
+ ansible_network_os: cisco.nxos.nxos
+ ansible_user: "changeme"
+ ansible_password: "changeme"
+
+ tasks:
+ - name: "Fetch interface state and parse with pyats"
+ ansible.utils.cli_parse:
+ command: show interface
+ parser:
+ name: ansible.netcommon.pyats
+ register: nxos_pyats_show_interface
+
+ - name: print structured interface state data
+ ansible.builtin.debug:
+ msg: "{{ nxos_pyats_show_interface['parsed'] }}"
+ ----
+
+This results in the following structured data.
+
+.. code-block:: text
+
+ ok: [nxos] => {
+ "changed": false,
+ "parsed": {
+ "Ethernet2/1": {
+ "admin_state": "down",
+ "auto_mdix": "off",
+ "auto_negotiate": false,
+ "bandwidth": 1000000,
+ "beacon": "off"
+ <--output omitted-->
+ },
+ "Ethernet2/10": {
+ "admin_state": "down",
+ "auto_mdix": "off",
+ "auto_negotiate": false,
+ "bandwidth": 1000000,
+ "beacon": "off",
+ <--output omitted-->
+ }
+ }
+ }
+
+See :ref:`cli_parsing` for details on how to parse semi-structured data into structured data.
+
+Defining the criteria to validate against
+=========================================
+
+This example uses the `jsonschema <https://pypi.org/project/jsonschema/>`_ validation engine to parse the JSON structured data we created in the prior section. the criteria defines the state we want the data to conform to. In this instance, we can validate against a desired admin state of ``up`` for all the interfaces.
+
+The criteria for ``jsonschema`` in this example is as follows:
+
+.. code-block:: text
+
+ $cat criteria/nxos_show_interface_admin_criteria.json
+ {
+ "type" : "object",
+ "patternProperties": {
+ "^.*": {
+ "type": "object",
+ "properties": {
+ "admin_state": {
+ "type": "string",
+ "pattern": "up"
+ }
+ }
+ }
+ }
+ }
+
+Validating the data
+====================
+
+Now that we have the structured data and the criteria, we can validate this data with the :ref:`validate <ansible_collections.ansible.utils.validate_module>` module.
+
+The following tasks check if the current state of the interfaces match the desired state defined in the criteria file.
+
+.. code-block:: yaml
+
+ - name: Validate interface admin state
+ ansible.utils.validate:
+ data: "{{ nxos_pyats_show_interface['parsed'] }}"
+ criteria:
+ - "{{ lookup('file', './criteria/nxos_show_interface_admin_criteria.json') | from_json }}"
+ engine: ansible.utils.jsonschema
+ ignore_errors: true
+ register: result
+
+ - name: Print the interface names that do not satisfy the desired state
+ ansible.builtin.debug:
+ msg: "{{ item['data_path'].split('.')[0] }}"
+ loop: "{{ result['errors'] }}"
+ when: "'errors' in result"
+
+
+In these tasks, we have:
+
+#. Set ``data`` to the structured JSON data from the :ref:`cli_parse <ansible_collections.ansible.utils.cli_parse_module>` module.
+#. Set ``criteria`` to the JSON criteria file we defined.
+#. Set the validate engine to ``jsonschema``.
+
+.. note::
+
+ The value of the criteria option can be a list and should be in a format that is defined by the validation engine used. You need to install the `jsonschema <https://pypi.org/project/jsonschema/>`_ on the control node for this example.
+
+The tasks output a list of errors indicating interfaces that do not have admin value in ``up`` state.
+
+.. code-block:: text
+
+ TASK [Validate interface for admin state] ***********************************************************************************************************
+ fatal: [nxos02]: FAILED! => {"changed": false, "errors": [{"data_path": "Ethernet2/1.admin_state", "expected": "up", "found": "down", "json_path": "$.Ethernet2/1.admin_state", "message": "'down' does not match 'up'", "relative_schema": {"pattern": "up", "type": "string"}, "schema_path": "patternProperties.^.*.properties.admin_state.pattern", "validator": "pattern"}, {"data_path": "Ethernet2/10.admin_state", "expected": "up", "found": "down", "json_path": "$.Ethernet2/10.admin_state", "message": "'down' does not match 'up'", "relative_schema": {"pattern": "up", "type": "string"}, "schema_path": "patternProperties.^.*.properties.admin_state.pattern", "validator": "pattern"}], "msg": "Validation errors were found.\nAt 'patternProperties.^.*.properties.admin_state.pattern' 'down' does not match 'up'. \nAt 'patternProperties.^.*.properties.admin_state.pattern' 'down' does not match 'up'. \nAt 'patternProperties.^.*.properties.admin_state.pattern' 'down' does not match 'up'. "}
+ ...ignoring
+
+
+ TASK [Print the interface names that do not satisfy the desired state] ****************************************************************************
+ Monday 14 December 2020 11:05:38 +0530 (0:00:01.661) 0:00:28.676 *******
+ ok: [nxos] => {
+ "msg": "Ethernet2/1"
+ }
+ ok: [nxos] => {
+ "msg": "Ethernet2/10"
+ }
+
+
+This shows Ethernet2/1 and Ethernet2/10 are not in the desired state based on the defined criteria. You can create a report or take further action to remediate this to bring the interfaces to the desired state based on the defined criteria.