Skip to content

Commit

Permalink
Merge branch 'release-1.3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
jerearista committed Feb 16, 2018
2 parents 8bfde11 + 30429a0 commit d8bb9f5
Show file tree
Hide file tree
Showing 16 changed files with 770 additions and 48 deletions.
28 changes: 28 additions & 0 deletions AristaLibrary/AristaLibrary.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,3 +731,31 @@ def address_is_reachable(self, address, vrf='default', source_int=None):
if loss_percent == '100':
return False
return True

def eapi_command(self, cmd, revision=None):
"""
Returns a properly formatted JSON object for an eAPI command with an
optionally-specified output revision.
Arguments:
- `cmd`: A text string containing the EOS command to execute
- `revision`: (Optional) The desired output revision
Example:
| ${commands}= | eapi Command | show cvx | revision=2 |
| Log List | ${commands} | level=DEBUG | |
| Get Command Output | cmd=${commands} | | |
| Expect | clusterMode | is | False |
| ${command1}= | eapi Command | show cvx | revision=2 |
| ${command2}= | show version | | |
| ${commands}= | Create List | ${command1} | ${command2} |
| Log List | ${commands} | level=DEBUG | |
| ${output}= | Enable | ${commands} | |
"""
command = {}
command['cmd'] = str(cmd)
if revision is not None:
command['revision'] = int(revision)

return [command]
50 changes: 28 additions & 22 deletions AristaLibrary/Expect.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,32 +264,38 @@ def get_command_output(self, switch_id=None, cmd=None, version=1):

self.arista_lib.change_to_switch(index)

# if self.import_cmd and re.match(r'^show running-config all', self.import_cmd):
if run_cmd == 'show startup-config':
# Command is 'show startup-config'. Get the startup config
# from the AristaLibrary object after refreshing the
# state of the configs stored in the object.
self.arista_lib.refresh()
reply = self.arista_lib.get_startup_config()
self.result[index] = reply.split('\n')
elif run_cmd == 'show running-config all':
# Command is 'show running-config all'. Get the running config
# from the AristaLibrary object after refreshing the
# state of the configs stored in the object.
self.arista_lib.refresh()
reply = self.arista_lib.get_running_config()
self.result[index] = reply.split('\n')
elif re.match(r'^show (startup|running)-config.*$', run_cmd):
# Command is a 'show *-config' that does not map directly
# to an AristaLibrary object attribute. Send the command
# to the switch and store the reply as a list.
reply = self.arista_lib.enable(run_cmd, encoding='text')
self.result[index] = reply[0]['result']['output'].split('\n')
elif run_cmd:
if isinstance(run_cmd, dict) or isinstance(run_cmd, list):
# Command is user specified. Send the command to the switch
# and store the result as a dictionary.
reply = self.arista_lib.enable(run_cmd, version=version)
self.result[index] = reply[0]['result']
else:
# Command is a string. See if it matches a special case
if run_cmd == 'show startup-config':
# Command is 'show startup-config'. Get the startup config
# from the AristaLibrary object after refreshing the
# state of the configs stored in the object.
self.arista_lib.refresh()
reply = self.arista_lib.get_startup_config()
self.result[index] = reply.split('\n')
elif run_cmd == 'show running-config all':
# Command is 'show running-config all'. Get the running config
# from the AristaLibrary object after refreshing the
# state of the configs stored in the object.
self.arista_lib.refresh()
reply = self.arista_lib.get_running_config()
self.result[index] = reply.split('\n')
elif re.match(r'^show (startup|running)-config.*$', run_cmd):
# Command is a 'show *-config' that does not map directly
# to an AristaLibrary object attribute. Send the command
# to the switch and store the reply as a list.
reply = self.arista_lib.enable(run_cmd, encoding='text')
self.result[index] = reply[0]['result']['output'].split('\n')
elif run_cmd:
# Command is user specified. Send the command to the switch
# and store the result as a dictionary.
reply = self.arista_lib.enable(run_cmd)
self.result[index] = reply[0]['result']

return self.result

Expand Down
6 changes: 4 additions & 2 deletions AristaLibrary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN
from version import VERSION
""" Top-level imports for AristLibrary
"""
from .version import VERSION
__version__ = VERSION
from AristaLibrary import * # NOQA
from .AristaLibrary import * # NOQA
2 changes: 1 addition & 1 deletion AristaLibrary/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = '1.2.0'
VERSION = '1.3.0'
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.2.0
1.3.0
138 changes: 138 additions & 0 deletions atest/AristaLibrary/BDD_style.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
============================================
Simple Test Example usign BDD style keywords
============================================

.. raw:: html

<!-- This class allows us to hide the test setup part -->
<style type="text/css">.hidden { display: none; }</style>

.. contents::
:local:

This example demonstrates how RobotFramework tests can be embedded in
ReStructuredText documentation and use the Behavior Driven Development (BDD)
(gherkin) style language. If you are converting an existing tab-separated test
suite, convert tabs to 4-spaces within the RST file.

“Given”, “When”, “Then” and “And” are ignored at the beginning of user keywords.

See http://robotframework.googlecode.com/svn/tags/robotframework-2.1.2/doc/userguide/RobotFrameworkUserGuide.html#embedding-arguments-into-keyword-name

The testcases should be in `code:: robotframework` blocks.

Installing RobotFramework
=========================

To execute this test, setup the following::

pip install robotframework docutils Pygments
git clone https://github.com/arista-eosplus/robotframework-aristalibrary.git
cd robotframework-aristalibrary/
python setup.py install


Executing tests
===============

Start tests using one of the examples, below::

robot demo/sample_test_refactored.rst

robot --variable SW1_HOST:localhost --variable SW1_PORT:61080 \
--variable USERNAME:eapiuser --variable PASSWORD:icanttellyou \
demo/sample_test_refactored.rst

robot --variablefile demo/myvariables.py
demo/sample_test_refactored.rst

Variable files
--------------

Variable files are just python modules with KEY = value pairs.

Example `myvariables.py`::

""" My custom values for this test suite
"""

SW1_HOST = 'localhost'
SW1_PORT = 61080
USERNAME = 'eapiuser'
PASSWORD = 'icanttellyou'

Suite Setup
===========

.. code:: robotframework
:class: hidden
*** Settings ***
Documentation This is a sample Robot Framework suite which takes advantage of
... the AristaLibrary for communicating with and controlling Arista switches.
... Run with:
... pybot --pythonpath=AristaLibrary --noncritical new demo/sample-test-refactored.txt
Library AristaLibrary
Library Collections
Suite Setup Connect To Switches
Suite Teardown Clear All Connections
*** Variables ***
${TRANSPORT} http
${SW1_HOST} localhost
${SW1_PORT} 2080
${SW2_HOST} localhost
${SW2_PORT} 2081
${USERNAME} vagrant
${PASSWORD} vagrant
*** Keywords ***
Connect To Switches
[Documentation] Establish connection to a switch which gets used by test cases.
Connect To host=${SW1_HOST} transport=${TRANSPORT} username=${USERNAME} password=${PASSWORD} port=${SW1_PORT}
Configure hostname veos0
#Connect To host=${SW2_HOST} transport=${TRANSPORT} username=${USERNAME} password=${PASSWORD} port=${SW2_PORT}
#Configure hostname veos1
Configure IP Int
[Arguments] ${switch} ${interface} ${ip}
Change To Switch ${switch}
Configure default interface ${interface}
@{cmds}= Create List default interface ${interface} interface ${interface} no switchport ip address ${ip} no shutdown
Configure ${cmds}
Switch ${switch} interface ${interface} has ip ${ip}
Configure IP Int ${switch} ${interface} ${ip}
Switch ${switch} pings ${ip}
${output}= Enable ping 10.1.1.0 text
${result}= Get From Dictionary ${output[0]} result
Log ${result}
${match} ${group1}= Should Match Regexp ${result['output']} (\\d+)% packet loss
Set Suite Variable ${PING_RESULT} ${group1}
ping packet loss should be ${expected}
${result} = Get Variable Value ${PING_RESULT} "No_data"
Should Be Equal As Integers ${result} ${expected} msg="Packets lost percent is ${result}, not ${expected}!!!"
Set Suite Variable ${PING_RESULT} ${EMPTY}
Test Cases
===============

.. code:: robotframework
*** Test Cases ***
BDD Style Ping Self
Given switch 1 interface Ethernet1 has ip 10.1.1.0/31
When switch 1 pings 10.1.1.0
Then ping packet loss should be 0
#BDD Style Ping Peer
# Given switch 1 interface Ethernet1 has ip 10.1.1.0/31
# And switch 2 interface Ethernet1 has ip 10.1.1.1/31
# When switch 2 pings 10.1.1.0
# Then ping packet loss should be 0
There you go... Tests, embedded within documentation!
148 changes: 148 additions & 0 deletions atest/AristaLibrary/eapi_cmd_revisions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
========================================
Sample Test Example in RST documentation
========================================

.. raw:: html

<!-- This class allows us to hide the test setup part -->
<style type="text/css">.hidden { display: none; }</style>

.. contents::
:local:

This example demonstrates how RobotFramework tests can be embedded in
ReStructuredText documentation. If you are converting an existing
tab-separated test suite, convert tabs to 4-spaces within the RST file.

The testcases should be in `code:: robotframework` blocks.

Installing RobotFramework
=========================

To execute this test, setup the following::

pip install robotframework docutils Pygments
git clone https://github.com/arista-eosplus/robotframework-aristalibrary.git
cd robotframework-aristalibrary/
python setup.py install


Executing tests
===============

Start tests using one of the examples, below::

robot demo/sample_test_refactored.rst

robot --variable SW1_HOST:localhost --variable SW1_PORT:61080 \
--variable USERNAME:eapiuser --variable PASSWORD:icanttellyou \
demo/sample_test_refactored.rst

robot --variablefile demo/myvariables.py
demo/sample_test_refactored.rst

Variable files
--------------

Variable files are just python modules with KEY = value pairs.

Example `myvariables.py`::

""" My custom values for this test suite
"""

SW1_HOST = 'localhost'
SW1_PORT = 61080
USERNAME = 'eapiuser'
PASSWORD = 'icanttellyou'

Suite Setup
===========

.. code:: robotframework
:class: hidden
*** Settings ***
Documentation This is a sample Robot Framework suite which takes advantage of
... the AristaLibrary for communicating with and controlling Arista switches.
... Run with:
... pybot --pythonpath=AristaLibrary --noncritical new demo/sample-test-refactored.txt
Library AristaLibrary
Library AristaLibrary.Expect
Library Collections
Suite Setup Connect To Switches
Suite Teardown Clear All Connections
*** Variables ***
${TRANSPORT} http
${SW1_HOST} localhost
${SW1_PORT} 2080
${SW2_HOST} localhost
${SW2_PORT} 2081
${USERNAME} vagrant
${PASSWORD} vagrant
*** Keywords ***
Connect To Switches
[Documentation] Establish connection to a switch which gets used by test cases.
Connect To host=${SW1_HOST} transport=${TRANSPORT} username=${USERNAME} password=${PASSWORD} port=${SW1_PORT}
Configure hostname veos0
#Connect To host=${SW2_HOST} transport=${TRANSPORT} username=${USERNAME} password=${PASSWORD} port=${SW2_PORT}
#Configure hostname veos1
Test Cases
===============

.. code:: robotframework
*** Test Cases ***
eAPI Command Revision
[tags] Production
# Default revision
${output}= Enable show cvx
${result}= Get From Dictionary ${output[0]} result
Log ${result}
Dictionary Should Not Contain Key ${result} clusterMode
# Specify revision 2 for this command
${show_cvx}= Create Dictionary cmd=show cvx revision=${2}
${cmds}= Create List ${show_cvx}
Log List ${cmds}
${output}= Enable ${cmds}
${result}= Get From Dictionary ${output[0]} result
Log ${result}
Dictionary Should Contain Key ${result} clusterMode
eAPI Command Revision with Expect
[tags] Production
# Specify revision 2 for this command
${show_cvx}= Create Dictionary cmd=show cvx revision=${2}
${cmds}= Create List ${show_cvx}
Log List ${cmds}
Get Command Output cmd=${cmds}
Expect clusterMode is False
eAPI Command Revision with Eapi Command
[tags] Production
${show_cvx2}= Create Dictionary cmd=show cvx revision=${2}
${cmds2}= Create List ${show_cvx2}
# Specify revision 2 for this command
${show_cvx}= Eapi Command cmd=show cvx revision=2
${show_ver}= Eapi Command cmd=show version
${cmds}= Combine Lists ${show_cvx} ${show_ver}
Log List ${cmds}
Log List ${show_cvx}
Log List ${cmds2}
#Dictionaries Should Be Equal ${show_cvx}[0] ${show_cvx2}[0]
Lists Should Be Equal ${show_cvx} ${cmds2}
${output}= Enable ${cmds}
Log List ${output}
Log Dictionary ${output[0]['result']}
There you go... Tests, embedded within documentation!
Loading

0 comments on commit d8bb9f5

Please sign in to comment.