Full and Generic Datastore CRUD Library
authorPhillip Shea <phillip.shea@hp.com>
Sat, 22 Aug 2015 00:21:40 +0000 (17:21 -0700)
committerPhillip Shea <phillip.shea@hp.com>
Wed, 26 Aug 2015 16:58:14 +0000 (09:58 -0700)
Implements generic Create, Read, Update and Delete keywords to be
used on any controller datastore.
A cars and people library was started such that modular CRUD tests
can be written for those shards.
The Config and Operational API  variables in Variables.py were modified
to remove a trailing '/' which was causing REST failures.

Change-Id: I732b03a7449d2b0a4d6bb1b57f5e8e8b19c87644
Signed-off-by: Phillip Shea <phillip.shea@hp.com>
test/csit/libraries/CarsAndPeopleCRUD.robot [new file with mode: 0644]
test/csit/libraries/DatastoreCRUD.robot [new file with mode: 0644]
test/csit/variables/Variables.py

diff --git a/test/csit/libraries/CarsAndPeopleCRUD.robot b/test/csit/libraries/CarsAndPeopleCRUD.robot
new file mode 100644 (file)
index 0000000..a853b31
--- /dev/null
@@ -0,0 +1,70 @@
+*** Settings ***
+Library           Collections
+Resource          DatastoreCRUD.robot
+
+*** Keywords ***
+Initialize Cars
+    [Arguments]    ${controller_ip}    ${field bases}
+    [Documentation]    Initializes the cars shard by creating a 0th car with POST then deleting it.
+    ...    Field bases are a dictionary of datastore record field values onto which is appended
+    ...    an incremental value to uniquely identify the record from which it came.
+    ...    Typically, you will use the Create Dictionary keyword on arguments which look like this:
+    ...    id=${EMPTY} category=coupe model=model manufacturer=mfg year=2
+    ${node}=    Set Variable    ${EMPTY}
+    ${prefix}=    Set Variable    {"car:cars":{"car-entry":[{
+    ${postfix}=    Set Variable    }]}}
+    Create Records    ${controller_ip}    ${node}    ${0}    ${0}    ${prefix}    ${field bases}    ${postfix}
+    ${node}=    Set Variable    car:cars/car-entry
+    Delete Records    ${controller_ip}    ${node}    ${0}    ${0}
+
+Create Cars
+    [Arguments]    ${controller_ip}    ${first}    ${last}    ${field bases}
+    [Documentation]    Creates cars with record IDs of specified range using POST.
+    ...    If first and last are equal, only one record is updated.
+    ...    Field bases are a dictionary of datastore record field values onto which is appended
+    ...    an incremental value to uniquely identify the record from which it came.
+    ...    Typically, you will use the Create Dictionary keyword on an argument which looks like this:
+    ...    id=${EMPTY} category=coupe model=model manufacturer=mfg year=2
+    ${node}=    Set Variable    car:cars
+    ${prefix}=    Set Variable    {"car-entry":[{
+    ${postfix}=    Set Variable    }]}
+    Create Records    ${controller_ip}    ${node}    ${first}    ${last}    ${prefix}    ${field bases}    ${postfix}
+
+Update Cars
+    [Arguments]    ${controller_ip}    ${first}    ${last}    ${field bases}
+    [Documentation]    Updates cars with record IDs of the specified using PUT.
+    ...    If first and last are equal, only one record is updated.
+    ...    Field bases are a dictionary of datastore record field values onto which is appended
+    ...    an incremental value to uniquely identify the record from which it came.
+    ...    Typically, you will use the Create Dictionary keyword on arguments which look like this:
+    ...    id=${EMPTY} category=coupe model=model manufacturer=mfg year=2
+    ${node}=    Set Variable    car:cars/car-entry
+    ${prefix}=    Set Variable    {"car-entry":[{
+    ${postfix}=    Set Variable    }]}
+    Update Records    ${controller_ip}    ${node}    ${first}    ${last}    ${prefix}    ${field bases}    ${postfix}
+
+Read All Cars
+    [Arguments]    ${controller_ip}
+    [Documentation]    Returns all records from the cars shard in JSON format.
+    ${node}=    Set Variable    car:cars
+    ${result}=    Read Records    ${controller_ip}    ${node}
+    [Return]    ${result}
+
+Read One Car
+    [Arguments]    ${controller_ip}    ${id}
+    [Documentation]    Returns the specified record from the cars shard in JSON format.
+    ${node}=    Set Variable    car:cars/car-entry/${id}
+    ${result}=    Read Records    ${controller_ip}    ${node}
+    [Return]    ${result}
+
+Delete All Cars
+    [Arguments]    ${controller_ip}
+    [Documentation]    Deletes all records from the cars shard.
+    ${node}=    Set Variable    car:cars
+    Delete All Records    ${controller_ip}    ${node}
+
+Delete Cars
+    [Arguments]    ${controller_ip}    ${first}    ${last}
+    [Documentation]    Deletes the specified range of records from the cars shard.
+    ${node}=    Set Variable    car:cars/car-entry
+    Delete Records    ${controller_ip}    ${node}    ${first}    ${last}
diff --git a/test/csit/libraries/DatastoreCRUD.robot b/test/csit/libraries/DatastoreCRUD.robot
new file mode 100644 (file)
index 0000000..ba7f091
--- /dev/null
@@ -0,0 +1,75 @@
+*** Settings ***
+Library           Collections
+Library           RequestsLibrary
+Variables         ../variables/Variables.py
+
+*** Keywords ***
+Create Records
+    [Arguments]    ${controller_ip}    ${node}    ${first}    ${last}    ${prefix}    ${field bases}    ${postfix}
+    [Documentation]    POSTs records to a controller's data store. First and last index numbers are specified
+    ...    as is a dictionary called field_bases containing the base name for the field contents
+    ...    onto which will be appended the index number. Prefix and postfix are used to complete
+    ...    the JSON payload. The keyword passes if return code is correct.
+    ${last}    Convert to Integer    ${last}
+    : FOR    ${INDEX}    IN RANGE    ${first}    ${last+1}
+    \    ${payload}=    Assemble Payload    ${INDEX}    ${prefix}    ${field bases}    ${postfix}
+    \    Log    ${payload}
+    \    Create_Session    session    http://${controller_ip}:${RESTCONFPORT}${CONFIG_API}    headers=${HEADERS}    auth=${AUTH}
+    \    ${resp}    RequestsLibrary.Post    session    ${node}    ${payload}
+    \    Log    ${resp}
+    \    Should Be Equal As Strings    ${resp}    <Response [204]>
+
+Read Records
+    [Arguments]    ${controller_ip}    ${node}
+    [Documentation]    GETs records from a shard on a controller's data store.
+    Create_Session    session    http://${controller_ip}:${RESTCONFPORT}${CONFIG_API}    headers=${HEADERS}    auth=${AUTH}
+    ${resp}=    RequestsLibrary.Get    session    ${node}
+    [Return]    ${resp.json()}
+
+Update Records
+    [Arguments]    ${controller_ip}    ${node}    ${first}    ${last}    ${prefix}    ${field bases}    ${postfix}
+    [Documentation]    PUTs records to shard on a controller's data store. First and last index numbers are specified
+    ...    as is a dictionary called field_bases containing the base name for the field contents
+    ...    onto which will be appended the index number. Prefix and postfix are used to complete
+    ...    the JSON payload. The keyword passes if return code is correct.
+    ${last}    Convert to Integer    ${last}
+    : FOR    ${INDEX}    IN RANGE    ${first}    ${last+1}
+    \    ${payload}=    Assemble Payload    ${INDEX}    ${prefix}    ${field bases}    ${postfix}
+    \    Log    ${payload}
+    \    Create_Session    session    http://${controller_ip}:${RESTCONFPORT}${CONFIG_API}    headers=${HEADERS}    auth=${AUTH}
+    \    ${resp}=    RequestsLibrary.Put    session    ${node}/${INDEX}    ${payload}
+    \    Log    ${resp}
+    \    Should Be Equal As Strings    ${resp}    <Response [200]>
+
+Delete Records
+    [Arguments]    ${controller_ip}    ${node}    ${first}    ${last}
+    [Documentation]    DELETEs specified range of records from a shard on a contrsoller's data store.
+    ${last}    Convert to Integer    ${last}
+    : FOR    ${INDEX}    IN RANGE    ${first}    ${last+1}
+    \    Create_Session    session    http://${controller_ip}:${RESTCONFPORT}${CONFIG_API}    headers=${HEADERS}    auth=${AUTH}
+    \    ${resp}=    RequestsLibrary.Delete    session    ${node}/${INDEX}
+    \    Should Be Equal As Strings    ${resp}    <Response [200]>
+
+Delete All Records
+    [Arguments]    ${controller_ip}    ${node}
+    [Documentation]    DELETEs all records from a shard on a controller's data store.
+    Create_Session    session    http://${controller_ip}:${RESTCONFPORT}${CONFIG_API}    headers=${HEADERS}    auth=${AUTH}
+    ${resp}=    RequestsLibrary.Delete    session    ${node}
+    Should Be Equal As Strings    ${resp}    <Response [200]>
+
+Assemble Payload
+    [Arguments]    ${id}    ${prefix}    ${field bases}    ${postfix}
+    [Documentation]    Populates a payload for creating or updating a shard record.
+    ...    id: The record number and is also appended onto each field to uniquely identify it.
+    ...    prefix: The portion of the json payload before the records.
+    ...    field bases: A dictionary of records onto which the id is appended.
+    ...    prefix: The portion of the json payload after the records.
+    ${length}=    Get Length    ${field bases}
+    ${keys}=    Get Dictionary Keys    ${field bases}
+    ${payload}=    Set Variable    ${prefix}
+    : FOR    ${key string}    IN    @{keys}
+    \    ${value string}=    Get From Dictionary    ${field bases}    ${key string}
+    \    ${payload}=    Catenate    ${payload}    "${key string}": "${value string}${id}",
+    ${payload}=    Get Substring    ${payload}    ${EMPTY}    -1
+    ${payload}=    Catenate    ${payload}    ${postfix}
+    [Return]    ${payload}
index 5b5850fa24046d1361b6405e871aa1283dc58f4e..ef89eecbd1bd477b630c515f29784647dc75681c 100644 (file)
@@ -84,8 +84,8 @@ CONTROLLER_CONFIG_MOUNT = ('/restconf/config/network-topology:'
                            'network-topology/topology'
                            '/topology-netconf/node/'
                            'controller-config/yang-ext:mount')
                            'network-topology/topology'
                            '/topology-netconf/node/'
                            'controller-config/yang-ext:mount')
-CONFIG_API = '/restconf/config/'
-OPERATIONAL_API = '/restconf/operational/'
+CONFIG_API = '/restconf/config'
+OPERATIONAL_API = '/restconf/operational'
 
 # TOKEN
 AUTH_TOKEN_API = '/oauth2/token'
 
 # TOKEN
 AUTH_TOKEN_API = '/oauth2/token'