Using Easypy¶
Easypy comes with its own command line entrypoint: pyats run job
.
It is part of the overall pyATS Command Line Interface
that gets installed into your pyATS instance automatically.
Note
prior to pyATS v5.1, the CLI command for Easypy was actually easypy
, and
used single dash -
arguments instead.
Starting pyATS v5.1 forward, it has been replaced by pyats run job
command in favor of POSIX-style arguments. The old command is deprecated,
but not removed for backwards compatbility purposes.
# activate your pyats instance, eg:
[tony@jarvis:~]$ cd /ws/tony-stark/pyats
[tony@jarvis:pyats]$ source env.sh
Activating the pyATS instance @ /ws/tony-stark/pyats
--------------------------------------------------------------------
PYTHONPATH=/ws/tony-stark/pyats:
LD_LIBRARY_PATH=/usr/X11R6/lib
--------------------------------------------------------------------
# easypy is now part of your path
(pyats) [tony@jarvis:pyats]$ which pyats
/ws/tony-stark/pyats/bin/pyats
pyats run job
comes natively with built-in help information:
[tony@jarvis:~]$ pyats run job --help
Usage:
pyats run job [file] [options]
Example
-------
pyats run job /path/to/jobfile.py
pyats run job /path/to/jobfile.py --testbed-file /path/to/testbed.yaml
Description:
Runs a pyATS job file with the provided arguments, generating & report result.
Configuration:
-C, --configuration FILE
easypy configuration yaml file for plugins
Job Information:
JOBFILE target jobfile to be launched
--job-uid Unique ID identifiying this job run
--pyats-configuration
pyats configuration override file
Tasks:
--task-uids LOGIC Logic string to match task UIDs to run eg: "Or('Task-[12]')"
Mailing:
--no-mail disable report email notifications
--mail-to list of report email recipients
--mail-subject report email subject header
--mail-html enable html format report email
Reporting:
--submitter Specify the current submitter user id
--image Specify the image under test
--release Specify the release being tested
--branch Specify the branch being tested
--meta Specify some meta information as a dict (supports base64 encoded strings)
--no-xml-report Disable generation of the XML Report
Runinfo:
--no-archive disable archive creation
--no-archive-subdir disable archive subdirectory creation
--runinfo-dir specify alternate runinfo directory
--archive-dir specify alternate archive directory
--archive-name specify alternate archive file name
Liveview:
--liveview Starts a liveview server in a separate process
--liveview-host HOST Specify host for liveview server. Default is localhost
--liveview-port PORT Specify port for liveview server.
--liveview-hostname HOSTNAME
Displayed hostname for liveview.
--liveview-displayed-url LIVEVIEW_DISPLAYED_URL
Displayed url for liveview, for example, http://<liveview_hostname>:<port>
--liveview-keepalive Keep log viewer server alive after the run finishes.
--liveview-callback-url LIVEVIEW_CALLBACK_URL
Specify xpresso callback url for jenkins run.
--liveview-callback-token LIVEVIEW_CALLBACK_TOKEN
Specify xpresso token for jenkins run.
Testbed:
-t, --testbed-file Specify testbed file location
Clean:
--clean-file FILE [FILE ...]
Specify clean file location(s). Multiple clean files can be specified by
separating them with spaces.
--clean-devices [ [ ...]]
Specify list of devices to clean, separated by spaces. To clean groups of
devices sequentially, specify as "[[dev1, dev2], dev3]".
--clean-scope {job,task}
Specify whether clean runs before job or per task
--invoke-clean Clean is only invoked if this parameter is specified.
--clean-device-image space separated images per device with format device:/path/to/image.bin
--clean-os-image space separated images per OS with format os:/path/to/image.bin
--clean-group-image space separated images per group with format group:/path/to/image.bin
--clean-platform-image space separated images per platform with format platform:/path/to/image.bin
--clean-image-json dictionary of clean images in JSON string (supports base64 encoded strings)
Bringup:
--logical-testbed-file
Specify logical testbed file location
Rerun:
--rerun-file FILE rerun.results file that contains the information of tasks and testcases
--rerun-task [ ...] TASKID TESTSCRIPT [TESTCASES...] Details to identify a specific Task to
rerun. Can be used multiple times for multiple tasks.
--rerun-condition [ ...]
Results type list for the condition of rerun plugin.
xUnit:
--xunit [DIR] Generate xunit report in the provided location. If used as a flag, generates
xunit reports runtime directory
HTML Logging:
--html-logs [DIR] Directory to generate HTML logs in addition to any existing log files. Note
- will increase archive size due to log duplication.
General Options:
-h, --help Show help information
-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
Standard Arguments¶
pyats run job
accepts a number of standard arguments that can be used to
influence and/or change jobfile execution behaviors. All arguments are
constructed and processed using python argparse module. Please also see
Easypy Return Codes.
Argument |
Description |
---|---|
|
positional argument, full path/name of Jobfiles to run. |
|
configuration yaml file for plugins |
|
additional pyats configuration for execution |
|
unique id from upper systems identifying this run |
|
Logic string with Task UID filter |
|
full path/URL for YAML testbed file |
|
file path/URL to file containing Clean File information |
|
a list of devices to clean |
|
whether to perform clean/bringup at job or task level |
|
Clean is only invoked when this parameter is specified. |
|
space separated images per device with format device:/path/to/image.bin |
|
space separated images per OS with format os:/path/to/image.bin |
|
space separated images per group with format group:/path/to/image.bin |
|
space separated images per platform with format platform:/path/to/image.bin |
|
dictionary of clean images in JSON string. Can be base64 encoded. |
|
specify a run submitter (defaults to current user) |
|
enable generating HTML logs |
|
specify the current test image information |
|
specify the current release string information |
|
specify the current branch information |
|
A JSON dict of additional user information about this execution. Can be base64 encoded. |
|
specify a different name for the generated archive file. |
|
flag, disables the creation of a log archive |
|
flag, disables the creation of date-specific archive subdirectory. |
|
flag, disables email notification at the end of run |
|
specify the list of email notification recipients. |
|
email notification subject line. |
|
flag, enables HTML format email notification. |
|
specify alternative runtime info directory location |
|
specify alternative archive storage directory location |
|
flag, enables x-unit style report generation |
|
generate more or less log output |
Important
jobfile
is a positional argument, and must be provided first before
all other arguments.
Tip
pyats run job
standardizes on POSIX Style CLI arguments.
-h, --help
Prints help information and how to use each arguments.
bash$ pyats run job --help
jobfile
Mandatory positional argument. Specifies the full path/name to the Jobfiles to run.
bash$ pyats run job /path/to/jobfile.py
-C, --configuration
optional argument, used to provide the YAML plugin configuration file. Use this if you want to configure your Easypy to run certain plugins in custom orders for this particular run. Can be a file path or URL. URL with token can be given like below example.
bash$ pyats run job /path/to/jobfile.py --configuration /path/to/config.yaml bash$ pyats run job /path/to/jobfile.py --configuration "http://<url>/config.yaml" bash$ pyats run job /path/to/jobfile.py --configuration "http://<token>@<url>/config.yaml"
--job-uid
optional argument. Allows upstream executor (eg, Jenkins) to pass down a unique identifier string to be stored in report.
bash$ pyats run job /path/to/jobfile.py --job-uid "this_is_an_example"
--pyats-configuration
optional argument. Additional file to add to Configuration.
bash$ pyats run job /path/to/jobfile.py --pyats-configuration /path/to/my/pyats.conf
--task-uids
Logic string to filter which tasks will be run. See Logic String Inputs.
# filter tasks to run, run only task "Task-1" bash$ pyats run job job.py --task-uids "Or('Task-1$')" # filter tasks to run, run task "task1" and "task3" bash$ pyats run job job.py --task-uids "Or('task[13]$')"
--testbed-file
Specifies the full path/name or URL of YAML topology URL with token can be given like below example. Testbed File to be loaded as part of this run. When used, Easypy automatically loads the testbed yaml file into a topology Testbed Object, and passes it to each task inside the jobfiles as its
testbed
parameter. Refer to testbed for more details.Alternatively, you can specify a source to be loaded with the testbed creator package. To do so, append ‘source:’ in front of the desired loader name and specify any required arguments in CLI form. Refer to pyats.contrib for more details.
bash$ pyats run job /path/to/jobfile.py --testbed-file /path/to/mytestbed.yaml bash$ pyats run job /path/to/jobfile.py --testbed-file source:netbox --netbox-token=token --netbox-url=url bash$ pyats run job /path/to/jobfile.py --testbed-file "http://<url>/testbed.yaml" bash$ pyats run job /path/to/jobfile.py --testbed-file "http://<token>@<url>/testbed.yaml"
--clean-file
Full path or URL to the clean file. This enables testbed cleaning using the kleenex module. This option is only useable if testbed information is provided using
--testbed-file
argument. URL with token can be given like below example.bash$ pyats run job jobfile.py --testbed-file /path/to/mytestbed.yaml\ --clean-file /path/to/clean.yaml --invoke-clean bash$ pyats run job jobfile.py --testbed-file "http://<url>/testbed.yaml"\ --clean-file "http://<url>/clean.yaml" --invoke-clean bash$ pyats run job jobfile.py --testbed-file "http://<token>@<url>/testbed.yaml"\ --clean-file "http://<token>@<url>/clean.yaml" --invoke-clean
--clean-devices
Specifies the list of devices to clean. If not specified, defaults to cleaning all devices specified in the clean file that are also present in the testbed file.
bash$ pyats run job jobfile.py --testbed-file /path/to/my/testbed.yaml\ --clean-file /path/to/my/clean.yaml\ --clean-devices device_a device_b device_c\ --invoke-clean
Groups of devices to be sequentially cleaned may be specified via nested list format. In the following example, device_a, device_b and device_c are cleaned in parallel, and only once complete are device_d and device_e cleaned in parallel.
bash$ pyats run job jobfile.py --testbed-file /path/to/my/testbed.yaml\ --clean-file /path/to/my/clean.yaml\ --clean-devices "[[device_a, device_b, device_c], [device_d, device_e]]"\ --invoke-clean
--clean-device-image
specifies images to be used for clean per device.
bash$ pyats run job jobfile.py --testbed-file /path/to/my/testbed.yaml\ --clean-file /path/to/my/clean.yaml\ --invoke-clean\ --clean-device-image PE1:/path/to/clean_image.bin
This is equivalent to the following in YAML
devices: PE1: images: - /path/to/clean_image.bin
To provide a list of images:
bash$ pyats run job jobfile.py --testbed-file /path/to/my/testbed.yaml\ --clean-file /path/to/my/clean.yaml\ --invoke-clean\ --clean-device-image PE1:/path/to/controller_image.bin\ PE1:/path/to/switch_image.bin
This is equivalent to the following in YAML:
devices: PE1: images: - /path/to/controller_image.bin - /path/to/switch_image.bin
To provide images with a key structure:
bash$ pyats run job jobfile.py --testbed-file /path/to/my/testbed.yaml\ --clean-file /path/to/my/clean.yaml\ --invoke-clean\ --clean-device-image PE1:image:/path/to/image.bin\ PE1:packages:/path/to/optional_package1\ PE1:packages:/path/to/optional_package2
This is equivalent to the following in YAML:
devices: PE1: images: image: - /path/to/image.bin packages: - /path/to/optional_package1 - /path/to/optional_package2
You may also specify an image which resides at a URL:
bash$ pyats run job jobfile.py --testbed-file /path/to/my/testbed.yaml\ --clean-file /path/to/my/clean.yaml\ --invoke-clean\ --clean-device-image PE1:http://<url>/path/to/image.bin
This is equivalent to the following in YAML:
devices: PE1: images: - http://<url>/path/to/image.bin
Note
--clean-device-image
can be used in combination with--clean-os-image
,--clean-group-image
and--clean-platform-image
. Conflicts are resolved according to the following order:device > group > platform > os
.--clean-os-image
specifies images to be used for clean per OS. Uses same format as
--clean-device-image
.bash$ pyats run job jobfile.py --testbed-file /path/to/my/testbed.yaml\ --clean-file /path/to/my/clean.yaml\ --invoke-clean\ --clean-os-image iosxe:/path/to/clean_image.bin
--clean-group-image
specifies images to be used for clean per group. Uses same format as
--clean-device-image
.bash$ pyats run job jobfile.py --testbed-file /path/to/my/testbed.yaml\ --clean-file /path/to/my/clean.yaml\ --invoke-clean\ --clean-group-image group1:/path/to/clean_image.bin
--clean-platform-image
specifies images to be used for clean per platform. Uses same format as
--clean-device-image
.bash$ pyats run job jobfile.py --testbed-file /path/to/my/testbed.yaml\ --clean-file /path/to/my/clean.yaml\ --invoke-clean\ --clean-platform-image n9k:/path/to/clean_image.bin
--clean-image-json
JSON string with images for clean. The string can be base64 encoded. The two examples below are equivalent:
bash$ pyats run job /path/to/jobfile.py --clean-image-json '{"os":{"iosxe":["test.bin"]}}' bash$ pyats run job /path/to/jobfile.py --clean-image-json eyJvcyI6eyJpb3N4ZSI6WyJ0ZXN0LmJpbiJdfX0=
The schema for the JSON string is as follows:
{ "device": { "DEVICE_NAME": [ "URL_TO_IMAGE" ] }, "os": { "OS_NAME": [ "URL_TO_IMAGE" ] }, "group": { "GROUP_NAME": [ "URL_TO_IMAGE" ] }, "platform": { "PLATFORM_NAME": [ "URL_TO_IMAGE" ] } }
The clean image json will override any other image arguments as it will be applied after the standard arguments of device image, os image, group image and platform image.
E.g. using the following argument combination:
--clean-device-image R1:test.bin --clean-image-json '{"os":{"iosxe":["test_new.bin"]}}'
will use test_new.bin if the device
R1
is an IOSXE device.--clean-scope
specifies whether clean is to be done at the job level or the task level. If specified as “job”, clean is done only once per job. If specified as “task”, clean is done before each task starts. If not specified, defaults to “job”.
bash$ pyats run job jobfile.py --testbed-file /path/to/my/testbed.yaml\ --clean-file /path/to/my/clean.yaml\ --clean-scope task --invoke-clean
--invoke-clean
Clean is only invoked when this parameter is specified.
Note
Whether or not
--invoke-clean
is specified, Clean File content is still parsed and made available.-v, --verbose, -q, --quiet
Controls the logging level for Easypy. Use
-v
to increase and-q
to decrease the verbosity of log output. Additive - use up to three to achieve more effect.# quieter output bash$ pyats run job /path/to/jobfile.py -q # extre verbosity bash$ pyats run job /path/to/jobfile.py -vvv
--submitter
Specifies an alternate userid to be displayed in the submitter field. (default: current user).
bash$ pyats run job /path/to/jobfile.py --submitter chambers
--html-logs
generates an HTML formatted, user-friendly log file
TaskLog.html
in addition to existing text-based log file. Optionally, provide the location where you want the HTML files to be generated to.# use as a flag to generate HTML in the runtime archive bash$ pyats run job /path/to/jobfile.py --html-logs # use as an argument with directory where HTML logs should be put to bash$ pyats run job /path/to/jobfile.py --html-logs /path/to/directory/
Note
Experimental feature. Enabling this flag will double the size of your result archive due to log duplications.
--image
/--release
/--branch
Specifies the image path/file and release/branch string information of used for result reporting purposes.
bash$ pyats run job /path/to/jobfile.py --image /path/to/image --release zn7
--meta
User specified JSON dictionary of information to be added for reporting purposes. Can be a base64 encoded string of this JSON dictionary. The two examples below are equivalent:
bash$ pyats run job /path/to/jobfile.py --meta "{\"key\":\"value\"}" bash$ pyats run job /path/to/jobfile.py --meta eyJrZXkiOiJ2YWx1ZSJ9
URLs to JSON files, paths to JSON files, and individual key/value pairs can also be supplied. These data sources can be freely combined and the
--meta
argument can be used multiple times per command. Individual key/value pairs must use an equals sign (=
) to separate the key and the value. Being able to combine different sources of information for the JSON meta dictionary means that extra info can be added quickly and easily on a per-job basis. See examples below:bash$ pyats run job /path/to/jobfile.py --meta https://<url>/jsonfile.json bash$ pyats run job /path/to/jobfile.py --meta /path/to/jsonfile.json bash$ pyats run job /path/to/jobfile.py --meta key=value bash$ pyats run job /path/to/jobfile.py --meta https://<url>/jsonfile.json --meta /path/to/jsonfile.json bash$ pyats run job /path/to/jobfile.py --meta key=value --meta another_key=another_value bash$ pyats run job /path/to/jobfile.py --meta /path/to/jsonfile.json --meta extra_key=value
--archive-name
Specifies an alternative name for the archive file other than <jobuid>.zip.
--no-archive
Flag. When used, disables the creation of archive zip file containing the current run information/logs, and preserves the job runinfo directory (as opposed to removing it after archive creation). Using this option also disables log uploading, as log uploading requires an archive zip file to be created and uploaded.
bash$ pyats run job /path/to/jobfile.py --no-archive
--no-archive-subdir
Flag. Archive files are added to a subdirectory in the archive dir that specifies the month and day that the job was executed. When this flag is used, no such subdirectory is specified and archive files are added to the archive dir directly.
# Creates archive in <archive_dir>/ instead of <archive_dir>/<month>/ bash$ pyats run job /path/to/jobfile.py --no-archive-subdir
--no-mail
Flag, disables email notification at the end of execution.
bash$ pyats run job /path/to/jobfile.py --no-mail
--mailto
Provides a list of recipients that receive email notification at the end of the run. Supports using either white-space, comma or semi-colon as the delimiter, and supports either user ids or full email addresses. (default: current user)
bash$ pyats run job jobfile.py --mailto "john, joe, jack@domain.com"
--mail-subject
When specified, replaces the default email notification subject line. (default:
pyATS Report - job: <name> by: <uid> - Total: # (P:#, PX:#, F:# ...)
)bash$ pyats run job jobfile.py --mail-subject "legen -wait-for-it- dary. Legendary!"
--mail-html
Flag, generates an html email notification report at the end of execution. You are able to attach custom report information in the html report, please refer to Report Customization.
bash$ pyats run job /path/to/jobfile.py --mail-html
--runinfo-dir
Specifies an alternative location for execution
runinfo
directory.bash$ pyats run job /path/to/jobfile.py --runinfo-dir /my/runinfo/directory
--archive-dir
Specifies an alternative location for storing archive zip files.
bash$ pyats run job /path/to/jobfile.py --archive-dir /my/archive/directory
--xunit
Flag, enables the generation of an extra x-unit/j-unit result report XML. Can also be optionally used to provide the alternate location to generate xunit report to
# enable generation bash$ pyats run job /path/to/job/file.py --xunit # enable and also copy report to specified location bash$ pyats run job /path/to/job/file.py --xunit /path/to/dir
Argument Propagation¶
Easypy uses Python standard module argparse to parse command line arguments
stored in sys.argv
. In an effort to allow Easypy plugins to parse their own
arguments, and as well to allow users to provide custom arguments from the
command line and process them using their own parser code, a set of argument
propagation and processing rules were created:
all arguments shall follow GNU POSIX CLI argument style
parsers shall not feature positional arguments (except the Easypy
jobfile
argument)parsers shall parse directly from
sys.argv
parsers shall always leave
sys.argv[0]
untouched.parsers shall always use
ArgumentParser.parse_known_args()
to parse only their own arguments.all parsed/recognized arguments shall be removed from
sys.argv
all other remaining/unknown arguments shall be placed back into
sys.argv
In other words, parsers only take what they know, and leave behind what they don’t know for the next parser to continue parsing. This allows parsing to occur in sequential stages, wherever needed. The following is a list of typical parser location/stages in Easypy environment, in their respective parsing order:
Easypy main program
Easypy plugins: core plugins first, then user’s custom plugins.
User’s jobfile
Test-harness
aetest
main programUser’s script file
# Visualizing Argument Propagation
# --------------------------------
#
# assuming that easypy is invoked with the following arguments
# bash$ pyats run job jobfile.py --testbed-file tb.yaml \
# --no-archive --pdb --random --custom-arg "123"
# breaking down the arguments into stages
# ---------------------------------------
#
# easypy arguments: --no-archive -> disable archive
#
# plugin arguments: --testbed-file tb.yaml -> load testbed file
#
# aetest arguments: --pdb -> pdb on failure
# --random -> randomize testcases
#
# custom arguments: --custom-args "123" -> user custom
# 0. at the first beginning
# -------------------------
sys.argv = ['pyats run job', '--testbed-file', 'tb.yaml',
'--no-archive', '--pdb', '--random', '--custom-arg', '123']
# 1. easypy argument parser
# -------------------------
# easypy takes away its known argument --no-archive
#
sys.argv = ['pyats run job', '--testbed-file', 'tb.yaml', '--pdb', '--random',
'--custom-arg', '123']
# 2. plugin argument parser
# -------------------------
# testbed plugin takes away its known argument --testbed-file
#
sys.argv = ['pyats run job', '--pdb', '--random', '--custom-arg', '123']
# 3. jobfile custom argument parser
# ---------------------------------
# assume that the user wrote a custom parser in their jobfile, looking for
# argument --custom-arg. While the jobfile is being run (before Tasks are)
# started, this argument is also taken away
#
sys.argv = ['pyats run job', '--pdb', '--random']
# 4. aetest argument parser
# -------------------------
# aetest finally takes away its known argument --pdb and --random
#
sys.argv = ['pyats run job']
This argument propagation scheme essentially allows users to provide any additional custom arguments from the command line to be processed by the job and/or script file, allowing for more dynamic & data-driven testing.
Tip
because argument propagation only parses known arguments, any typos would be treated as an unknown argument and propagated further.
Steve Jobs once said, “you’re holding it wrong”.