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, --helpPrints help information and how to use each arguments.
bash$ pyats run job --help
jobfileMandatory positional argument. Specifies the full path/name to the Jobfiles to run.
bash$ pyats run job /path/to/jobfile.py
-C, --configurationoptional 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-uidoptional 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-configurationoptional argument. Additional file to add to Configuration.
bash$ pyats run job /path/to/jobfile.py --pyats-configuration /path/to/my/pyats.conf
--task-uidsLogic 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-fileSpecifies 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
testbedparameter. 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-fileFull 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-fileargument. 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-devicesSpecifies 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-imagespecifies 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-imagecan be used in combination with--clean-os-image,--clean-group-imageand--clean-platform-image. Conflicts are resolved according to the following order:device > group > platform > os.--clean-os-imagespecifies 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-imagespecifies 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-imagespecifies 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-jsonJSON 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
R1is an IOSXE device.--clean-scopespecifies 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-cleanClean is only invoked when this parameter is specified.
Note
Whether or not
--invoke-cleanis specified, Clean File content is still parsed and made available.-v, --verbose, -q, --quietControls the logging level for Easypy. Use
-vto increase and-qto 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
--submitterSpecifies an alternate userid to be displayed in the submitter field. (default: current user).
bash$ pyats run job /path/to/jobfile.py --submitter chambers
--html-logsgenerates an HTML formatted, user-friendly log file
TaskLog.htmlin 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/--branchSpecifies 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
--metaUser 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
--metaargument 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-nameSpecifies an alternative name for the archive file other than <jobuid>.zip.
--no-archiveFlag. 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-subdirFlag. 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-mailFlag, disables email notification at the end of execution.
bash$ pyats run job /path/to/jobfile.py --no-mail
--mailtoProvides 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-subjectWhen 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-htmlFlag, 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-dirSpecifies an alternative location for execution
runinfodirectory.bash$ pyats run job /path/to/jobfile.py --runinfo-dir /my/runinfo/directory
--archive-dirSpecifies an alternative location for storing archive zip files.
bash$ pyats run job /path/to/jobfile.py --archive-dir /my/archive/directory
--xunitFlag, 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
jobfileargument)parsers shall parse directly from
sys.argvparsers 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.argvall 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
aetestmain 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”.