diff --git a/docs/aetest/debugging.rst b/docs/aetest/debugging.rst index 0224720..93997a5 100644 --- a/docs/aetest/debugging.rst +++ b/docs/aetest/debugging.rst @@ -227,8 +227,9 @@ want to pause the testscript execution somewhere & check the current state and/or configuration of your environment, logs, and testbed devices? The **pause on phrase** feature allows you to pause on **any** log messages -generated by the current script run, without requiring any modifications to the -scripts and/or its libraries. When enabled, it actively filters all log messages +generated by the current script run, including CLI output from devices, +without requiring any modifications to the scripts and/or its libraries. +When enabled, it actively filters all log messages propagated to the ``logging.root`` logger, and pauses when a match is found. Three distinct types of pause actions are supported: @@ -486,3 +487,46 @@ Below are some examples of the pause on phrase feature in action: # -> /path/to/my/example/testscript.py[20] test() # (press Ctrl-D to resume execution) # >>> + +The pause will also dump the connection information, including which devices are currently connected. + +.. code-block:: python + + # -------------------------------------------------------------------------------- + # Pause On Phrase: Connection Information + # + # +-------------------+--------------------------------+ + # | Device Property | Value | + # +-------------------+--------------------------------+ + # | Name | device.name | + # | Alias | device.alias | + # | Active Connection | alias of active connection | + # | Status | Connected|Disconnected | + # | Spawn Command | command for active connection | + # | -------- | -------- | + # | Connection Alias | connection alias e.g. cli | + # | Class | Unicon, Gnmi, Netconf, etc | + # | IP | IPV4|IPV6 address | + # | Protocol | ssh, telnet, etc | + # | -------- | -------- | + # | URL | ://: | + # +-------------------+--------------------------------+ + + +.. note:: + + If it is required to connect to the device directly while the test is paused, the device connection must be disconnected + from before it can be accessed directly. + +.. code-block:: python + + >>> import pyats.easypy as ep + >>> dev = ep.runtime.testbed.devices[''] + >>> dev.disconnect() + + # the device can now be connected to in a separate terminal. Once ready to resume the test, + # break the connection and reattach with + + >>> dev.connect() + + diff --git a/docs/aetest/parameters.rst b/docs/aetest/parameters.rst index 96a52b8..80536fb 100644 --- a/docs/aetest/parameters.rst +++ b/docs/aetest/parameters.rst @@ -18,16 +18,16 @@ Test Parameters ``aetest`` is a data-driven test infrastructure. Its scripts and test cases are intended to be driven dynamically by: -- Data in the form of input arguments to the test script +- Data in the form of input arguments to the TestScript - Dynamic data generated during runtime The collection of dynamic data that artificially affects the behavior of -test scripts and test cases in ``aetest`` is called **parameters**. It adheres to +TestScripts and Testcases in ``aetest`` is called **parameters**. It adheres to a pre-defined set of parent/child propagation relationships and may be used as `Function Arguments`_ to each test section. -This feature is a supplement to static test case data (attribute values stored -within each test case). +This feature is a supplement to static Testcase data (attribute values stored +within each Testcase). .. tip:: @@ -74,8 +74,8 @@ methods as the "doer," then parameters are the "what to do with." E.g., an add_to_c(1, 2) # 103 -In data-driven testing, test scripts are the *doers*, performing the act -of testing a facet of some product. Test script arguments and parameters are thus the +In data-driven testing, TestScripts are the *doers*, performing the act +of testing a facet of some product. TestScript arguments and parameters are thus the input data that influences the specific actions of testing. Here are some possible use cases: @@ -86,13 +86,13 @@ are some possible use cases: - The ``vlan`` argument to the ``layer2_traffic`` script can dynamically control the VLAN to be configured for traffic testing. - - Other toggle arguments that dynamically turn on/off certain test cases, + - Other toggle arguments that dynamically turn on/off certain Testcases, and a combination of features to be configured & tested - Etc. Of course, the parameters feature in ``aetest`` is much more than just script -arguments. It enables users to write test cases and test scripts that are capable +arguments. It enables users to write Testcases and TestScripts that are capable of being driven by inputs, varying the degree of testing, etc. Relationship Model @@ -162,7 +162,7 @@ execution, this happens behind the scenes automatically. new_testcase_parameters.update(testcase.parameters) testcase.parameters = new_testcase_parameters - # so that the new parameters seen in the test case + # so that the new parameters seen in the Testcase # level, is: testcase.parameters # {'param_A': 100, 'param_B': 2, 'param_C': 3} @@ -203,7 +203,7 @@ within the test script. # note that this also applies to CommonSetup & CommonCleanup class Testcase(aetest.Testcase): - # all default parameters specific to this test case are declared + # all default parameters specific to this Testcase are declared # in its own parameters dictionary. parameters = { 'generic_param_A': 200 @@ -247,7 +247,7 @@ dynamically access & update parameters. # # continuing from the above - # re-defining the test case for the sake of code-continuity + # re-defining the Testcase for the sake of code-continuity class Testcase(aetest.Testcase): # local parameters defaults, same as above @@ -272,7 +272,7 @@ dynamically access & update parameters. @aetest.test def test(self): - # access & print parent test script parameters + # access & print parent TestScript parameters # (following the parent model) print(self.parent.parameters) # {'generic_param_A': 100, @@ -291,7 +291,7 @@ dynamically access & update parameters. Consider the above example: parameters can be set and accessed as the script runs, opening the opportunity for scripts to dynamically discover the runtime environment and modify test behavior (parameters) as required. E.g., the ``setup`` -section of modifying test case parameters based on the current testbed state, and +section of modifying Testcase parameters based on the current testbed state, and altering the behavior of ensuing ``test`` sections, etc. .. tip:: @@ -306,7 +306,7 @@ altering the behavior of ensuing ``test`` sections, etc. Script Arguments ---------------- -In short, any arguments passed to the test script before startup becomes part of +In short, any arguments passed to the TestScript before startup becomes part of the ``TestScript`` parameter. This includes all the arguments passed through the :ref:`easypy_jobfile` during :ref:`aetest_jobfile_execution`, and/or any command line arguments parsed and passed to ``aetest.main()`` during @@ -323,7 +323,7 @@ line arguments parsed and passed to ``aetest.main()`` during # without going into details about how script parameters/arguments are # passed in (covered under Running Scripts section) - # assuming that the test script was called with the following inputs + # assuming that the TestScript was called with the following inputs script_arguments = { 'arg_a': 100, 'arg_c': 3, @@ -353,7 +353,7 @@ script's base parameters and overwrite existing ones. .. tip:: Define your default parameters in the script, and change the behavior of - the test script by overwriting specific ones using script arguments. + the TestScript by overwriting specific ones using script arguments. .. _parameters_as_funcargs: @@ -404,7 +404,7 @@ their support. # this setup section definition identifies "param_B" # as an input requirement. As this parameter is available at this - # test case level (aggregated from the parent test script), it + # Testcase level (aggregated from the parent TestScript), it # is passed in as input @aetest.setup def setup(self, param_B): @@ -533,7 +533,7 @@ support arguments, can identify the current execution context, and can act accordingly. A parametrized function is declared when the ``@parameters.parametrize`` -decorator is used on a function within a test script. This also adds the newly +decorator is used on a function within a TestScript. This also adds the newly created parametrized function automatically as part of ``TestScript`` parameters, using the function name as the parameter name. @@ -583,7 +583,7 @@ identical to its callable parameter sibling, with the following additions: # As previously stated, there's no need to add parametrized functions # to the parameters dict(). They are automatically discovered and added. - # Defining two tests under this test case + # Defining two tests under this Testcase # ---------------------------------------------- # Similar to callable parameters, the above parameters # are evaluated when used as function arguments to section @@ -686,8 +686,8 @@ property, and is not useable as a function argument. # names as keyword arguments to methods @aetest.subsection def subsection_one(self, testscript, section, steps): - # Testscript object has an attribute called module - # which is this test script's module + # TestScript object has an attribute called module + # which is this TestScript's module print (testscript.module) # @@ -718,7 +718,7 @@ property, and is not useable as a function argument. Reserved parameters provide ``aetest`` a mechanism to offer optional features without polluting the :ref:`object_model` with additional attributes. It also -allows users to write test scripts that delve deeper and interact with the +allows users to write TestScripts that delve deeper and interact with the internals of ``aetest`` using a supported method instead of hacking around. *With great power comes great responsibilities* - use them wisely. diff --git a/docs/apidoc/easypy/pyats.easypy.runinfo.rst b/docs/apidoc/easypy/pyats.easypy.runinfo.rst index e75abb5..d7dda52 100644 --- a/docs/apidoc/easypy/pyats.easypy.runinfo.rst +++ b/docs/apidoc/easypy/pyats.easypy.runinfo.rst @@ -22,14 +22,4 @@ Submodules :show-inheritance: -.. automodule:: pyats.easypy.runinfo.kafka - :members: - :undoc-members: - :show-inheritance: - - -.. automodule:: pyats.easypy.runinfo.s3 - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/apidoc/index.rst b/docs/apidoc/index.rst index 33145ac..8522a8a 100644 --- a/docs/apidoc/index.rst +++ b/docs/apidoc/index.rst @@ -13,7 +13,6 @@ API Documentation robot/index async/index datastructures/index - tcl/index log/index reporter/index results/index diff --git a/docs/apidoc/kleenex/index.rst b/docs/apidoc/kleenex/index.rst index e18e20f..c0e63fe 100644 --- a/docs/apidoc/kleenex/index.rst +++ b/docs/apidoc/kleenex/index.rst @@ -11,38 +11,39 @@ Subpackages .. toctree:: - pyats.kleenex.loader + pyats.clean.loader pyats.kleenex.reporter + pyats.bringup Submodules ---------- -.. automodule:: pyats.kleenex.bases +.. automodule:: pyats.bringup.bases :members: :undoc-members: :show-inheritance: -.. automodule:: pyats.kleenex.bringup_base_cli_parser +.. automodule:: pyats.bringup.base_cli_parser :members: :undoc-members: :show-inheritance: -.. automodule:: pyats.kleenex.bringup_manager +.. automodule:: pyats.bringup.manager :members: :undoc-members: :show-inheritance: -.. automodule:: pyats.kleenex.bringup_manager_cli_parser +.. automodule:: pyats.bringup.manager_cli_parser :members: :undoc-members: :show-inheritance: -.. automodule:: pyats.kleenex.bringup_signals +.. automodule:: pyats.bringup.signals :members: :undoc-members: :show-inheritance: @@ -66,19 +67,19 @@ Submodules :show-inheritance: -.. automodule:: pyats.kleenex.kleenex_traceback +.. automodule:: pyats.clean.traceback :members: :undoc-members: :show-inheritance: -.. automodule:: pyats.kleenex.schema +.. automodule:: pyats.clean.schema :members: :undoc-members: :show-inheritance: -.. automodule:: pyats.kleenex.utils +.. automodule:: pyats.clean.utils :members: :undoc-members: :show-inheritance: diff --git a/docs/apidoc/kleenex/pyats.kleenex.loader.rst b/docs/apidoc/kleenex/pyats.clean.loader.rst similarity index 59% rename from docs/apidoc/kleenex/pyats.kleenex.loader.rst rename to docs/apidoc/kleenex/pyats.clean.loader.rst index d849f47..1a42c06 100644 --- a/docs/apidoc/kleenex/pyats.kleenex.loader.rst +++ b/docs/apidoc/kleenex/pyats.clean.loader.rst @@ -1,7 +1,7 @@ -pyats.kleenex.loader package +pyats.clean.loader package ============================ -.. automodule:: pyats.kleenex.loader +.. automodule:: pyats.clean.loader :members: :undoc-members: :show-inheritance: @@ -10,7 +10,7 @@ Submodules ---------- -.. automodule:: pyats.kleenex.loader.markup +.. automodule:: pyats.clean.loader.markup :members: :undoc-members: :show-inheritance: diff --git a/docs/apidoc/kleenex/pyats.kleenex.reporter.rst b/docs/apidoc/kleenex/pyats.kleenex.reporter.rst index e05f0cf..56a0c52 100644 --- a/docs/apidoc/kleenex/pyats.kleenex.reporter.rst +++ b/docs/apidoc/kleenex/pyats.kleenex.reporter.rst @@ -10,19 +10,7 @@ Submodules ---------- -.. automodule:: pyats.kleenex.reporter.base - :members: - :undoc-members: - :show-inheritance: - - -.. automodule:: pyats.kleenex.reporter.clean - :members: - :undoc-members: - :show-inheritance: - - -.. automodule:: pyats.kleenex.reporter.context +.. automodule:: pyats.kleenex.reporter.reporter :members: :undoc-members: :show-inheritance: diff --git a/docs/apidoc/log/index.rst b/docs/apidoc/log/index.rst index 1d1414e..a9723df 100644 --- a/docs/apidoc/log/index.rst +++ b/docs/apidoc/log/index.rst @@ -12,6 +12,7 @@ Subpackages .. toctree:: pyats.log.commands + pyats.atslog Submodules ---------- diff --git a/docs/apidoc/log/pyats.log.commands.parser.rst b/docs/apidoc/log/pyats.log.commands.parser.rst index 45a28f0..33cb2ea 100644 --- a/docs/apidoc/log/pyats.log.commands.parser.rst +++ b/docs/apidoc/log/pyats.log.commands.parser.rst @@ -10,19 +10,19 @@ Submodules ---------- -.. automodule:: pyats.log.commands.parser.base +.. automodule:: pyats.log.commands.parser.base_parser :members: :undoc-members: :show-inheritance: -.. automodule:: pyats.log.commands.parser.xml +.. automodule:: pyats.log.commands.parser.xml_parser :members: :undoc-members: :show-inheritance: -.. automodule:: pyats.log.commands.parser.yaml +.. automodule:: pyats.log.commands.parser.yaml_parser :members: :undoc-members: :show-inheritance: diff --git a/docs/apidoc/tcl/index.rst b/docs/apidoc/tcl/index.rst deleted file mode 100644 index fb8ff7b..0000000 --- a/docs/apidoc/tcl/index.rst +++ /dev/null @@ -1,59 +0,0 @@ -pyats.tcl package -================= - -.. automodule:: pyats.tcl - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - - -.. automodule:: pyats.tcl.array - :members: - :undoc-members: - :show-inheritance: - - -.. automodule:: pyats.tcl.history - :members: - :undoc-members: - :show-inheritance: - - -.. automodule:: pyats.tcl.internal - :members: - :undoc-members: - :show-inheritance: - - -.. automodule:: pyats.tcl.interpreter - :members: - :undoc-members: - :show-inheritance: - - -.. automodule:: pyats.tcl.keyedlist - :members: - :undoc-members: - :show-inheritance: - - -.. automodule:: pyats.tcl.namespace - :members: - :undoc-members: - :show-inheritance: - - -.. automodule:: pyats.tcl.q - :members: - :undoc-members: - :show-inheritance: - - -.. automodule:: pyats.tcl.tclstr - :members: - :undoc-members: - :show-inheritance: - diff --git a/docs/changelog/2020/index.rst b/docs/changelog/2020/index.rst index 0eac7d5..20aa920 100644 --- a/docs/changelog/2020/index.rst +++ b/docs/changelog/2020/index.rst @@ -10,8 +10,8 @@ sep aug jul - jun may apr mar + feb jan \ No newline at end of file diff --git a/docs/changelog/2022/august.rst b/docs/changelog/2022/august.rst new file mode 100644 index 0000000..fc3b4be --- /dev/null +++ b/docs/changelog/2022/august.rst @@ -0,0 +1,76 @@ +August 2022 +========== + +August 26 - Pyats v22.8 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v22.8 + ``pyats.aereport``, v22.8 + ``pyats.aetest``, v22.8 + ``pyats.async``, v22.8 + ``pyats.cisco``, v22.8 + ``pyats.connections``, v22.8 + ``pyats.datastructures``, v22.8 + ``pyats.easypy``, v22.8 + ``pyats.kleenex``, v22.8 + ``pyats.log``, v22.8 + ``pyats.reporter``, v22.8 + ``pyats.results``, v22.8 + ``pyats.robot``, v22.8 + ``pyats.tcl``, v22.8 + ``pyats.topology``, v22.8 + ``pyats.utils``, v22.8 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.easypy + * Fixed task-uids filter when using default Task IDs (e.g. Task-2) + +* pyats.manifest + * Add support for boolean overrides with `pyats manifest` CLI command + +* manifest + * combine_cli_args_and_script_arguments + * Handling for any number of uses of the ``--meta`` argument + +* pyats.topology + * Updated testbed.raw_config to contain post-extend, post-markup content. This fixes issues introduced by previous changes when using Genie jinja configure and YAML reference markup. + +* pyats.utils + * Updated schemaengine to support optional advanced datatypes + * Updated yaml loader to support advanced datatypes argument + * Updated yaml loader to store raw/pre/mark/validated/post content + + +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* ats.cisco + * bussinesstelemetry + * Updated get_paches for collecting package from requirements.txt + + diff --git a/docs/changelog/2022/july.rst b/docs/changelog/2022/july.rst new file mode 100644 index 0000000..8f723cd --- /dev/null +++ b/docs/changelog/2022/july.rst @@ -0,0 +1,64 @@ +July 2022 +========== + +July 26 - Pyats v22.7 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v22.7 + ``pyats.aereport``, v22.7 + ``pyats.aetest``, v22.7 + ``pyats.async``, v22.7 + ``pyats.cisco``, v22.7 + ``pyats.connections``, v22.7 + ``pyats.datastructures``, v22.7 + ``pyats.easypy``, v22.7 + ``pyats.kleenex``, v22.7 + ``pyats.log``, v22.7 + ``pyats.reporter``, v22.7 + ``pyats.results``, v22.7 + ``pyats.robot``, v22.7 + ``pyats.tcl``, v22.7 + ``pyats.topology``, v22.7 + ``pyats.utils``, v22.7 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.topology + * Update schema to correctly reflect peripheral structure + +* pyats.easypy + * Modified MailBot: + * Enabled {runtime} formatting for custom subjects on CLI + * Added `email.subject` configuration option + +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* ats.devat + * Add DevAT package to pyats repo + + diff --git a/docs/changelog/2022/november.rst b/docs/changelog/2022/november.rst new file mode 100644 index 0000000..33d5f71 --- /dev/null +++ b/docs/changelog/2022/november.rst @@ -0,0 +1,52 @@ +November 2022 +========== + +November 28 - Pyats v22.11 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v22.11 + ``pyats.aereport``, v22.11 + ``pyats.aetest``, v22.11 + ``pyats.async``, v22.11 + ``pyats.cisco``, v22.11 + ``pyats.connections``, v22.11 + ``pyats.datastructures``, v22.11 + ``pyats.easypy``, v22.11 + ``pyats.kleenex``, v22.11 + ``pyats.log``, v22.11 + ``pyats.reporter``, v22.11 + ``pyats.results``, v22.11 + ``pyats.robot``, v22.11 + ``pyats.tcl``, v22.11 + ``pyats.topology``, v22.11 + ``pyats.utils``, v22.11 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.cisco + * Fix TIMS upload (Cisco internal use only) + + diff --git a/docs/changelog/2022/october.rst b/docs/changelog/2022/october.rst new file mode 100644 index 0000000..cfc27fb --- /dev/null +++ b/docs/changelog/2022/october.rst @@ -0,0 +1,64 @@ +October 2022 +========== + +October 25 - Pyats v22.10 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v22.10 + ``pyats.aereport``, v22.10 + ``pyats.aetest``, v22.10 + ``pyats.async``, v22.10 + ``pyats.cisco``, v22.10 + ``pyats.connections``, v22.10 + ``pyats.datastructures``, v22.10 + ``pyats.easypy``, v22.10 + ``pyats.kleenex``, v22.10 + ``pyats.log``, v22.10 + ``pyats.reporter``, v22.10 + ``pyats.results``, v22.10 + ``pyats.robot``, v22.10 + ``pyats.tcl``, v22.10 + ``pyats.topology``, v22.10 + ``pyats.utils``, v22.10 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.utils + * Updated markup processer to support keys() as target + * Support %EXTEND_LIST markup to extend one or more lists as a value + * Modified recursive dict update to support hierarchical use of EXTEND_LIST markup + +* log + * Modified archive.py + * Added await to fix the bug where exposed API calls for results does not return file contents. + +* reporter + * Added Schema + * schema for results.json + * Modified commands.py + * added pyats validate results + + diff --git a/docs/changelog/2022/september.rst b/docs/changelog/2022/september.rst new file mode 100644 index 0000000..f67031f --- /dev/null +++ b/docs/changelog/2022/september.rst @@ -0,0 +1,87 @@ +September 2022 +========== + +September 27 - Pyats v22.9 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v22.9 + ``pyats.aereport``, v22.9 + ``pyats.aetest``, v22.9 + ``pyats.async``, v22.9 + ``pyats.cisco``, v22.9 + ``pyats.connections``, v22.9 + ``pyats.datastructures``, v22.9 + ``pyats.easypy``, v22.9 + ``pyats.kleenex``, v22.9 + ``pyats.log``, v22.9 + ``pyats.reporter``, v22.9 + ``pyats.results``, v22.9 + ``pyats.robot``, v22.9 + ``pyats.tcl``, v22.9 + ``pyats.topology``, v22.9 + ``pyats.utils``, v22.9 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ + +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + + +* pyats.topology + * Fixed return exit code for pyats validate testbed + +* pyats installer + * Updated pyATS installer + * Pinned installer dependencies + * Refactor installer builder + +* pyats.cli + * Updated cmd implementation, added encoding and ignoring errors + * Log output of failed commands if available + +* pyats.easypy + * Add support for clean files and logical testbed per task + +* easypy + * Modified Task + * Improved terminate to kill any subprocesses that remain after attempting to terminate + + +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* pyats + * Pinned pip version to use pip index versions + * Added wrapper for required, legacy and optional packages + +* pyats.cli.commands.version + * Added CheckAvailableVersions + * Created method to get all available versions of a package + * Created method to get the latest version of a list of packages + +* Modified update + * Added latest version to dialog confirming which packages will be updated + * Added --pre argument to fetch minor and dev versions + diff --git a/docs/changelog/2023/april.rst b/docs/changelog/2023/april.rst new file mode 100644 index 0000000..d626248 --- /dev/null +++ b/docs/changelog/2023/april.rst @@ -0,0 +1,73 @@ +April 2023 +========== + +April 25 - Pyats v23.4 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v23.4 + ``pyats.aereport``, v23.4 + ``pyats.aetest``, v23.4 + ``pyats.async``, v23.4 + ``pyats.cisco``, v23.4 + ``pyats.connections``, v23.4 + ``pyats.datastructures``, v23.4 + ``pyats.easypy``, v23.4 + ``pyats.kleenex``, v23.4 + ``pyats.log``, v23.4 + ``pyats.reporter``, v23.4 + ``pyats.results``, v23.4 + ``pyats.robot``, v23.4 + ``pyats.tcl``, v23.4 + ``pyats.topology``, v23.4 + ``pyats.utils``, v23.4 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.manifest + * Add support for CLI arguments with * as value + +* pyats.utils + * Fixed default value with CLI markup usage + +* pyats.easypy + * Update the plugin loading in the plugins and update the black_box test. + +* install + * Fix for installer to source venv for pip format json command. + +* update + * Fix to pick up ats packages instead of pyats + + +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* easypy + * moved AEPluginReporter and AEPluginContext and report_func Wrapper from Plugin Bundle + * move the reporter from plugin bundle to easypy reporter + + diff --git a/docs/changelog/2023/august.rst b/docs/changelog/2023/august.rst new file mode 100644 index 0000000..933aefb --- /dev/null +++ b/docs/changelog/2023/august.rst @@ -0,0 +1,70 @@ +August 2023 +========== + +August 29 - Pyats v23.8 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v23.8 + ``pyats.aereport``, v23.8 + ``pyats.aetest``, v23.8 + ``pyats.async``, v23.8 + ``pyats.cisco``, v23.8 + ``pyats.connections``, v23.8 + ``pyats.datastructures``, v23.8 + ``pyats.easypy``, v23.8 + ``pyats.kleenex``, v23.8 + ``pyats.log``, v23.8 + ``pyats.reporter``, v23.8 + ``pyats.results``, v23.8 + ``pyats.robot``, v23.8 + ``pyats.tcl``, v23.8 + ``pyats.topology``, v23.8 + ``pyats.utils``, v23.8 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* pyats.aetest + * Added support for YAML Markup with datafiles, including testbed references + +* pyats.utils + * add new function chainattrget + +* pyats.easypy + * Added section result statistics to job report + + +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.kleenex + * Update device name mapping logic to support missing entries from orchestrator + * Fix device names used with actual testbed vs logical testbed for use with clean image overrides + +* pyats.utils + * Updated implementation of enforce_max_key_value_length to support hierarchical dictionaries + + diff --git a/docs/changelog/2023/february.rst b/docs/changelog/2023/february.rst new file mode 100644 index 0000000..11ce6bb --- /dev/null +++ b/docs/changelog/2023/february.rst @@ -0,0 +1,60 @@ +February 2023 +========== + +February 28 - Pyats v23.2 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v23.2 + ``pyats.aereport``, v23.2 + ``pyats.aetest``, v23.2 + ``pyats.async``, v23.2 + ``pyats.cisco``, v23.2 + ``pyats.connections``, v23.2 + ``pyats.datastructures``, v23.2 + ``pyats.easypy``, v23.2 + ``pyats.kleenex``, v23.2 + ``pyats.log``, v23.2 + ``pyats.reporter``, v23.2 + ``pyats.results``, v23.2 + ``pyats.robot``, v23.2 + ``pyats.tcl``, v23.2 + ``pyats.topology``, v23.2 + ``pyats.utils``, v23.2 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* pyats.utils + * Modified %CLI markup + * Added support for default value, including list syntax support + +* install + * Updated the pyats installer. + * The installer can now install all the required and optional packages. + +* topology + * Updated the schema to support management apis + + diff --git a/docs/changelog/2023/january.rst b/docs/changelog/2023/january.rst new file mode 100644 index 0000000..c8b281a --- /dev/null +++ b/docs/changelog/2023/january.rst @@ -0,0 +1,46 @@ +January 2023 +========== + +January 31 - Pyats v23.1 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v23.1 + ``pyats.aereport``, v23.1 + ``pyats.aetest``, v23.1 + ``pyats.async``, v23.1 + ``pyats.cisco``, v23.1 + ``pyats.connections``, v23.1 + ``pyats.datastructures``, v23.1 + ``pyats.easypy``, v23.1 + ``pyats.kleenex``, v23.1 + ``pyats.log``, v23.1 + ``pyats.reporter``, v23.1 + ``pyats.results``, v23.1 + ``pyats.robot``, v23.1 + ``pyats.tcl``, v23.1 + ``pyats.topology``, v23.1 + ``pyats.utils``, v23.1 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ + + diff --git a/docs/changelog/2023/july.rst b/docs/changelog/2023/july.rst new file mode 100644 index 0000000..9199c12 --- /dev/null +++ b/docs/changelog/2023/july.rst @@ -0,0 +1,52 @@ +July 2023 +========== + +July 25 - Pyats v23.7 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v23.7 + ``pyats.aereport``, v23.7 + ``pyats.aetest``, v23.7 + ``pyats.async``, v23.7 + ``pyats.cisco``, v23.7 + ``pyats.connections``, v23.7 + ``pyats.datastructures``, v23.7 + ``pyats.easypy``, v23.7 + ``pyats.kleenex``, v23.7 + ``pyats.log``, v23.7 + ``pyats.reporter``, v23.7 + ``pyats.results``, v23.7 + ``pyats.robot``, v23.7 + ``pyats.tcl``, v23.7 + ``pyats.topology``, v23.7 + ``pyats.utils``, v23.7 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* ats.kleenex + * Allow users to override device `type` and `alias` with values from logical testbed + + diff --git a/docs/changelog/2023/june.rst b/docs/changelog/2023/june.rst new file mode 100644 index 0000000..043a324 --- /dev/null +++ b/docs/changelog/2023/june.rst @@ -0,0 +1,55 @@ +June 2023 +========== + +June 27 - Pyats v23.6 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v23.6 + ``pyats.aereport``, v23.6 + ``pyats.aetest``, v23.6 + ``pyats.async``, v23.6 + ``pyats.cisco``, v23.6 + ``pyats.connections``, v23.6 + ``pyats.datastructures``, v23.6 + ``pyats.easypy``, v23.6 + ``pyats.kleenex``, v23.6 + ``pyats.log``, v23.6 + ``pyats.reporter``, v23.6 + ``pyats.results``, v23.6 + ``pyats.robot``, v23.6 + ``pyats.tcl``, v23.6 + ``pyats.topology``, v23.6 + ``pyats.utils``, v23.6 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.easypy + * Fixed issue with multiprocessing causing socket usage collisions + +* pyats.kleenex + * Updated bringup logic to allow users to specify any interface type + + diff --git a/docs/changelog/2023/march.rst b/docs/changelog/2023/march.rst new file mode 100644 index 0000000..09be568 --- /dev/null +++ b/docs/changelog/2023/march.rst @@ -0,0 +1,55 @@ +March 2023 +========== + +March 28 - Pyats v23.3 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v23.3 + ``pyats.aereport``, v23.3 + ``pyats.aetest``, v23.3 + ``pyats.async``, v23.3 + ``pyats.cisco``, v23.3 + ``pyats.connections``, v23.3 + ``pyats.datastructures``, v23.3 + ``pyats.easypy``, v23.3 + ``pyats.kleenex``, v23.3 + ``pyats.log``, v23.3 + ``pyats.reporter``, v23.3 + ``pyats.results``, v23.3 + ``pyats.robot``, v23.3 + ``pyats.tcl``, v23.3 + ``pyats.topology``, v23.3 + ``pyats.utils``, v23.3 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.manifest + * Add support for CLI arguments with * as value + +* pyats.utils + * Fixed default value with CLI markup usage + + diff --git a/docs/changelog/2023/may.rst b/docs/changelog/2023/may.rst new file mode 100644 index 0000000..c8fc75b --- /dev/null +++ b/docs/changelog/2023/may.rst @@ -0,0 +1,70 @@ +May 2023 +========== + +May 30 - Pyats v23.5 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v23.5 + ``pyats.aereport``, v23.5 + ``pyats.aetest``, v23.5 + ``pyats.async``, v23.5 + ``pyats.cisco``, v23.5 + ``pyats.connections``, v23.5 + ``pyats.datastructures``, v23.5 + ``pyats.easypy``, v23.5 + ``pyats.kleenex``, v23.5 + ``pyats.log``, v23.5 + ``pyats.reporter``, v23.5 + ``pyats.results``, v23.5 + ``pyats.robot``, v23.5 + ``pyats.tcl``, v23.5 + ``pyats.topology``, v23.5 + ``pyats.utils``, v23.5 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.pyats + * Add a cli for manifest to use symlink + +* pyats.easypy + * Add checking for using symlink for the manifest + * Update manifest execution logic to allow jobfiles to be symlinked to another folder + +* aetest + * Modified PausePdb + * Dumps the connection information from the testbed to the console + + +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* easypy + * Added suite_id to all the jobs reports + * Add suite_name to report data from suite-name CLI argument + * Added label and component reporting options + + diff --git a/docs/changelog/2023/november.rst b/docs/changelog/2023/november.rst new file mode 100644 index 0000000..3b585e4 --- /dev/null +++ b/docs/changelog/2023/november.rst @@ -0,0 +1,95 @@ +November 2023 +========== + +November 27 - Pyats v23.11 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v23.11 + ``pyats.aereport``, v23.11 + ``pyats.aetest``, v23.11 + ``pyats.async``, v23.11 + ``pyats.cisco``, v23.11 + ``pyats.connections``, v23.11 + ``pyats.datastructures``, v23.11 + ``pyats.easypy``, v23.11 + ``pyats.kleenex``, v23.11 + ``pyats.log``, v23.11 + ``pyats.reporter``, v23.11 + ``pyats.results``, v23.11 + ``pyats.robot``, v23.11 + ``pyats.tcl``, v23.11 + ``pyats.topology``, v23.11 + ``pyats.utils``, v23.11 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* bringup.bases + * Added authenticate method to BringUpWorkerBase + * Class method to handle authentication before bringup + +* bringup.manager + * Modified __enter__ to authenticate + * Authentication is done (if required) before start_server is called + +* reporter + * Modified Testsuite/Task report + * Testsuite and Task now have an overall result in the final report + + +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* clean + * Modified bases.py + * Set default loglevel to be inherited from pyats + +* kleenex + * Modified kleenex package structure + * Split kleenex into bringup, clean, kleenex + * Bringup contains the scripts to bringup logical devices + * Clean contains the scripts common to bringup and kleenex + * Kleenex contains the scripts to execute clean + * Fixed issue with kleenex loader where the `--clean-image-json` argument wouldn't allow for device aliases to be passed + * Added unittests to verify changes + +* easypy + * Modified kleenex plugin + * Updated references to kleenex package structure + +* pyats.topology + * Updated schema to support services for testbed servers. + +* manifest + * Fixed issue with `parse_cli_args` where the `meta` argument would get nested in lists if it was specified more than two times + +* pyats.connections.bases + * Add CLI arguments to service wrapper + * Updated docs + * Detached service wrapper from easypy runtime + * Added steps to service wrapper methods to allow for reporting + + diff --git a/docs/changelog/2023/october.rst b/docs/changelog/2023/october.rst new file mode 100644 index 0000000..e4f64f3 --- /dev/null +++ b/docs/changelog/2023/october.rst @@ -0,0 +1,65 @@ +October 2023 +========== + +October 31 - Pyats v23.10 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v23.10 + ``pyats.aereport``, v23.10 + ``pyats.aetest``, v23.10 + ``pyats.async``, v23.10 + ``pyats.cisco``, v23.10 + ``pyats.connections``, v23.10 + ``pyats.datastructures``, v23.10 + ``pyats.easypy``, v23.10 + ``pyats.kleenex``, v23.10 + ``pyats.log``, v23.10 + ``pyats.reporter``, v23.10 + ``pyats.results``, v23.10 + ``pyats.robot``, v23.10 + ``pyats.tcl``, v23.10 + ``pyats.topology``, v23.10 + ``pyats.utils``, v23.10 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.kleenex + * Modified markup processor to use chainattrget utility function to allow object attribute and key lookup + +* easypy + * Modified update_job + * Modified update_job to format elapsedtime + + +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* topology + * Updated schema for fallback credentials + * Add fallback credentials under connection + + diff --git a/docs/changelog/2023/september.rst b/docs/changelog/2023/september.rst new file mode 100644 index 0000000..d14fb2b --- /dev/null +++ b/docs/changelog/2023/september.rst @@ -0,0 +1,87 @@ +September 2023 +========== + +September 26 - Pyats v23.9 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v23.9 + ``pyats.aereport``, v23.9 + ``pyats.aetest``, v23.9 + ``pyats.async``, v23.9 + ``pyats.cisco``, v23.9 + ``pyats.connections``, v23.9 + ``pyats.datastructures``, v23.9 + ``pyats.easypy``, v23.9 + ``pyats.kleenex``, v23.9 + ``pyats.log``, v23.9 + ``pyats.reporter``, v23.9 + ``pyats.results``, v23.9 + ``pyats.robot``, v23.9 + ``pyats.tcl``, v23.9 + ``pyats.topology``, v23.9 + ``pyats.utils``, v23.9 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* pyats + * Added BaseServiceWrapper class + +* pyats.aetest + * Added support for YAML Markup with datafiles, including testbed references + +* pyats.utils + * add new function chainattrget + * Added duplicate key detection in yaml loader + +* pyats.easypy + * Added section result statistics to job report + + +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.kleenex + * Update device name mapping logic to support missing entries from orchestrator + * Fix device names used with actual testbed vs logical testbed for use with clean image overrides + +* pyats.topology + * Updated management schema type for protocols. + +* pyats.utils + * Updated implementation of enforce_max_key_value_length to support hierarchical dictionaries + +* kleenex + * Modified KleenexMarkupProcessor + * Delayed processing of testbed markups to support logical testbeds + * Modified kleenex_main + * Reloaded clean file to process testbed markups after topology bringup + +* easypy + * Modified Kleenex Plugin + * Reloaded clean file to process testbed markups after topology bringup + + diff --git a/docs/changelog/2024/September.rst b/docs/changelog/2024/September.rst new file mode 100644 index 0000000..b7d2101 --- /dev/null +++ b/docs/changelog/2024/September.rst @@ -0,0 +1,50 @@ +September 2024 +========== + +September 24 - Pyats v24.9 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v24.9 + ``pyats.aereport``, v24.9 + ``pyats.aetest``, v24.9 + ``pyats.async``, v24.9 + ``pyats.cisco``, v24.9 + ``pyats.connections``, v24.9 + ``pyats.datastructures``, v24.9 + ``pyats.easypy``, v24.9 + ``pyats.kleenex``, v24.9 + ``pyats.log``, v24.9 + ``pyats.reporter``, v24.9 + ``pyats.results``, v24.9 + ``pyats.robot``, v24.9 + ``pyats.tcl``, v24.9 + ``pyats.topology``, v24.9 + ``pyats.utils``, v24.9 + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* pyats.connections.wrapper + * Added add_service_wrapper_usage_data function to push service wrapper data to business telemetry. + + +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* topology + * schema + * Added device id to schema + + diff --git a/docs/changelog/2024/april.rst b/docs/changelog/2024/april.rst new file mode 100644 index 0000000..f877e62 --- /dev/null +++ b/docs/changelog/2024/april.rst @@ -0,0 +1,102 @@ +April 2024 +========== + +April 30 - Pyats v24.4 +---------------------- + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v24.4 + ``pyats.aereport``, v24.4 + ``pyats.aetest``, v24.4 + ``pyats.async``, v24.4 + ``pyats.cisco``, v24.4 + ``pyats.connections``, v24.4 + ``pyats.datastructures``, v24.4 + ``pyats.easypy``, v24.4 + ``pyats.kleenex``, v24.4 + ``pyats.log``, v24.4 + ``pyats.reporter``, v24.4 + ``pyats.results``, v24.4 + ``pyats.robot``, v24.4 + ``pyats.tcl``, v24.4 + ``pyats.topology``, v24.4 + ``pyats.utils``, v24.4 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* pyats.easypy + * Added Tips Plugin + * A new plugin that provides a way to display tips and tricks to users + +* pyats.topology + * Updated Device class `repr`, added alias value + + +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* easypy + * Fix device recovery data type for tftp address + * Modified Plugin Reporting + * Plugins now report errors as results even when the plugin is not specified to report anything. This prevents the overall result showing Passed when a plugin had an error. + +* iosxe + * Added RerunPlugin + * Remove commonSetup, commonCleanup, testcases if it is none. + +* easypy/plugins + * kleenex + * updated logic to add device recovery section even if there are no clean image attributes. + +* pyats.connections + * Modified connection manager + * Updated logic to support service wrapper with connection pools + * Pass Steps object to service wrapper if none found + +* pyats.aetest + * Modified Steps class to support index offset + +* pyats.async + * Support Steps with pcall + * Modified child process logic to update steps offset for child processes + * Add logic to propagate step failures in subprocess + +* bringup + * Manager + * Fixed bug preventing manager from halting exit with pyats clean command + +* kleenex + * loader + * Update to load and check the logical testbed in _preprocess_add_cli_images in order to get correct image_set for iol devices. + +* pyats.cisco + * Fix telemetry upload + +* utils/fileutils + * http + * Added logic for http stat in fileutils. + + diff --git a/docs/changelog/2024/february.rst b/docs/changelog/2024/february.rst new file mode 100644 index 0000000..e0e610f --- /dev/null +++ b/docs/changelog/2024/february.rst @@ -0,0 +1,101 @@ +February 2024 +========== + +February 27 - Pyats v24.2 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v24.2 + ``pyats.aereport``, v24.2 + ``pyats.aetest``, v24.2 + ``pyats.async``, v24.2 + ``pyats.cisco``, v24.2 + ``pyats.connections``, v24.2 + ``pyats.datastructures``, v24.2 + ``pyats.easypy``, v24.2 + ``pyats.kleenex``, v24.2 + ``pyats.log``, v24.2 + ``pyats.reporter``, v24.2 + ``pyats.results``, v24.2 + ``pyats.robot``, v24.2 + ``pyats.tcl``, v24.2 + ``pyats.topology``, v24.2 + ``pyats.utils``, v24.2 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Add +-------------------------------------------------------------------------------- + +* docker + * Added aarch64 python 3.12 builder + + +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* makefile + * Added aiohttp package + +* easypy.plugins + * kleenex.py + * Added logic to update device recovery information to clean data. + * kleenex.py + * Added dyntopo entrypoints to take cli args from the workers. + + +-------------------------------------------------------------------------------- + Modify +-------------------------------------------------------------------------------- + +* aetest-pkg + * Removed unused and deprecated imports + * Renamed the file to fix UT issue + +* easypy-pkg + * assertEquals is not support for 3.12 hence changed to assertEqual + +* utils-pkg + * updated import utils with exec_module instead of load_module + + +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* installer + * Modified installer script to remove dependency on pypi.org (Cisco internal use only) + +* pyats.connections + * utils.py + * Fixed bug with set_parameters and added unittest + +* pyats.connections.bases + * Move wrapper to before connection so that `connect` can be wrapped + +* easypy.plugins + * Modified XunitPlugin + * Updated post_job method and separated xunit xml generation code + * Added conditional xunit_include_logs parameter to generate xunit.xml + + diff --git a/docs/changelog/2024/january.rst b/docs/changelog/2024/january.rst new file mode 100644 index 0000000..e962d0c --- /dev/null +++ b/docs/changelog/2024/january.rst @@ -0,0 +1,108 @@ +January 2024 +========== + +30 - Pyats v24.1 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v24.1 + ``pyats.aereport``, v24.1 + ``pyats.aetest``, v24.1 + ``pyats.async``, v24.1 + ``pyats.cisco``, v24.1 + ``pyats.connections``, v24.1 + ``pyats.datastructures``, v24.1 + ``pyats.easypy``, v24.1 + ``pyats.kleenex``, v24.1 + ``pyats.log``, v24.1 + ``pyats.reporter``, v24.1 + ``pyats.results``, v24.1 + ``pyats.robot``, v24.1 + ``pyats.tcl``, v24.1 + ``pyats.topology``, v24.1 + ``pyats.utils``, v24.1 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* kleenex + * Fixed issue with kleenex loader handling device alias + +* pyats.configuration + * Removed pyATS Configuration object from sys.modules, refactored usage + * Change "from pyats import configuration" to "from pyats.configuration import configuration" + +* log-pkg + * commands + * remove aiohttp-swagger and its references to resolve markupsafe errors + +* pyats.utils + * Updated YAML markup processor to support markup in dictionary keys + +* easypy + * Removed + * Removed duplicate Task Result Details and Task Result Summary + +* pyats.topology + * Updated management schema type for address and gateway. + +* pyats.kleenex + * Modified p_reference_markup + * Parse credentials on testbed.raw_config + + +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* easypy.plugins + * kleenex.py + * Added preprocessor logic to update default clean image + +* cisco.commands + * Added pyats testbed teardown + * Added command to teardown topology using dyntopo orchestrators + * Added pyats testbed bringup + * Added command to bringup topology using dyntopo orchestrators + +* easypy + * AEReporter + * add skipped to AEPluginReporter + * Kleenex + * Add skip-teardown-on-failure argument to skip teardown when success rate is below 100% + +* pyats.utils + * Added load_dict_from_list + * Added support for meta argument if passed as a list + * Support keyword argument (kwarg) syntax with CALLABLE YAML markup + +* bringup.bases + * Added skip_teardown argument + * Added argument to skip topology teardown after clean/bringup execution. + +* easypy.plugins.kleenex + * Added skip_teardown argument + * Added argument to skip topology teardown after test case execution. + + diff --git a/docs/changelog/2024/july.rst b/docs/changelog/2024/july.rst new file mode 100644 index 0000000..1b207e7 --- /dev/null +++ b/docs/changelog/2024/july.rst @@ -0,0 +1,69 @@ +July 2024 +========== + +July 30 - Pyats v24.7 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v24.7 + ``pyats.aereport``, v24.7 + ``pyats.aetest``, v24.7 + ``pyats.async``, v24.7 + ``pyats.cisco``, v24.7 + ``pyats.connections``, v24.7 + ``pyats.datastructures``, v24.7 + ``pyats.easypy``, v24.7 + ``pyats.kleenex``, v24.7 + ``pyats.log``, v24.7 + ``pyats.reporter``, v24.7 + ``pyats.results``, v24.7 + ``pyats.robot``, v24.7 + ``pyats.tcl``, v24.7 + ``pyats.topology``, v24.7 + ``pyats.utils``, v24.7 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.utils + * Modified argv parser helper function + * Ignore arguments after `--` + * Allow `-` to be passed as a value + +* pyats.cli + * Modified version update + * Ignore packages that have no matching version + + +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* pyats.reporter + * update the log offset for each sub process + +* pyats + * remove init file for declaring namespaces for all the packages to avoid deprecation messages. + + diff --git a/docs/changelog/2024/june.rst b/docs/changelog/2024/june.rst new file mode 100644 index 0000000..277caf3 --- /dev/null +++ b/docs/changelog/2024/june.rst @@ -0,0 +1,63 @@ +June 2024 +========== + + - Pyats v24.6 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v24.6 + ``pyats.aereport``, v24.6 + ``pyats.aetest``, v24.6 + ``pyats.async``, v24.6 + ``pyats.cisco``, v24.6 + ``pyats.connections``, v24.6 + ``pyats.datastructures``, v24.6 + ``pyats.easypy``, v24.6 + ``pyats.kleenex``, v24.6 + ``pyats.log``, v24.6 + ``pyats.reporter``, v24.6 + ``pyats.results``, v24.6 + ``pyats.robot``, v24.6 + ``pyats.tcl``, v24.6 + ``pyats.topology``, v24.6 + ``pyats.utils``, v24.6 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* easy/plugins + * kleenex + * Fixed clean default image issue. + * kleenex + * Fixed clean default image where multiple images being passed to each device, instead + +* kleenex + * clean/loader + * Fixed a bug with clean templates, where it was not updating the clean image properly. + +* topology + * Modified schema + * Added submodel key in device schema + + diff --git a/docs/changelog/2024/march.rst b/docs/changelog/2024/march.rst new file mode 100644 index 0000000..bef8277 --- /dev/null +++ b/docs/changelog/2024/march.rst @@ -0,0 +1,80 @@ +March 2024 +========== + + - Pyats v24.3 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v24.3 + ``pyats.aereport``, v24.3 + ``pyats.aetest``, v24.3 + ``pyats.async``, v24.3 + ``pyats.cisco``, v24.3 + ``pyats.connections``, v24.3 + ``pyats.datastructures``, v24.3 + ``pyats.easypy``, v24.3 + ``pyats.kleenex``, v24.3 + ``pyats.log``, v24.3 + ``pyats.reporter``, v24.3 + ``pyats.results``, v24.3 + ``pyats.robot``, v24.3 + ``pyats.tcl``, v24.3 + ``pyats.topology``, v24.3 + ``pyats.utils``, v24.3 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* easypy.plugins + * rerun + * Added ability to download archive/rerun file from a URL + +* pyats.aetest + * Modified PauseOnPhrase, added collect and custom options + +* pyats.cli + * Migrate abstract + * Added functionality to the `pyats migrate abstract` command to modify the files in-place with the suggested changes + +* easypy + * plugins(kleenex) + * add --clean-template-action cli argument to kleenex plugin. + +* kleenex + * loader + * add logic for loading a template for cleaning the device + + +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.connection + * Service Wrapper + * Fixed an issue that caused a circular import when using the service wrapper with external connection packages + * Changed `BaseServiceWrapper` to `ServiceWrapper` + * Changed `ServiceWrapper` import from `from pyats.connections.bases import BaseServiceWrapper` to `from pyats.connections import ServiceWrapper` + * This feature replaces the previous concept of Service Hooks + + diff --git a/docs/changelog/2024/may.rst b/docs/changelog/2024/may.rst new file mode 100644 index 0000000..addb779 --- /dev/null +++ b/docs/changelog/2024/may.rst @@ -0,0 +1,77 @@ +May 2024 +========== + +May 28 - Pyats v24.5 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v24.5 + ``pyats.aereport``, v24.5 + ``pyats.aetest``, v24.5 + ``pyats.async``, v24.5 + ``pyats.cisco``, v24.5 + ``pyats.connections``, v24.5 + ``pyats.datastructures``, v24.5 + ``pyats.easypy``, v24.5 + ``pyats.kleenex``, v24.5 + ``pyats.log``, v24.5 + ``pyats.reporter``, v24.5 + ``pyats.results``, v24.5 + ``pyats.robot``, v24.5 + ``pyats.tcl``, v24.5 + ``pyats.topology``, v24.5 + ``pyats.utils``, v24.5 + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # DevNet Community + bash$ pip install --upgrade pyats + + # Cisco Internal Developers + bash$ pip install --upgrade ats + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* pyats.cisco + * Update package discovery error handling + * Update ABS URL, add environment variable lookup + + +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* kleenex/worker + * Updated logic to make device alias name as default in reporter. + +* pyats/topology + * schema + * Update topology schema for rommon information. + +* clean + * schema + * Updated clean schema with resources section with memory and cpu. + +* cisco/commands/testbed + * bringup + * Updated logic to pull the dyntopo worker arguments dynamically. + +* cisco/commands + * testbed/export + * Added export subcommand to export the testbed data using laasv2 + + diff --git a/docs/changelog/2024/october.rst b/docs/changelog/2024/october.rst new file mode 100644 index 0000000..5eb7b1f --- /dev/null +++ b/docs/changelog/2024/october.rst @@ -0,0 +1,41 @@ +October 2024 +========== + +October 29 - Pyats v24.10 +------------------------ + + + +.. csv-table:: New Module Versions + :header: "Modules", "Version" + + ``pyats``, v24.10 + ``pyats.aereport``, v24.10 + ``pyats.aetest``, v24.10 + ``pyats.async``, v24.10 + ``pyats.cisco``, v24.10 + ``pyats.connections``, v24.10 + ``pyats.datastructures``, v24.10 + ``pyats.easypy``, v24.10 + ``pyats.kleenex``, v24.10 + ``pyats.log``, v24.10 + ``pyats.reporter``, v24.10 + ``pyats.results``, v24.10 + ``pyats.robot``, v24.10 + ``pyats.tcl``, v24.10 + ``pyats.topology``, v24.10 + ``pyats.utils``, v24.10 + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* fixed the schema for management routes + * Update to add static route ipv4 + + diff --git a/docs/changelog/index.rst b/docs/changelog/index.rst index f2f7b07..457a653 100644 --- a/docs/changelog/index.rst +++ b/docs/changelog/index.rst @@ -8,6 +8,31 @@ Changelog .. toctree:: :maxdepth: 2 + 2024/october + 2024/September + 2024/july + 2024/june + 2024/may + 2024/april + 2024/march + 2024/february + 2024/january + 2023/november + 2023/october + 2023/september + 2023/august + 2023/july + 2023/june + 2023/may + 2023/april + 2023/march + 2023/february + 2023/january + 2022/november + 2022/october + 2022/september + 2022/august + 2022/july 2022/june 2022/may 2022/april diff --git a/docs/cli/index.rst b/docs/cli/index.rst index 5ed5993..f4ec086 100644 --- a/docs/cli/index.rst +++ b/docs/cli/index.rst @@ -15,6 +15,7 @@ and usage. pyats_create pyats_develop pyats_logs + pyats_migrate pyats_run pyats_secret pyats_shell diff --git a/docs/cli/pyats.rst b/docs/cli/pyats.rst index 8cb59fc..2721dbe 100644 --- a/docs/cli/pyats.rst +++ b/docs/cli/pyats.rst @@ -14,8 +14,18 @@ Synopsis pyats [options] Commands: - validate utlities that helps to validate input files - version display currently installed pyATS version + clean runs the provided clean file + create create scripts and libraries from template + diff Command to diff two snapshots saved to file or directory + learn Command to learn device features and save to file + logs command enabling log archive viewing in local browser + migrate utilities for migrating to future versions of pyATS + parse Command to parse show commands + run runs the provided script and output corresponding results. + secret utilities for working with secret strings. + shell enter Python shell, loading a pyATS testbed file and/or pickled data + validate utilities that help to validate input files + version commands related to version display and manipulation General Options: -h, --help Show help diff --git a/docs/cli/pyats_migrate.rst b/docs/cli/pyats_migrate.rst new file mode 100644 index 0000000..973de7c --- /dev/null +++ b/docs/cli/pyats_migrate.rst @@ -0,0 +1,44 @@ +pyats migrate +============= + +Command to identify and inform a user of required upcoming changes to their +environment. + +.. code-block:: text + + Usage: + pyats migrate [options] + + Subcommands: + abstract Discover what changes must be made to existing test environments to conform + to the new token discovery. + + +pyats migrate abstract +--------------------- + +The mechanism for `Genie Abstract`_ and the organization of `Unicon Supported Platforms`_ +are being updated for better consistency and utility. This subcommand will +examine your environment and inform you of any potential changes that may be +required. The usage of ``os``, ``model``, ``platform`` will be strictly defined within +Unicon in the `PID tokens`_ file and may require updates to testbeds and scripts to correctly reflect +these definitions. + +.. _Genie Abstract: https://pubhub.devnetcloud.com/media/genie-docs/docs/abstract/index.html +.. _Unicon Supported Platforms: https://pubhub.devnetcloud.com/media/unicon/docs/user_guide/supported_platforms.html +.. _PID tokens: https://github.com/CiscoTestAutomation/unicon.plugins/blob/master/src/unicon/plugins/pid_tokens.csv + +.. code-block:: text + + Usage: + pyats migrate abstract [options] + + Description: + Discover what changes must be made to existing test environments to conform to the new token discovery. + + Abstract Options: + path Path to start searching for files + --init Only process __init__.py files + --python Only process Python files + --yaml Only process YAML files + --threads THREADS Max number of threads to run while processing files (default 100) diff --git a/docs/cli/pyats_validate.rst b/docs/cli/pyats_validate.rst index 24a89ae..6518bc1 100644 --- a/docs/cli/pyats_validate.rst +++ b/docs/cli/pyats_validate.rst @@ -11,6 +11,7 @@ related input files, formats, and content. Subcommands: datafile validate your YAML-based datafile syntax + jinja2_config validate genie config file jinja2 rendering testbed validate your testbed file yaml syntax General Options: @@ -225,4 +226,71 @@ Example .. tip:: - use ``-q`` to quiet pretty information such as "----" sections and headers. \ No newline at end of file + use ``-q`` to quiet pretty information such as "----" sections and headers. + + + + +pyats validate jinja2_config +---------------------------- + +This subcommand validates the content of your Genie configuration datafile. It +gives developers an opportunity to check if the file is written following +valid YAML syntax and what the Jinja2 rendered output configuration looks like. + +.. code-block:: text + + Usage: + pyats validate jinja2_config [file] [options] + + Description: + Validates the provided genie config file for jinja2 rendering. + + Jinja2_config Options: + [file] Genie config datafile to validate + --testbed-file TESTBED + Testbed file (required) + --devices DEVICES [DEVICES ...] + Devices to render configs for (optional) + --sequence SEQUENCE [SEQUENCE ...] + Sequence(s) to render (optional) + + General Options: + -h, --help Show help + -v, --verbose Give more output, additive up to 3 times. + -q, --quiet Give less output, additive up to 3 times, corresponding to WARNING, ERROR, + and CRITICAL logging levels + +Options +^^^^^^^ + +``[file]`` + The Genie configuration datafile. Can be a file path or a URL to a YAML file + +``--devices`` + Device names to render the configuration for. Only configurations for these devices will be + used to render configurations. + +``--sequence`` + Sequence(s) to render the configuration for. Only the sequences specified will be rendered. + + +Example +^^^^^^^ + + +.. code-block:: text + + $ pyats validate jinja2_config data/config_datafile.yaml --testbed-file data/testbed.yaml --sequence 1 + + Device R1 sequence 1: + interface Loopback0 + no shutdown + ip address 1.1.1.1 255.255.255.255 + + + Device R2 sequence 1: + interface Loopback0 + no shutdown + ip address 2.2.2.2 255.255.255.255 + diff --git a/docs/configuration/index.rst b/docs/configuration/index.rst index 2d03605..ac46259 100644 --- a/docs/configuration/index.rst +++ b/docs/configuration/index.rst @@ -126,6 +126,8 @@ The following fields are currently open for user to customize. format = # Collect git info, default is True. git_info = + # section reporting, default is "SubSection SetupSection CleanupSection TestSection" + sections = SubSection SetupSection CleanupSection TestSection # configuration related to timestamps [timestamp] diff --git a/docs/connections/hook.rst b/docs/connections/hook.rst deleted file mode 100644 index a151072..0000000 --- a/docs/connections/hook.rst +++ /dev/null @@ -1,173 +0,0 @@ -Connection Hook -=============== - -Whereas a connection class provides the fundamentals of communicating to target -devices using object methods (**services**), the goal of a connection hook is -to *tap* onto particular services and *inject* code to run before and after the -actual service call, **without modifying** the original behavior. - -Here are some typical use cases of connection hooks: - - - tracking the sequence/occurance of CLI command calls throughout a script - - - debug-logging the input arguments to, and output values from particular - services. - - - building a LRU cache based on script inputs and device states. - - - etc. - - -Usage ------ - -A connection hook wraps the original connection service method, and replaces it -during runtime (dynamically). The original functionality of the service remains -intact, but the hook enables uses to add code before/after the service method. - -- all connection hooks should inherit the base ``connections.hooks.ServiceHook`` - class - -- to add code *before a service*, define the ``enter()`` method under your - class. - - - all arguments to the service is passed to ``enter()`` method in the same way - as the original call. - -- to execute code *after a service*, define the ``after()`` method under your - class - - - the return of the service is passed to the ``after()`` method - -- to enable custom error/exception tracking, define a ``error_handle()`` method - under you class. - - - the current exception is passed into the error handler as ``e``. - -- to disable the current hook, call the ``restore()`` method of the hook. - -.. note:: - - error handlers can suppress an exception, and/or track/register it - internally. By default the built-in error handler will simply raise the - current exception. Developer can modify that to suppress the current - exception being handled, and return a fixed/altered result. - - -.. code-block:: python - - # Example - # ------- - # - # a simple tracking implementation - - import pdb - import collections - - from pyats.connections.hooks import ServiceHook - - class Tracker(ServiceHook): - '''A hook implementation intended to count the number of CLI calls, and - track their result returns''' - - def __init__(self, *args, **kwargs): - - # always call the parent - super().__init__(*args, **kwargs) - - # create a local counter - self.counter = collections.Counter() - - # create a command return storage dictionary - self.returns = {} - - def enter(self, cmd, *args, **kwargs): - '''enter - - Track the command occurance (calls) by assuming execute() command's - first argument is the CLI command to run, and ignoring the rest of - the arguments - ''' - - # increment the counter - # (using this command as key) - self.counter[cmd] += 1 - - # store the current command for use in exit() - self.cmd = cmd - - def exit(self, retval): - '''exit - - store the return from the command call in another dictionary - ''' - - # the current command from enter() - cmd = self.cmd - - # current command occurance - index = self.counter[cmd] - - # because a command can be called multiple times, store each - # possible command using a dictionary with their counter as index - self.returns.setdefault(cmd, {}) - - # now store the return - self.returns[cmd][index] = retval - - def error_handle(self, e): - '''error_handle - - This dummy handler will just print the current exception and go into - pdb - that could be very useful! - - Note - ---- - for demonstration purpose only. - - NEVER do this in production :) you will BLOCK sanity/regression - automated runs. - ''' - - print(e) - print('-' * 80) - - # go into pdb - pdb.set_trace() - - # re-raise the exception - # (default behavior) - raise - - - # now that we've defined a hook implementation - # let's hook an actual device. - # ----------------------------------------------------------- - - # assuming we have a testbed from somewhere - from pyats.topology import loader - testbed = loader.load('/path/to/testbed.yaml') - - # get the device and connect to it - device = testbed.devices['my-device'] - device.connect() - - # use our hook and hook onto the execute() service - hook = Tracker(device, 'execute') - # note that device.execute is actually device.connections['default'].execute - # as per connection manager integration with device objects. - # thus it's actually more accurate to hook onto the connection itself - # eg: - # hook = Tracker(device.connections['default'], 'execute') - - # from here onwards, all calls to device.execute() will be tracked - device.execute('show version') - device.execute('show ip interface brief') - - # the returned hook instance can be used to check the hook returns & etc - hook.counter - hook.returns - - # to disable the hook behavior, call the restore() api. - hook.restore() - # this will restore the original functionality and disable the hook diff --git a/docs/connections/index.rst b/docs/connections/index.rst index 4d63dd4..7ee5b31 100644 --- a/docs/connections/index.rst +++ b/docs/connections/index.rst @@ -11,5 +11,5 @@ integrates into the pyATS topology model. integration manager class - hook + wrapper sharing \ No newline at end of file diff --git a/docs/connections/wrapper.rst b/docs/connections/wrapper.rst new file mode 100644 index 0000000..f5a152c --- /dev/null +++ b/docs/connections/wrapper.rst @@ -0,0 +1,375 @@ +.. _service_wrapper:: + +Service Wrapper +=============== + +The Service Wrapper is a class designed to wrap various methods of a Connection +object with pre, post, and exception handlers, adding extra functionality to +existing Connection methods. It allows users to extend and customize the +behavior of specific Connection methods without modifying the original +implementation. + +Here are some typical use cases of service wrappers: + + - tracking the sequence/occurance of CLI command calls throughout a script + + - debug-logging the input arguments to, and output values from particular + services. + + - building a LRU cache based on script inputs and device states. + + - etc. + + +Usage +----- + +To use the Service Wrapper, follow these steps: + +1) Create a child class derived from the `pyats.connections.ServiceWrapper` +class. This child class will serve as the Service Wrapper for the desired +Connection methods. + +2) Set the `conn_type` and `service_name` of the child class to the Connection +type and service name that the Service Wrapper will be applied to. This will +typically be `unicon.Connection` and the name of the service method, such as +`execute` or `configure`. The `order` class variable can also be set to +determine the order in which the Service Wrappers will be applied. + +3) Define the conditions under which the Service Wrapper should be applied to +the service using the `applicable` method. + +4) (Optional) Implement the necessary methods in the child class to define pre, +post, and exception handling behavior. These methods will be executed at +different stages during the service call. + +5) (Optional) Use Testcase `Steps` to provide more robust reporting and +leverage the pyATS reporter functionality. + +6) (Optional) Configure CLI parser arguments in the child class using the +`configure_parser` method. This is used to enable easy integration with CLI +interfaces. + +.. note:: + + Error handlers can suppress an exception, and/or track/register it + internally. By default the built-in error handler will simply raise the + current exception. Developer can modify that to suppress the current + exception being handled, and return a fixed/altered result. + + +Service Wrapper Class +--------------------- + +The Service Wrapper base class provides several methods that can be overwritten +by the user to customize the behavior of the service call: + +`call_service` +`````````````` + +This method is responsible for calling the wrapped service. By default, it calls + the service and passes any arguments that were provided to it. It returns the + output of the service call, which can be utilized in the `post_service` method. + If an error occurs, it calls the `exception_service` method. This method can + be completely overloaded to change the behavior of the service call. + +.. code-block:: python + + def call_service(self, *args, **kwargs) -> Any: + """Call the service three times""" + ret_list = [] + for _ in range(3): + try: + ret_list.append(self.service(*args, **kwargs)) + except Exception as e: + logger.exception(f"Exception occurred: {e}") + return ret_list + +`exception_service` +``````````````````` + +The `exception_service` method is called if an exception occurs during the +service call inside the `call_service` method. It is an abstracted method that +will only run if the child class implements it. It can return anything to be +used in the `post_service` method. + +.. code-block:: python + + def exception_service(self, e: Exception, *args, **kwargs) -> Any: + logger.exception(f"Exception occurred: {e}") + return f'Exception occurred: {e}' + +`pre_service` +````````````` + +The `pre_service` method is called before the `call_service` method is executed. + It is an abstracted method that will only run if the child class implements it. + This method allows performing any necessary actions or setup before the actual + service call. + +.. code-block:: python + + def pre_service(self, *args, **kwargs) -> None: + logger.info(f"Running pre_service on {self.service_name}") + logger.info(f"{self.service_name} args: {args} kwargs: {kwargs}") + +`post_service` +`````````````` + +The `post_service` method is called after the `call_service` method is executed. + It is an abstracted method that will only run if the child class implements it. + This method is used to handle any post-processing actions after the service + call. It receives the output of the `call_service` method as an argument. + +.. code-block:: python + + def post_service(self, output: Any, *args, **kwargs) -> None: + logger.info(f"Running post_service on {self.service_name}") + logger.info(f"{self.service_name} output: {output}") + +`configure_parser` +`````````````````` + +The `configure_parser` method is called when the Service Wrapper is loaded. It +is used to configure CLI parser arguments, similar to an easypy plugin. This is +a classmethod that requires definition from the implementor. It takes in a +`parser` argument, which is an instance of the `argparse.ArgumentParser` class. + +.. code-block:: python + + @classmethod + def configure_parser(cls, parser: argparse.ArgumentParser) -> None: + parser.add_argument( + '--service-wrapper-arg', + dest='service_wrapper_arg', + action='store_true', + help='Service Wrapper argument', + ) + + return parser + +`applicable` +```````````` + +The `applicable` class method is used to determine whether the Service Wrapper +should be applied to the service. This is also a classmethod that requires +definition from the implementor. It takes in a `connection` argument, which is +an instance of the `pyats.connections.BaseConnection` class. It should return a +boolean value: `True` if the Service Wrapper should be applied, and `False` +otherwise. + +This is in addition to the default `conn_type` and `service_name` checks that +are done. This allows for more fine-grained control over which services the +Service Wrapper is applied to. For example, the Service Wrapper can be applied +to a specific device type, or only when a certain argument is passed to the +service. + +.. code-block:: python + + # Override applicable to check if the device is an IOSXE device + @classmethod + def applicable(cls, connection: BaseConnection, *args, **kwargs) -> bool: + """Ensure the device OS is iosxe and the service wrapper argument is passed""" + return connection.device.os == 'iosxe' + +Important Attributes +```````````````````` + +The Service Wrapper base class also provides several attributes that can be used + in the Service Wrapper methods: + +- `self.service` + - The service method that the Service Wrapper is applied to + - Note that this should be exclusively used to call the wrapper services. + You **cannot** call `self.execute` for example as this does not exist. +- `self.connection` + - The Connection object that the Service Wrapper is applied to + - Note that caution should be taken when calling wrapped attributes on the + connection object. It's possible to create an infinite loop if the wrapped + attribute is also wrapped by the Service Wrapper. +- `self.device` + - The device object that the Connection object is connected to +- `self.logger` + - The logger object that can be used to log messages specific to the Service + Wrapper +- `self.testcase` + - The testcase object that can be used to access testcase data + - This is the same testcase object that is passed to easypy plugins and has + access to testcase data through `self.testcase.parameters` +- `self.args` + - The arguments as defined in the `configure_parser` method + +Class Variables +``````````````` + +In addition to the methods, the Service Wrapper base class also provides several + class variables that must be set to define which service the Service Wrapper + will be applied to: + +- `conn_type` + - The Connection type that the Service Wrapper will be applied to. Options + include + + .. code-block:: python + + # This is a catch-all for all Connection types + pyats.connections.BaseConnection + + # This is the standard unicon connection + unicon.Connection + + # Used for rest connections + rest.connector.Rest + + # Used for yang connections + yang.connector.Gnmi + yang.connector.Netconf + +- `service_name` + - The service the wrapper will be used on. This will be the name of the + service method, such as `execute` or `configure` + +- `order` + - This is an optional variable. It's is used to determine the order in which + the Service Wrappers will be applied. It is an integer value, with higher + values being applied first. The default value is `0`. + +Examples +-------- + +Execute Service Wrapper - IOSXE Device +`````````````````````````````````````` + +This is an example of a service wrapper for wrapping the execute service on an +IOSXE device + +.. note:: This example wrapper will run for ALL IOSXE devices when this wrapper + script is installed. If this wrapper is installed in a shared environment, + be aware that it affects all user jobs and any IOSXE devices in use. + +.. code-block:: python + + import unicon + from pyats.connections import ServiceWrapper + + class ExampleWrapper(ServiceWrapper): + conn_type = unicon.Connection + service_name = 'execute' + + @classmethod + def configure_parser(cls, parser) -> None: + parser.add_argument( + '--service-wrapper-arg', + dest='service_wrapper_arg', + action='store_true', + help='Service Wrapper argument', + ) + + return parser + + @classmethod + def applicable(cls, connection, *args, **kwargs) -> bool: + return connection.device.os == 'iosxe' + + def pre_service(self, *args, **kwargs) -> None: + self.logger.info(f"Running command: {args[0]} on {self.device.name}") + + def post_service(self, output, *args, **kwargs) -> None: + self.logger.info(f"Output: {output}") + + def call_service(self, *args, **kwargs) -> Any: + try: + self.logger.info(f"Calling service: {self.service_name}") + return self.service(*args, **kwargs) + except Exception as e: + return self.exception_service(e, *args, **kwargs) + + def exception_service(self, e, *args, **kwargs): + self.logger.exception(f"Exception occurred: {e}") + return f'Exception occurred: {e}' + +Steps +----- + +Inside of each service wrapper method you are able to pass a `steps` argument +that will automatically pick up the Testcase's current `steps` object, which +allows for use of the context manager style of reporting, failing, and passing +a test. + +.. code-block:: python + + with steps.start() as step: + step.passed('Passed') + +This can be used in any of the four service wrapper methods. + +.. code-block:: python + + from pyats.connections import ServiceWrapper + + class ExampleWrapper(ServiceWrapper): + @classmethod + def applicable(cls, connection, *args, **kwargs) -> bool: + return True + + def pre_service(self, steps, *args, **kwargs) -> None: + with steps.start('Pre Service Step') as step: + step.passed('Sucessfully ran pre service step') + + def post_service(self, output, steps, *args, **kwargs) -> None: + with steps.start('Post Service Step') as step: + step.passed('Sucessfully ran post service step') + + def call_service(self, steps, *args, **kwargs) -> None: + with steps.start('Call Service Step') as step: + step.passed('Sucessfully ran call service step') + + def exception_service(self, e, steps, *args, **kwargs) -> None: + with steps.start('Exception Service Step') as step: + step.passed('Sucessfully ran exception service step') + +.. note:: The `steps` argument is only filled when the service wrapper is run in + the context of a Testcase. If no Testcase is found, the `steps` argument + will be `None`. Keep this in mind if your service wrapper is used in a + standalone context with no Testcase. + +Discovery +--------- + +There are two methods to enable pyATS to discover service wrappers. The first +method is to configure the service wrapper in the pyats configuration file. The +second method is to use an entry point. + +Configuration Method +```````````````````` + +Once the service wrapper is created, you can utilize it by adding it to the +pyats configuration file. You can read up on how to configure that +:ref:`here. ` + +.. code-block:: ini + + [service_wrapper] + example_wrapper = path.to.module:ExampleWrapper + +Entrypoint Method +````````````````` + +Additionally, you can utilize it by adding it as an entry +point in your package's setup file through the `pyats.connections.wrapper` +entry point descriptor. This enables the service wrapper to be called and +employed within the context of your package, facilitating seamless integration +and utilization of the wrapped functionalities. + +.. code-block:: python + + setup( + ..., + + # console entry point + entry_points = { + 'pyats.connections.wrapper': [ + 'example_wrapper = path.to.path:ExampleWrapper' + ] + } + ) \ No newline at end of file diff --git a/docs/easypy/email.rst b/docs/easypy/email.rst index 940dda0..6686f75 100644 --- a/docs/easypy/email.rst +++ b/docs/easypy/email.rst @@ -51,7 +51,20 @@ The following describes the default email report content. Note that fields in TOTAL : {runtime.job.results[total]} - Success Rate : {runtime.job.results[success_rate]:.02f} % + Success Rate : {runtime.job.results[success_rate]:.02f} + + Section Stats + Passed : {runtime.job.section_results[passed]} + Passx : {runtime.job.section_results[passx]} + Failed : {runtime.job.section_results[failed]} + Aborted : {runtime.job.section_results[aborted]} + Blocked : {runtime.job.section_results[blocked]} + Skipped : {runtime.job.section_results[skipped]} + Errored : {runtime.job.section_results[errored]} + + TOTAL : {runtime.job.section_results[total]} + + Section Success Rate : {runtime.job.section_results[success_rate]:.02f} +------------------------------------------------------------------------------+ | Task Result Summary | @@ -91,6 +104,24 @@ host, update the following fields in pyATS :ref:`pyats_configuration`'s Report Customization -------------------- +The email and job summary report includes Overall Stats which is based on the +count of CommonSetup, CommonCleanup, Testcase, Trigger and Verification +classes defined in test scripts. The report also includes Section Stats that +summarize SubSection, SetupSection, CleanupSection and TestSection stats. + +The section reporting can be changed by updating the `report.sections` +configuration to define which sections should be counted for reporting purposes. + +For example, to include only TestSections (decorated with `@aetest.test`), Setup +(`aetest.setup`) and Cleanup (`@aetest.cleanup`) sections, set `report.sections` +as below. The values for the sections are space separated. + +.. code-block:: ini + + # report configuration + [report] + sections = TestSection SetupSection CleanupSection + Easypy email notification reports are fully customizable, allowing users to attach custom information to the email report body. @@ -248,8 +279,42 @@ at any time prior to calling the send() method. - **to_email**: A list or tuple of recipient addresses. - **subject**: The subject line of the email. - **body**: The body text. This should be a plain text message. - - **attachments**: A list of attachments to put on the message. These can be - either email.MIMEBase.MIMEBase instances, or (filename, content, mimetype) - triples - currently only supports MIMEText. + - **attachments**: A list of attachments to put on the message. Currently only supports MIMEText. - **html_email**: flag to enable alternative HTML email format. - **html_body**: Body in HTML format. + +.. code-block:: python + + # Example + # ------- + # + # Sending email from pyATS + + # import EmailMsg class + from pyats.utils.email import EmailMsg + + # Create email message object + mail = EmailMsg( + from_email=email_from_address, + to_email=email_to_address, + subject=email_subject, + body=email_body) + + # send email + mail.send() + + # If you want to send HTML email: + mail = EmailMsg( + from_email=email_from_address, + to_email=email_to_address, + subject=email_subject, + html_email=True, + html_body=html_body) + + # You can also add attachments: + mail = EmailMsg( + from_email=email_from_address, + to_email=email_to_address, + subject=email_subject, + body=email_body, + attachments=['/path/to/file']) diff --git a/docs/easypy/jobfile.rst b/docs/easypy/jobfile.rst index 53c6670..857fcb3 100644 --- a/docs/easypy/jobfile.rst +++ b/docs/easypy/jobfile.rst @@ -242,18 +242,24 @@ Task Class ``Task`` class objects represent the task/testscript being executed in a child process. It is a subclass of Python ``multiprocessing.Process`` class, and -always uses ``multiproessing.get_context('fork')`` to fork and create child -processes. +always uses ``multiprocessing.get_context('fork')`` to fork and create child +processes. The ``gTask`` class object is used for Genie Tasks. .. csv-table:: Task Class Arguments :header: "Argument", "Description" ``testscript``, "testscript to be run in this task" - ``taskid``, "unique task id (defaults to ``Task-#`` where # is an - incrementing number)" + ``taskid``, "unique task id (defaults to ``Task-#`` where # is an incrementing number)" ``runtime``, "easypy runtime object" - ``kwargs``, "any other keyword-arguments to be passed to the testscript - as script parameters" + ``clean_files``, "List of clean files, specific to this task (optional)" + ``logical_testbed_file``, "Path to logical testbed file, specific to this task (optional)" + ``kwargs``, "any other keyword-arguments to be passed to the testscript as script parameters" + +For Genie tasks, the `gTask` class can be used. No testscript should be specified for Genie tasks. + +The ``clean_files`` and ``logical_testbed_File`` arguments are optional arguments +that can be passed if the task uses task specific clean. By default, the job level +clean arguments are used. Like its parent ``Process`` class, instantiating a ``Task`` object does not create the actual child process: the class constructor only sets internal states @@ -350,6 +356,32 @@ each task process. # raise exception raise TimeoutError('Not all tasks finished in 5 minutes!') +Example for Genie tasks with gTask. The ``gTask`` class is imported from the `genie.harness.main` module. + +.. code-block:: python + + # Example + # ------- + # + # job file tasks using gTask() api + + from genie.harness.main import gTask + + def main(runtime): + + # using Task class to create a task object + task_1 = gTask(trigger_datafile='trigger_data.yaml', + config_datafile='config_data.yaml', + subsection_datafile='subsection_data.yaml', + trigger_uids='TestBgp', + taskid='task1') + + # start the task + task_1.start() + + # wait for a max runtime of 60*5 seconds = 5 minutes + task_1.wait(60*5) + Easypy expects all tasks to be finished/terminated when ``main()`` scope is exited (eg, the jobfile finished execution). Therefore, all tasks created and started using ``Task`` class should always be waited for using ``wait()``, and diff --git a/docs/index.rst b/docs/index.rst index 543a8e6..43569cc 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -23,6 +23,7 @@ studies and more. :maxdepth: 1 :caption: Main Components + aereport/index aetest/index easypy/index topology/index diff --git a/docs/manifest/introduction.rst b/docs/manifest/introduction.rst index a4706d6..053070c 100644 --- a/docs/manifest/introduction.rst +++ b/docs/manifest/introduction.rst @@ -48,7 +48,7 @@ the manifest. Currently, the supported types for the manifest are: * easypy -Only suported script types have an execution runtime that allows +Only supported script types have an execution runtime that allows the manifest to execute the script. @@ -80,11 +80,13 @@ The internal argument structure is translated to the command line argument strin * Arguments may explicitly define dash syntax, e.g `"-key": value` * Argument values are quoted using double quotes, e.g. `val1` will translate to `"val1"` * Arguments specified as a list will translate to `--key "val1" "val2"` - * If the value is `*N`, repeat the argument key N number of times + * If the value is `*N`, repeat the argument key N number of times (e.g. `"-v": "*3"` translates to `-v -v -v`) * If the value is a boolean, leave out the value and only add - the key to the argument string, e.g. `flag: True` translates to `--flag`. - * If the boolean needs to be explicitly added to the argument string, the value - must be explicitly specified as a string, e.g. `key: "True"` + the key to the argument string, e.g. `flag: True` translates to `--flag`. Note: + if the boolean needs to be explicitly added to the argument string, the value + must be explicitly specified as a string, e.g. `key: "True"` (not as a boolean value). + See below for overriding boolean arguments. + * If the `meta` argument is used on the command line, it will be prepended as an additional meta argument. For example, the script arguments defined in the manifest could look like this: @@ -110,6 +112,46 @@ For example running the manifest execution with the above arguments and adding t $ pyats validate manifest job.tem --profile local --testbed-file testbed2.yaml +**Meta argument handling** + +If the `meta` argument is used on the command line, it will be prepended +as an additional meta argument. Note, the value for the `meta` argument provided +via a *profile* argument will override the default value (same as for any other argument). + +.. code-block:: yaml + + arguments: + meta: key1=value1 + +.. code-block:: + + $ pyats validate manifest job.tem --meta key2=value2 + +The above will result in the following command line arguments to be used: + +.. code-block:: + + pyats run job job.py --meta key2=value2 --meta key1=value1 + + +**Overriding boolean arguments** + +You can override boolean arguments by specifying the boolean string value after the argument +on the command line, i.e. `"False"` or `"True"`. + +With below example, the ``no-mail: True`` argument specified in the manifest can be overriden +by specifying the argument on the manifest command line with value `False`. This combination +will result in the `--no-mail` argument *not* to be added to the `pyats run job` command. + +.. code-block:: yaml + + arguments: + no-mail: True + +.. code-block:: shell + + $ pyats validate manifest job.tem --no-mail False + runtimes ~~~~~~~~ diff --git a/docs/topology/creation.rst b/docs/topology/creation.rst index 61ada47..201ded3 100644 --- a/docs/topology/creation.rst +++ b/docs/topology/creation.rst @@ -94,216 +94,8 @@ unanimous for all. Testbed File Markups -------------------- -Another advantage of using testbed files is to leverage the built-in markup -feature. Whereas standard YAML format does not allow variable substitution and -references, ``topology.loader`` effectively added this using specific syntax -(markups) similar to the Django template language. +See :ref:`yaml_file_markup` -.. code-block:: text - - # Syntax - # ------ - # - # YAML markup syntax - - # basic syntax - # ------------ - # %{..<...>} - # %INTF{logical_interface_name} - # %ENV{environment_variable_name} - # %CALLABLE{path_to_callable} - # %CALLABLE{path_to_callable(param1,param2,param3)} - # %INCLUDE{yaml_file_path} - # %ASK{optional prompt text} - # %ENC{encoded text} - # %ENC{encoded text, prefix=x} - # %CLI{cli_argument_name} - # - # - use %{ } to denote the begin and end of a markup block - # - use . to separate reference path - # - use 'self' as first word to reference current device - # - The %INTF{ } form causes the logical interface name to be - # replaced with the actual interface name from the - # device's topology block. - # - The %ENV{ } form causes the environment variable name to be - # replaced with the actual environment value from the os. - # - The %CALLABLE{ } form causes the callable to be replaced with the - # actual return value from the callable. All defined parameters - # will be passed to the callable. - # - The %INCLUDE{ } form causes the yaml file path to be replaced - # with the actual content of the yaml file. - # - The %ASK{ } form causes the user to be prompted to enter information - # manually. - # - The %ENC{ } form causes an encoded string to be replaced with a - # decoded string or secret string which supports decoding. - # - The %CLI{ } form replaces the variable name with the value provided - # from the command line argument. If no command line argument was - # provided for this variable, the value will be an empty string. - # Supports single and double dash argument style. - - # reference to current device name - %{self} - - # reference to attributes within current device - %{self.x.y.z} - - # reference to logical interface within current device - # (replaced with actual interface name) - %INTF{logical_interface_name} - - # reference to arbitrary attribute within this YAML file - %{a.b.c} - - # reference to environment variable from the os - # (replaced with actual environment variable name) - %ENV{environment_variable_name} - - # reference to callable without parameter - # (replaced with actual path to callable) - %CALLABLE{path.to.callable} - - # reference to callable with parameters param1, param2 and param3 - # (replaced with actual path to callable) - %CALLABLE{path.to.callable(param1,param2,param3)} - - # reference to content from other YAML file - # (replaced with actual path to YAML file) - %INCLUDE{yaml_file_path} - - # prompt user to enter string content manually - %ASK{optional prompt text} - - # Reference to text encoded with "pyats secret encode" command - # Encoded credential passwords are substituted by secret strings. - # Other encoded references are substituted with their decoded string. - # See secret strings documentation for details. - %ENC{} - - # Reference to text encoded with "pyats secret encode --prefix x" command. - # Encoded credential passwords are substituted by secret strings. - # Other encoded references are substituted with their decoded string. - # See secret strings documentation for details. - %ENC{, prefix=x} - - # Reference to "some_arg" will be replaced by "some_value" if - # the command line "pyats run job --some_arg some_value" is used. - %CLI{some_arg} - - # If the command line argument is provided without a value, - # the value is set to boolean 'True'. The following command line - # sets the value for "some_flag" to True. - # "pyats run job --some_flag" - %CLI{some_flag} - - # If the command line argument has multiple values, - # the variable is replaced with a list of values. - # The following command line argument creates a list - # of values in place of the devices variable. - # "pyats run job --devices R1 R2" - %CLI{devices} - - # If the command line argument contains a number value, - # either integer or float, the variable is converted from - # a string to an integer or float. - # "pyats run job --retries 3" - %CLI{retries} - -.. note:: - - Make sure to enclose your markup in quotes if it occurs directly - after a colon. For example:: - - testbed: - name: my_testbed - - passwords: - enable: lab - line: "%{testbed.passwords.enable}" - tacacs: "%{testbed.passwords.enable}" - tacacs: - username: admin - -YAML itself does not distinguish the markups from regular text (strings). -Before the creation of testbed objects, the loader walks through the generated -data and replaces all markup languages with referenced data. -Any syntax outside of the above is neither recognized nor processed. - -.. code-block:: yaml - - # Example - # ------- - # - # yaml testbed using markup - # notice how markups were used as information references. - devices: - example_device: - type: "%CALLABLE{mylib.get_device_type}" - connections: - a: - protocol: telnet - ip: "1.1.1.1" - port: 2001 - alt: - protocol: telnet - ip: "%{self.clean.mgt_itf.ipv4.address}" - - dynamic_device: "%CALLABLE{mylib.create_device(2.2.2.2)}" - topology: - example_device: - interfaces: - Ethernet4/6: - alias: my_logical_interface - link: link-x - type: "%ENV{DEFAULT_INTERFACE_TYPE}" - dynamic_device: "%INCLUDE{/path/to/dynamic/generated/device/interfaces/file}" - - -Testbed file can be broken down in multiple yaml files with the extend key. -Each file can represent a subset of the main testbed file. - - -Let's say this file is named tb1.yaml - -.. code-block:: yaml - - devices: - xr-1: - connections: - cli: - ip: 10.1.1.1 - protocol: ssh - credentials: - default: - password: cisco - username: cisco - enable: - password: cisco - os: iosxr - type: iosxr - - -And this file is named tb2.yaml - -.. code-block:: yaml - - extends: tb1.yaml - devices: - xr-2: - connections: - cli: - ip: 10.2.2.2 - protocol: ssh - credentials: - default: - password: cisco - username: cisco - enable: - password: cisco - os: iosxr - type: iosxr - -Now at run time, you can provide the tb2.yaml, which will merge tb1.yaml and -tb2.yaml together to create a merged testbed. Manual Creation --------------- diff --git a/docs/topology/schema.rst b/docs/topology/schema.rst index f531722..ad3ef6f 100644 --- a/docs/topology/schema.rst +++ b/docs/topology/schema.rst @@ -220,8 +220,8 @@ Production YAML Schema peripherals: # device hardware block # may contain anything describing peripherals - # connected to the device. - # currently supported devices are terminal servers + # connected to the device. + # currently supported devices are terminal servers # and power cyclers. # (optional) @@ -273,6 +273,9 @@ Production YAML Schema # (default: None - let the connection class decide) # (optional) + fallback_credentials: # list of the fallback credentials to be used for + # the connections in the testbed.(optional) + connections: # a list of subconnections for a multi-console # device. # Supported by unicon connector implementation. @@ -311,6 +314,9 @@ Production YAML Schema port: # port to connect to # (optional) + fallback_credentials: # list of the fallback credentials for this + # connection.(optional) + credentials: # credential details specific to this connection # (optional) diff --git a/docs/utilities/index.rst b/docs/utilities/index.rst index 895bd42..eeacdd2 100644 --- a/docs/utilities/index.rst +++ b/docs/utilities/index.rst @@ -11,5 +11,6 @@ Utilities file_transfer_utilities file_transfer_server import_utils + yaml_markup .. sectionauthor:: Myles Dear diff --git a/docs/utilities/yaml_markup.rst b/docs/utilities/yaml_markup.rst new file mode 100644 index 0000000..d2178c5 --- /dev/null +++ b/docs/utilities/yaml_markup.rst @@ -0,0 +1,366 @@ + +.. _yaml_file_markup: + +YAML File Markups +================= + +The pyATS YAML loader, which is used in several places including the testbed +loader, supports pyATS specific YAML markup. + +Whereas standard YAML format does not allow variable substitution and +references, ``pyats.utils.yaml.Loader`` effectively added this using specific +syntax (markups) similar to the Django template language. + +Reference +--------- + +.. code-block:: text + + # Syntax + # ------ + # + # YAML markup syntax + + # basic syntax + # ------------ + # %{..<...>} + # %{..<...>.keys()} + # %INTF{logical_interface_name} + # %ENV{environment_variable_name} + # %CALLABLE{path_to_callable} + # %CALLABLE{path_to_callable(param1,param2,param3)} + # %CALLABLE{path_to_callable(param1='val1',param2='val2')} + # %INCLUDE{yaml_file_path} + # %ASK{optional prompt text} + # %ENC{encoded text} + # %ENC{encoded text, prefix=x} + # %CLI{cli_argument_name} + # %CLI{another_cli_arg, default=} + # %CLI{another_list, default=[,]} + # %EXTEND_LIST{key} + # %EXTEND_LIST{path.to.value1,path.to.value2} + # + # - use %{ } to denote the begin and end of a markup block + # - use . to separate reference path + # - use 'self' as first word to reference current device + # - use '.keys()' to get the key values for a path + # - The %INTF{ } form causes the logical interface name to be + # replaced with the actual interface name from the + # device's topology block. + # - The %ENV{ } form causes the environment variable name to be + # replaced with the actual environment value from the os. + # - The %CALLABLE{ } form causes the callable to be replaced with the + # actual return value from the callable. All defined parameters + # will be passed to the callable. + # - The %INCLUDE{ } form causes the yaml file path to be replaced + # with the actual content of the yaml file. + # - The %ASK{ } form causes the user to be prompted to enter information + # manually. + # - The %ENC{ } form causes an encoded string to be replaced with a + # decoded string or secret string which supports decoding. + # - The %CLI{ } form replaces the variable name with the value provided + # from the command line argument. If no command line argument was + # provided for this variable, the value will be an empty string. + # Supports single and double dash argument style. A default value + # can be specified using `, default=` syntax. A list can be specified + # as default value. + # - The %EXTEND_LIST{ } form can be used for keys to extend a list + # from another YAML file. The same syntax can also be used to create + # a value by extending one or more list references. + + +Markup Examples +--------------- + +.. code-block:: text + + # reference to current device name + %{self} + + # reference to attributes within current device + %{self.x.y.z} + + # reference to logical interface within current device + # (replaced with actual interface name) + %INTF{logical_interface_name} + + # reference to arbitrary attribute within this YAML file + %{a.b.c} + + # reference to the list of keys of this attribute within this YAML file + %{d.e.keys()} + + # reference to environment variable from the os + # (replaced with actual environment variable name) + %ENV{environment_variable_name} + + # reference to callable without parameter + # (replaced with actual path to callable) + %CALLABLE{path.to.callable} + + # reference to callable with parameters param1, param2 and param3 + # (replaced with actual path to callable) + %CALLABLE{path.to.callable(param1,param2,param3)} + + # reference to callable with paramter param1 and + # kwarg style parameter param2 + %CALLABLE{path.to.callable(param1, param2='val1')} + + # reference to content from other YAML file + # (replaced with actual path to YAML file) + %INCLUDE{yaml_file_path} + + # prompt user to enter string content manually + %ASK{optional prompt text} + + # Reference to text encoded with "pyats secret encode" command + # Encoded credential passwords are substituted by secret strings. + # Other encoded references are substituted with their decoded string. + # See secret strings documentation for details. + %ENC{} + + # Reference to text encoded with "pyats secret encode --prefix x" command. + # Encoded credential passwords are substituted by secret strings. + # Other encoded references are substituted with their decoded string. + # See secret strings documentation for details. + %ENC{, prefix=x} + + # Reference to "some_arg" will be replaced by "some_value" if + # the command line "pyats run job --some_arg some_value" is used. + %CLI{some_arg} + + # If the command line argument is provided without a value, + # the value is set to boolean 'True'. The following command line + # sets the value for "some_flag" to True. + # "pyats run job --some_flag" + %CLI{some_flag} + + # If the command line argument has multiple values, + # the variable is replaced with a list of values. + # The following command line argument creates a list + # of values in place of the devices variable. + # "pyats run job --devices R1 R2" + %CLI{devices} + + # If the command line argument contains a number value, + # either integer or float, the variable is converted from + # a string to an integer or float. + # "pyats run job --retries 3" + %CLI{retries} + + # A default value can be specified for the %CLI markup. + %CLI{another_flag, default=12} + + # A default value can be a list + %CLI{another_flag, default=[1,2]} + +.. note:: + + Make sure to enclose your markup in quotes if it occurs directly + after a colon. For example:: + + testbed: + name: my_testbed + + passwords: + enable: lab + line: "%{testbed.passwords.enable}" + tacacs: "%{testbed.passwords.enable}" + tacacs: + username: admin +.. note:: + + Make sure to enclose strings with % sign in quotes + in the yaml file. For example:: + + testbed: + name: my_testbed + + credentials: + password: "%ASK{Your password}" + +YAML itself does not distinguish the markups from regular text (strings). +Before the creation of testbed objects, the loader walks through the generated +data and replaces all markup languages with referenced data. +Any syntax outside of the above is neither recognized nor processed. + + +Testbed YAML Examples +--------------------- + +.. code-block:: yaml + + # Example + # ------- + # + # yaml testbed using markup + # notice how markups were used as information references. + devices: + example_device: + type: "%CALLABLE{mylib.get_device_type}" + connections: + a: + protocol: telnet + ip: "1.1.1.1" + port: 2001 + alt: + protocol: telnet + ip: "%{self.clean.mgt_itf.ipv4.address}" + + dynamic_device: "%CALLABLE{mylib.create_device(2.2.2.2)}" + topology: + example_device: + interfaces: + Ethernet4/6: + alias: my_logical_interface + link: link-x + type: "%ENV{DEFAULT_INTERFACE_TYPE}" + dynamic_device: "%INCLUDE{/path/to/dynamic/generated/device/interfaces/file}" + + +Testbed file can be broken down in multiple yaml files with the extend key. +Each file can represent a subset of the main testbed file. + + +Let's say this file is named tb1.yaml + +.. code-block:: yaml + + devices: + xr-1: + connections: + cli: + ip: 10.1.1.1 + protocol: ssh + credentials: + default: + password: cisco + username: cisco + enable: + password: cisco + os: iosxr + type: iosxr + + +And this file is named tb2.yaml + +.. code-block:: yaml + + extends: tb1.yaml + devices: + xr-2: + connections: + cli: + ip: 10.2.2.2 + protocol: ssh + credentials: + default: + password: cisco + username: cisco + enable: + password: cisco + os: iosxr + type: iosxr + +Now at run time, you can provide the tb2.yaml, which will merge tb1.yaml and +tb2.yaml together to create a merged testbed. + +EXTEND_LIST usage examples +-------------------------- + +`%EXTEND_LIST` markup can be used in two ways: as a key markup or as a value markup. + +1. Example EXTEND_LIST usage for key markup. + +Example YAML file to be extended: + +.. code-block:: yaml + + parameters: + sections: [a, b] + +YAML file extending the file above: + +.. code-block:: yaml + + extends: a.yaml + + parameters: + "%EXTEND_LIST{sections}": [c] + +Example code loading an extended YAML file: + +.. code-block:: python + + from pyats.utils.yaml import Loader + loader = Loader(enable_extensions=True) + data = loader.load('b.yaml') + print(data) + +The output from above script is show below. As you can see, +the list data was extended from [a, b] to [a, b, c]. + +.. code-block:: text + + {'parameters': {'sections': ['a', 'b', 'c']}} + + +2. Example EXTEND_LIST usage for values. + +It's also possible to created a list from one or more other lists using +the EXTEND_LIST markup with one or more references to list values. + +.. code-block:: yaml + + parameters: + base_config: + CE1: + bgp: + address_families: + ipv4: + neighbors: + 1.1.1.1: {} + 1.1.1.2: {} + ipv6: + neighbors: + - 1::1 + - 1::2 + + CE1_neighbors: "%EXTEND_LIST{parameters.base_config.CE1.bgp.address_families.ipv4.neighbors.keys(),parameters.base_config.CE1.bgp.address_families.ipv6.neighbors}" + + +The output from above data after loading is shown below. The single lists of +neighbors is created by combining the two lists using their markup reference. + +.. code-block:: text + + { + "parameters": { + "base_config": { + "CE1": { + "bgp": { + "address_families": { + "ipv4": { + "neighbors": { + "1.1.1.1": {}, + "1.1.1.2": {} + } + }, + "ipv6": { + "neighbors": [ + "1::1", + "1::2" + ] + } + } + } + } + }, + "CE1_neighbors": [ + "1.1.1.1", + "1.1.1.2", + "1::1", + "1::2" + ] + } + }