diff options
Diffstat (limited to 'cmso-robot/robot/resources')
11 files changed, 770 insertions, 0 deletions
diff --git a/cmso-robot/robot/resources/browser_setup.robot b/cmso-robot/robot/resources/browser_setup.robot new file mode 100644 index 0000000..032759e --- /dev/null +++ b/cmso-robot/robot/resources/browser_setup.robot @@ -0,0 +1,50 @@ +*** Settings *** +Documentation The main interface for interacting with VID. It handles low level stuff like managing the selenium request library and VID required steps +Library Collections +Library OSUtils +Library OperatingSystem +Library Selenium2Library + +*** Variables *** +${CHROME_DRIVER_WIN32_PATH} drivers/win32 +${CHROME_DRIVER_MAC64_PATH} drivers/mac64 +${CHROME_DRIVER_LINUX64_PATH} drivers/linux64 +${CHROME_DRIVER_WIN32} ${CHROME_DRIVER_WIN32_PATH}/chromedriver.exe +${CHROME_DRIVER_MAC64} ${CHROME_DRIVER_MAC64_PATH} /chromedriver +${CHROME_DRIVER_LINUX64} ${CHROME_DRIVER_LINUX64_PATH}/chromedriver + +*** Keywords *** +Setup Browser + [Documentation] Sets up browser based upon the value of + [Arguments] ${browser} + Run Keyword If '${browser}' == 'firefox' Setup Browser Firefox + Run Keyword If '${browser}' == 'chrome' Setup Browser Chrome + Log Running with ${browser} + +Setup Browser Firefox + ${dc} Evaluate sys.modules['selenium.webdriver'].DesiredCapabilities.FIREFOX sys, selenium.webdriver + Set To Dictionary ${dc} elementScrollBehavior 1 + Create Webdriver Firefox desired_capabilities=${dc} + ##Set Global Variable ${GLOBAL_SELENIUM_BROWSER_CAPABILITIES} ${dc} + + + Setup Browser Chrome + ${os}= Get Normalized Os + Log Normalized OS=${os} + Run Keyword If '${os}' == 'win32' Append To Environment Variable PATH ${CHROME_DRIVER_WIN32_PATH} + ##Run Keyword If '${os}' == 'win32' Set Environment Variable webdriver.chrome.driver ${CHROME_DRIVER_WIN32} + Run Keyword If '${os}' == 'mac64' Append To Environment Variable PATH ${CHROME_DRIVER_MAC64_PATH} + #Run Keyword If '${os}' == 'mac64' Set Environment Variable webdriver.chrome.driver ${CHROME_DRIVER_MAC64} + Run Keyword If '${os}' == 'linux64' Append To Environment Variable PATH ${CHROME_DRIVER_LINUX64_PATH} + #Run Keyword if '${os}' == 'linux64' Set Environment Variable webdriver.chrome.driver ${CHROME_DRIVER_LINUX64} + ${chrome options}= Evaluate sys.modules['selenium.webdriver'].ChromeOptions() sys + Call Method ${chrome options} add_argument no-sandbox + ${dc} Evaluate sys.modules['selenium.webdriver'].DesiredCapabilities.CHROME sys, selenium.webdriver + Set To Dictionary ${dc} elementScrollBehavior 1 + Create Webdriver Chrome chrome_options=${chrome_options} desired_capabilities=${dc} + #Set Global Variable ${GLOBAL_SELENIUM_BROWSER_CAPABILITIES} ${dc} + +Handle ATT Speed Bump + [Documentation] Handle AT&T Speed Bump when accessing Rackspace UI from AT&T network + ${test} ${value}= Run keyword and ignore error Title Should Be Notice - Uncategorized Site + Run keyword If '${test}' == 'PASS' Click Element xpath=//a[contains(@href, 'accepted-Notify-Uncategorized')]
\ No newline at end of file diff --git a/cmso-robot/robot/resources/files.robot b/cmso-robot/robot/resources/files.robot new file mode 100644 index 0000000..fcfffbb --- /dev/null +++ b/cmso-robot/robot/resources/files.robot @@ -0,0 +1,50 @@ +*** Settings *** +Documentation Some handy Keywords for accessing log files over SSH. Assumptions are that logs will belong to users other than the currently logged in user and that sudo will be required +Library OperatingSystem +Library SSHLibrary +Library HttpLibrary.HTTP +Library String +Library Collections + +*** Variables *** + +*** Keywords *** +Open Connection And Log In + [Documentation] Open a connection using the passed user and SSH key. Connection alias will be the host name by default. + [Arguments] ${HOST} ${user} ${pvt} ${password}= ${alias}=${HOST} ${timeout}=120s + Open Connection ${HOST} alias=${alias} timeout=${timeout} + Login With Public Key ${user} ${pvt} password=${password} delay=0.5 seconds + +Grep Local File + [Documentation] Grep the passed file name and return all of the lines that match the passed pattern using the current connection + [Arguments] ${pattern} ${fullpath} + ${output}= Execute Command grep ${pattern} ${fullpath} + [Return] ${output} + + Grep File on Host + [Documentation] Grep the passed file name and return all of the lines that match the passed pattern using passed connection alias/host + [Arguments] ${host} ${pattern} ${fullpath} + Switch Connection ${host} + ${output}= Grep Local File ${pattern} ${fullpath} + @{lines}= Split To Lines ${output} + [Return] @{lines} + +Grep File on Hosts + [Documentation] Grep the passed file name and return all of the lines that match the passed pattern using passed list of connections + [Arguments] ${HOSTS} ${pattern} ${fullpath} + &{map}= Create Dictionary + :FOR ${HOST} IN @{HOSTS} + \ Log ${HOST} + \ @{lines}= Grep File on Host ${HOST} ${pattern} ${fullpath} + \ &{map}= Create Dictionary ${HOST}=@{lines} &{map} + [Return] &{map} + +Tail File on Host Until + [Documentation] Tail log file into grep which returns file lines containing the grep pattern. Will timeout after timeout= if expected pattern not received. + [Arguments] ${host} ${pattern} ${fullpath} ${expected} ${timeout}=60 ${options}=-c -0 + Switch Connection ${host} + ${tailcommand}= Catenate tail ${options} -f ${fullpath} | grep --color=never ${pattern} + Write ${tailcommand} + ${stdout}= Read Until Regexp ${expected} + @{lines}= Split To Lines ${stdout} + [Return] @{lines} diff --git a/cmso-robot/robot/resources/json_templater.robot b/cmso-robot/robot/resources/json_templater.robot new file mode 100644 index 0000000..b057251 --- /dev/null +++ b/cmso-robot/robot/resources/json_templater.robot @@ -0,0 +1,20 @@ +*** Settings *** +Documentation This resource is filling out json string templates and returning the json back +Library RequestsLibrary +Library StringTemplater +Library OperatingSystem + +*** Keywords *** +Fill JSON Template + [Documentation] Runs substitution on template to return a filled in json + [Arguments] ${json} ${arguments} + ${returned_string}= Template String ${json} ${arguments} + ${returned_json}= To Json ${returned_string} + [Return] ${returned_json} + +Fill JSON Template File + [Documentation] Runs substitution on template to return a filled in json + [Arguments] ${json_file} ${arguments} + ${json}= OperatingSystem.Get File ${json_file} + ${returned_json}= Fill JSON Template ${json} ${arguments} + [Return] ${returned_json}
\ No newline at end of file diff --git a/cmso-robot/robot/resources/misc.robot b/cmso-robot/robot/resources/misc.robot new file mode 100644 index 0000000..8409601 --- /dev/null +++ b/cmso-robot/robot/resources/misc.robot @@ -0,0 +1,42 @@ +*** Settings *** +Library Collections +Library String +Library UUID +Library Process +Library HttpLibrary.HTTP +Documentation Miscellaneous keywords + +Resource json_templater.robot +Resource scheduler_requests/create_schedule.robot + + +*** Variables *** + +*** Keywords *** + +Validate Status + [Documentation] Fail unless the Request response is in the passed list of valid HTTP status codes. + [Arguments] ${resp} ${valid_status_list} + ${status_code} Convert To String ${resp.status_code} + Return From Keyword If '${resp.status_code}' in ${valid_status_list} + Fail ${resp.status_code} + +Validate JSON Error + [Documentation] Fails if messageIds do not match. expected_errors should be a list but a string would likely work as well + [Arguments] ${resp_json} ${expected_errors} + ${result}= Get From Dictionary ${resp_json['requestError']} messageId + Should Contain ${expected_errors} ${result} #checks expected_errors list for the actual error received from schedule + +Check ATTIDs Template + [Documentation] This just checks a list of uuids + [Arguments] ${expected_status_code} ${template_folder} + ${request_file}= Convert to String OneVnfImmediateATTID.json.template + ${attid_file}= OperatingSystem.Get File robot/assets/AOTS_CM_IDs.txt + @{attids}= Split to lines ${attid_file} + :for ${attid} in @{attids} + \ ${uuid}= Generate UUID + \ ${resp}= Run Keyword and Continue on Failure Create Schedule ${uuid} ${request_file} ${template_folder} attid=${attid} + \ Run Keyword and Continue on Failure Should Be Equal as Strings ${resp.status_code} ${expected_status_code} + \ ${reps}= Delete Change Management auth schedules/${uuid} + +
\ No newline at end of file diff --git a/cmso-robot/robot/resources/scheduler_common.robot b/cmso-robot/robot/resources/scheduler_common.robot new file mode 100644 index 0000000..7fa8a59 --- /dev/null +++ b/cmso-robot/robot/resources/scheduler_common.robot @@ -0,0 +1,85 @@ +*** Settings *** +Documentation The private interface for interacting with Openstack. It handles low level stuff like managing the authtoken and Openstack required fields + +Library Collections +Library RequestsLibrary +Library UUID +Library HTTPUtils +Library String +Resource misc.robot +*** Variables *** +*** Variables *** +${SCHEDULER_PATH} /scheduler/v1 +${CHANGE_MANAGEMENT_PATH} ${SCHEDULER_PATH}/ChangeManagement +${valid_status_codes} 200 202 400 404 204 409 +#**************** Test Case Variables ****************** + +*** Keywords *** + + +Post Change Management + [Documentation] Runs a scheduler POST request + [Arguments] ${alias} ${resource} ${data}={} + ${data_path}= Catenate ${CHANGE_MANAGEMENT_PATH}/${resource} + ${resp}= Post Scheduler ${alias} ${data_path} ${data} + [Return] ${resp} + +Delete Change Management + [Documentation] Runs a scheduler DELETE request (this may need to be changed for 1802 US change Delete schedule to Cancel Schedule) + [Arguments] ${alias} ${resource} + ${data_path}= Catenate ${CHANGE_MANAGEMENT_PATH}/${resource} + ${resp}= Delete Scheduler ${alias} ${data_path} + [Return] ${resp} + +Get Change Management + [Documentation] Runs a scheduler GET request + [Arguments] ${alias} ${resource} + ${data_path}= Catenate ${CHANGE_MANAGEMENT_PATH}/${resource} + ${resp}= Get Scheduler ${alias} ${data_path} + [Return] ${resp} + +Post Scheduler + [Documentation] Runs a scheduler POST request + [Arguments] ${alias} ${data_path} ${data}={} + ${url}= Catenate ${GLOBAL_SCHEDULER_PROTOCOL}://${GLOBAL_SCHEDULER_HOST}:${GLOBAL_SCHEDULER_PORT} + ${uuid}= Generate UUID + ${proxies}= Create Dictionary no=pass + ${session}= Create Session ${alias} ${url} + ${auth_string}= B64 Encode ${GLOBAL_SCHEDULER_USER}:${GLOBAL_SCHEDULER_PASSWORD} + ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID} Authorization=Basic ${auth_string} + ${resp}= Post Request ${alias} ${data_path} headers=${headers} data=${data} + Log Received response from scheduler ${resp.text} + ${valid}= Split String ${valid_status_codes} + + Validate Status ${resp} ${valid} + [Return] ${resp} + +Delete Scheduler + [Documentation] Runs a scheduler POST request + [Arguments] ${alias} ${data_path} + ${url}= Catenate ${GLOBAL_SCHEDULER_PROTOCOL}://${GLOBAL_SCHEDULER_HOST}:${GLOBAL_SCHEDULER_PORT} + ${uuid}= Generate UUID + ${proxies}= Create Dictionary no=pass + ${session}= Create Session ${alias} ${url} + ${auth_string}= B64 Encode ${GLOBAL_SCHEDULER_USER}:${GLOBAL_SCHEDULER_PASSWORD} + ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID} Authorization=Basic ${auth_string} + ${resp}= Delete Request ${alias} ${data_path} headers=${headers} + Log Received response from scheduler ${resp.text} + ${valid}= Split String ${valid_status_codes} + Validate Status ${resp} ${valid} + [Return] ${resp} + +Get Scheduler + [Documentation] Runs a scheduler GET request + [Arguments] ${alias} ${data_path} + ${url}= Catenate ${GLOBAL_SCHEDULER_PROTOCOL}://${GLOBAL_SCHEDULER_HOST}:${GLOBAL_SCHEDULER_PORT} + ${uuid}= Generate UUID + ${proxies}= Create Dictionary no=pass + ${session}= Create Session ${alias} ${url} + ${auth_string}= B64 Encode ${GLOBAL_SCHEDULER_USER}:${GLOBAL_SCHEDULER_PASSWORD} + ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID} Authorization=Basic ${auth_string} + ${resp}= Get Request ${alias} ${data_path} headers=${headers} + Log Received response from scheduler ${resp.json()} + ${valid}= Split String ${valid_status_codes} + Validate Status ${resp} ${valid} + [Return] ${resp} diff --git a/cmso-robot/robot/resources/scheduler_requests/approval_requests.robot b/cmso-robot/robot/resources/scheduler_requests/approval_requests.robot new file mode 100644 index 0000000..c971017 --- /dev/null +++ b/cmso-robot/robot/resources/scheduler_requests/approval_requests.robot @@ -0,0 +1,36 @@ +*** Settings *** +Documentation Scheduler keywords + +Library StringTemplater +Library UUID +Library DateTime +Library Collections + +Resource ../scheduler_common.robot +Resource ../json_templater.robot + +*** Variables **** +${TEMPLATES} robot/assets/templates/changemanagement +${UTC} %Y-%m-%dT%H:%M:%SZ + +*** Keywords *** +Wait For Pending Approval + [Documentation] Gets the schedule identified by the uuid and checks if it is in the Pending Approval state + [Arguments] ${uuid} ${status}=Pending Approval + ${resp}= Get Change Management auth schedules/${uuid} + ${json}= Catenate ${resp.json()} + Dictionary Should Contain Item ${resp.json()} status ${status} + +Send Tier2 Approval + [Documentation] Sends an approval post request for the given schedule using the UUID and User given and checks that request worked + [Arguments] ${uuid} ${user} ${status} + ${approval}= Create Dictionary approvalUserId=${user} approvalType=Tier 2 approvalStatus=${status} + ${resp}= Post Change Management auth schedules/${uuid}/approvals data=${approval} + Should Be Equal As Strings ${resp.status_code} 204 + + +Send Invalid Approval + [Arguments] ${uuid} ${user} + ${approval}= Create Dictionary approvalUserId=${user} approvalType=Tier 3 approvalStatus=Accepted + Run Keyword and Expect Error 400 Post Change Management auth schedules/${uuid}/approvals data=${approval} +
\ No newline at end of file diff --git a/cmso-robot/robot/resources/scheduler_requests/create_schedule.robot b/cmso-robot/robot/resources/scheduler_requests/create_schedule.robot new file mode 100644 index 0000000..7264b05 --- /dev/null +++ b/cmso-robot/robot/resources/scheduler_requests/create_schedule.robot @@ -0,0 +1,49 @@ +*** Settings *** +Documentation SCheduler tests + +Library StringTemplater +Library UUID +Library String +Library DateTime +Library Collections +Library OperatingSystem +Library JSONUtils + +Resource ../scheduler_common.robot +Resource ../json_templater.robot + +*** Variables **** +${VID_TEMPLATES} robot/assets/templates/changemanagement +${UTC} %Y-%m-%dT%H:%M:%SZ + +*** Keywords *** +Create Schedule + [Arguments] ${uuid} ${request_file} ${TEMPLATES} ${workflow}=Unknown ${minutesFromNow}=5 + ${testid}= Catenate ${uuid} + ${testid}= Get Substring ${testid} -4 + ${dict}= Create Dictionary serviceInstanceId=${uuid} parent_service_model_name=${uuid} + ${callbackData}= Fill JSON Template File ${VID_TEMPLATES}/VidCallbackData.json.template ${dict} + ${callbackDataString}= Json Escape ${callbackData} + ${map}= Create Dictionary uuid=${uuid} callbackUrl=${GLOBAL_VID_CALLBACK_URL} callbackData=${callbackDataString} testid=${testid} workflow=${workflow} userId=${GLOBAL_VID_USERID} + ${nodelist}= Split String ${NODES} , + ${nn}= Catenate 1 + # Support up to 4 ChangeWindows + : For ${i} in range 1 4 + \ ${today}= Evaluate ((${i}-1)*1440)+${minutesFromNow} + \ ${tomorrow} Evaluate ${today}+1440 + \ ${last_time} Evaluate ${today}+30 + \ ${start_time}= Get Current Date UTC + ${today} minutes result_format=${UTC} + \ ${end_time}= Get Current Date UTC + ${tomorrow} minutes result_format=${UTC} + \ Set To Dictionary ${map} start_time${i}=${start_time} end_time${i}=${end_time} + + : For ${vnf} in @{nodelist} + \ Set To Dictionary ${map} node${nn} ${vnf} + \ ${nn}= Evaluate ${nn}+1 + + + ${data}= Fill JSON Template File ${TEMPLATES}/${request_file} ${map} + ${resp}= Post Change Management auth schedules/${uuid} data=${data} + [Return] ${resp} + + +
\ No newline at end of file diff --git a/cmso-robot/robot/resources/test_templates/change_management.robot b/cmso-robot/robot/resources/test_templates/change_management.robot new file mode 100644 index 0000000..0584cce --- /dev/null +++ b/cmso-robot/robot/resources/test_templates/change_management.robot @@ -0,0 +1,166 @@ +*** Settings *** +Documentation Creates VID VNF Instance +Library StringTemplater +Library String +Library OperatingSystem +Library UUID +Library Collections +Library HttpLibrary.HTTP +Library DateTime +Resource ../scheduler_common.robot +Resource ../json_templater.robot +Resource ../files.robot +Resource ../scheduler_requests/create_schedule.robot +Resource ../scheduler_requests/approval_requests.robot +*** Variables **** +#Variable can only be assigned String variables initially +${status_list}= +${expected_status_list_immediate}= "Scheduled","Notifications Initiated" +${expected_status_list}= "Pending Schedule","Pending Approval","Scheduled","Notifications Initiated","Optimization in Progress" +*** Keywords *** +#GENERAL NOTES about Robot Framework +# Keywords are effectively equivalent to functions/methods +# ${} denotes a scalar variable @{} denotes a list variable and &{} denotes a Dictionary +# Only scalar variables should be passed to a function. Even if your function calls for a list it is easier to pass the list in as a scalar ${} +# To do this simply declare your non-scalar normally (@{}&{}), then when passing the non-scalar into a function pass it as a ${} +# +Change Management Template + [Arguments] ${request_file} ${expected_status_code} ${template_folder} + ${uuid}= Generate UUID + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} #Sends the POST request to create schedule. Result stored in ${resp} resp is an object that comes from the RequestLibrary + Wait Until Keyword Succeeds 120s 5s Wait For Pending Approval ${uuid} #Runs Wait For Pending Approval every 5s for 120s or until it passes + Should Be Equal as Strings ${resp.status_code} ${expected_status_code} #This will fail if an unexpected result is received from Scheduler + Send Tier2 Approval ${uuid} jf9860 Accepted + ${resp}= Get Change Management auth schedules/${uuid} #GETs the schedule from Scheduler. The result is stored in $resp + Wait Until Keyword Succeeds 120s 5s Wait For All VNFs Reach Status Completed ${uuid} #Makes sure VNF(s) is(are) completed in the schedule + Wait Until Keyword Succeeds 120s 5s Wait for Schedule to Complete Completed ${uuid} #Makes sure Schedule is marked completed + ${reps}= Delete Change Management auth schedules/${uuid} #sends DELETE request to scheduler this may have to be changed for 1802 US to change Delete Schedule to Cancel Schedule + +Change Management Rejection Template + [Arguments] ${request_file} ${template_folder} + ${uuid}= Generate UUID + ${expected_status_code}= Convert to String 202 #Variables in keywords section have to be assigned keywords. So ${expected_status_code}= 202 + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} + Wait Until Keyword Succeeds 120s 5s Wait For Pending Approval ${uuid} + Should Be Equal as Strings ${resp.status_code} ${expected_status_code} + Send Tier2 Approval ${uuid} jf9860 Rejected #Sends and checks Approval POST request + +Change Management Failure Template + [Documentation] Sends a post request expecting a failure. expected_status_code should be whatever code is expected for this call + [Arguments] ${request_file} ${expected_status_code} ${template_folder} + ${uuid}= Generate UUID + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} + Should Be Equal as Strings ${resp.status_code} ${expected_status_code} + Return from Keyword If '${resp.status_code}' == '202' + #List of possible reasons that the request should fail - we should look for exact message..... + @{status_list}= Create List Scheduler.INVALID_ATTRIBUTE Scheduler.MISSING_REQUIRED_ATTRIBUTE Scheduler.NODE_LIST_CONTAINS_EMTPY_NODE Scheduler.INVALID_CHANGE_WINDOW + Validate Json Error ${resp.json()} ${status_list} + +Change Management Immediate Template + [Arguments] ${request_file} ${expected_status_code} ${template_folder} + ${uuid}= Generate UUID + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} #Immediate schedules do not need approval so there is no wait for pending approval or send approval + Should Be Equal as Strings ${resp.status_code} ${expected_status_code} + Wait Until Keyword Succeeds 120s 5s Wait For All VNFs Reach Status Completed ${uuid} + Wait Until Keyword Succeeds 120s 5s Wait for Schedule to Complete Completed ${uuid} + ${reps}= Delete Change Management auth schedules/${uuid} +Change Management Already Exists Immediate Template + [Arguments] ${request_file} ${template_folder} + ${uuid}= Convert to String 46969fb7-0d4c-4e78-80ca-e20759628be5 #This value was taken from DEV env Scheduler DB. To actually automate may want to make SQL query Keyword to get an existing scheduleId + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} + Should Be Equal as Strings ${resp.status_code} 409 +Record Status Immediate Template + [Arguments] ${request_file} ${template_folder} + ${uuid}= Generate UUID + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} + Set Global Variable ${status_list} ${EMPTY} #$EMPTY is a empty string variable defined by ROBOT. This makes sure the global variable is cleared each run + Wait Until Keyword Succeeds 120s 5s Add to Status List Completed ${uuid} + ${reps}= Delete Change Management auth schedules/${uuid} + Compare Status List ${expected_status_list_immediate} ${status_list} + Log ${status_list} +Record Status Template + [Documentation] This test checks statuses for future schedules. It tends to fail due to scheduled status being missed. + [Arguments] ${request_file} ${template_folder} + ${uuid}= Generate UUID + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} + Set Global Variable ${status_list} ${EMPTY} + Wait Until Keyword Succeeds 120s 5s Add to Status List Pending Approval ${uuid} + Send Tier2 Approval ${uuid} jf9860 Accepted + ${resp}= Get Change Management auth schedules/${uuid} + Wait Until Keyword Succeeds 300s 5s Wait For All VNFs Reach Status and Add to Status Completed ${uuid} + ${reps}= Delete Change Management auth schedules/${uuid} + Compare Status List ${expected_status_list} ${status_list} + Log ${status_list} +#Check Status Template +# [Arguments] ${request_file} ${template_folder} +# ${uuid}= Generate UUID +# ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} +# Check Schedule Status Pending Schedule ${uuid} + +Get Schedule Test Template + [Documentation] This function reads scheduleIds and the expected values from a text file (see robot/assets/get_schedule_UUIDs.txt for the format) then runs a get on them to confirm the GET schedule functionality #this could be enhanced with SQL query to db + [Arguments] ${existing_uuid_file} + ${uuid_file}= OperatingSystem.Get File ${existing_uuid_file} #this file works with the dev server as of 11/9/2017 + @{file_lines}= Split to Lines ${uuid_file} + &{uuid_dictionary}= Create Dictionary + :For ${line} in @{file_lines} + \ @{line_array}= Split String ${line} + \ log ${line_array[1]} + \ Set To Dictionary ${uuid_dictionary} @{line_array}[0] @{line_array}[1] #You can pass singular list items as scalar variables + \ + Log ${uuid_dictionary} + @{resp_list}= Create List + :For ${uuid} in @{uuid_dictionary.keys()} + \ ${resp}= Get Change Management auth schedules/${uuid} + \ ${actual_status}= Get from dictionary ${uuid_dictionary} ${uuid} + \ Should be equal as Strings ${actual_status} ${resp.status_code} + \ Run Keyword If ${resp.status_code} == 200 Dictionary should contain key ${resp.json()} status ELSE Dictionary Should Contain Key ${resp.json()['requestError']} messageId #${resp.json()['requestError']} this is a scalar reference to a singular item from a dictionary. + \ Append to List ${resp_list} ${resp.json()} + Log ${resp_list} +Wait For All VNFs Reach Status + [Documentation] Checks the status of the VNFs in a schedule. + [Arguments] ${status} ${uuid} + ${resp}= Get Change Management auth schedules/scheduleDetails?request.scheduleId=${uuid} + : for ${vnf} in @{resp.json()} + \ Dictionary Should Contain Item ${vnf} status Completed +Wait For All VNFs Reach Status and Add to Status + [Documentation] This records the status of the vnf in the global status list + [Arguments] ${status} ${uuid} + ${resp}= Get Change Management auth schedules/scheduleDetails?request.scheduleId=${uuid} + : for ${vnf} in @{resp.json()} + \ Dictionary Should Contain Item ${vnf} status Completed + Add to Status List Completed ${uuid} #This only runs if there are no failures in Dictionary should Contain Item for loop previously +Wait for Schedule to Complete + [Documentation] This is used in wait for keyword to succeed generally it checks if the status of the schedule returned by a GET request is Complete + [Arguments] ${status} ${uuid} + ${resp}= Get Change Management auth schedules/${uuid} + Dictionary Should Contain Item ${resp.json()} status Completed +#Check Schedule Status +# [Arguments] ${status} ${uuid} +# ${resp}= Get Change Management auth schedules/${uuid} +# Dictionary Should Contain Item ${resp.json()} status ${status} +Add To Status List + [Documentation] Takes List and Schedule ID and changes global list of Statuses #A global list was used because Wait for Keyword to Succeed only seems to return pass or fail + [Arguments] ${end_status} ${uuid} + ${resp}= Get Change Management auth schedules/${uuid} + ${json}= Stringify Json ${resp.json()} + ${status}= Get Json Value ${json} /status + ${temp_list}= Catenate ${status_list} ${status}, + ${temp_list}= Replace String ${temp_list} ${SPACE}" ${EMPTY}" + Set Global Variable ${status_list} ${temp_list} + Should Contain ${status} ${end_status} +Compare Status List + [Arguments] ${expected} ${actual} + @{expected_list}= Split String ${expected} , + @{actual_list}= Split String ${actual} , + :For ${current} in @{expected_list} + \ Should Contain ${actual_list} ${current} + +Change Management DB Failover Template + [Arguments] ${request_file} ${template_folder} ${uuid1} ${uuid2} + Set Global Variable ${NODES} ${uuid1} + Run Keyword If '${uuid2}' != 'None' Delete Change Management auth schedules/${uuid2} #Sends and checks Approval POST request + ${expected_status_code}= Convert to String 202 #Variables in keywords section have to be assigned keywords. So ${expected_status_code}= 202 + ${resp}= Create Schedule ${uuid1} ${request_file} ${template_folder} + Wait Until Keyword Succeeds 120s 5s Wait For Pending Approval ${uuid1} Optimization Failed + Should Be Equal as Strings ${resp.status_code} ${expected_status_code} diff --git a/cmso-robot/robot/resources/test_templates/change_management_ete.robot b/cmso-robot/robot/resources/test_templates/change_management_ete.robot new file mode 100644 index 0000000..74dfdc2 --- /dev/null +++ b/cmso-robot/robot/resources/test_templates/change_management_ete.robot @@ -0,0 +1,84 @@ +*** Settings *** +Documentation Creates VID VNF Instance + +Library StringTemplater +Library UUID +Library Collections +Library SSHLibrary + +Resource ../scheduler_common.robot +Resource ../json_templater.robot +Resource ../scheduler_requests/create_schedule.robot +Resource ../scheduler_requests/approval_requests.robot + +*** Variables **** +${TEMPLATES} robot/assets/templates + +*** Keywords *** +Change Management Template + [Arguments] ${request_file} ${workflow} ${minutesFromNow}=1 + ${template_folder}= Catenate ${TEMPLATES}/changemanagement + ${uuid}= Generate UUID + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} workflow=${workflow} minutesFromNow=${minutesFromNow} + Should Be Equal as Strings ${resp.status_code} 202 + Validate Acknowledgment Response Headers ${resp} + Wait Until Keyword Succeeds 600s 30s Wait For Pending Approval ${uuid} + Send Tier2 Approval ${uuid} jf9860 Accepted + ${resp}= Get Change Management auth schedules/${uuid} + Wait Until Keyword Succeeds 120s 30s Wait For All VNFs Reach Status Completed ${uuid} + Wait Until Keyword Succeeds 120s 30s Wait for Schedule to Complete Completed ${uuid} + ${reps}= Delete Change Management auth schedules/${uuid} + +Change Management Immediate Template + [Arguments] ${request_file} ${workflow} + ${template_folder}= Catenate ${TEMPLATES}/changemanagement + ${uuid}= Generate UUID + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} workflow=${workflow} + Should Be Equal as Strings ${resp.status_code} 202 + Validate Acknowledgment Response Headers ${resp} + Wait Until Keyword Succeeds 120s 30s Wait For All VNFs Reach Status Completed ${uuid} + Wait Until Keyword Succeeds 120s 30s Wait for Schedule to Complete Completed ${uuid} + ${reps}= Delete Change Management auth schedules/${uuid} + +Wait For All VNFs Reach Status + [Arguments] ${status} ${uuid} + ${resp}= Get Change Management auth schedules/scheduleDetails?request.scheduleId=${uuid} + : for ${vnf} in @{resp.json()} + \ Dictionary Should Contain Item ${vnf} status Completed + +Wait for Schedule to Complete + [Arguments] ${status} ${uuid} + ${resp}= Get Change Management auth schedules/${uuid} + Dictionary Should Contain Item ${resp.json()} status Completed + +Create and Approve + [Arguments] ${request_file} ${workflow} ${minutesFromNow}=5 + ${template_folder}= Catenate ${TEMPLATES}/changemanagement + ${uuid}= Generate UUID + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} workflow=${workflow} minutesFromNow=${minutesFromNow} + Should Be Equal as Strings ${resp.status_code} 202 + Validate Acknowledgment Response Headers ${resp} + Wait Until Keyword Succeeds 300s 5s Wait For Pending Approval ${uuid} + Send Tier2 Approval ${uuid} jf9860 Accepted + +Change Management Cancel Template + [Arguments] ${request_file} ${workflow} ${minutesFromNow}=5 + ${template_folder}= Catenate ${TEMPLATES}/changemanagement + ${uuid}= Generate UUID + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} workflow=${workflow} minutesFromNow=${minutesFromNow} + Should Be Equal as Strings ${resp.status_code} 202 + Validate Acknowledgment Response Headers ${resp} + Wait Until Keyword Succeeds 600s 5s Wait For Pending Approval ${uuid} + Send Tier2 Approval ${uuid} jf9860 Accepted + ${resp}= Delete Change Management auth schedules/${uuid} + Should Be Equal as Strings ${resp.status_code} 204 + Log ${resp.headers} + +Validate Acknowledgment Response Headers + [Arguments] ${Response} + Log ${Response.headers} + ${act_headers_keys} = Get Dictionary Keys ${Response.headers} + Dictionary Should Contain Key ${Response.headers} X-LatestVersion + Dictionary Should Contain Key ${Response.headers} X-MinorVersion + Dictionary Should Contain Key ${Response.headers} X-PatchVersion +
\ No newline at end of file diff --git a/cmso-robot/robot/resources/test_templates/check_logs.robot b/cmso-robot/robot/resources/test_templates/check_logs.robot new file mode 100644 index 0000000..5926caa --- /dev/null +++ b/cmso-robot/robot/resources/test_templates/check_logs.robot @@ -0,0 +1,95 @@ +*** Settings *** +Documentation Tests for checking ECOMP Scheduler Logs + +Library UUID +Library SSHLibrary +Library String + + +Resource ../files.robot +Resource ../scheduler_requests/create_schedule.robot +Resource ../scheduler_requests/approval_requests.robot +Resource ../json_templater.robot +*** Variables **** +${log_location}= /opt/app/ecomp-scheduler/logs/ +${debug_log_location}= /opt/app/ecomp-scheduler/debug-logs/ +${date_time_regex}= ((([0-9]{2,4}-?){3}.([0-9]{2}:?){3}.*)) +${uuid_regex}= [0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12} + +*** Keywords *** +#GENERAL Notes this +Check Audit Logs + [Documentation] This test runs Create, Get, and Delete Schedule then checks logs in the server for the result + [Arguments] ${user-id} ${user-pass} ${request_file} ${template_folder} + ${uuid}= Generate UUID + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} + ${resp}= Get Change Management auth schedules/${uuid} + ${resp}= Delete Change Management auth schedules/${uuid} + ${server}= Convert to String mtanjv9sdlg10 #This should not be hardcoded. From test_properties.py replace this with some modification of GLOBAL_SCHEDULER_HOST + ${log_level}= Convert to String (INFO|WARN|ERROR|FATAL) + ${log_msg}= Convert to String (Accepted|No Content|OK) + ${status_codes}= Convert to String (204|202|200) + ${audit_regex}= Convert to String \\|UNKNOWN\\|.*\\|ecomp-scheduler\\|.*\\|COMPLETE\\|${status codes}\\|${log_msg}\\|${uuid_regex}\\|${log_level}\\|.*\\|[0-9]{1,}\\|${server}\\|.* + #THis regex string follows the current expected audit.log structure logging guidelines as of 1710 here https://wiki.web.att.com/pages/viewpage.action?pageId=545861390 + Open Connection ${GLOBAL_SCHEDULER_HOST} port=22 + Login ${user-id} ${user-pass} #This may only work with dev server should investigate using Pageant with Robot + ${result}= Grep Local File -E '${date_time_regex}{2}\\|${uuid}${audit_regex}CREATE_SCHEDULE_REQUEST' ${log_location}audit.log + @{create_grep_result}= Split to Lines ${result} + ${result}= Grep Local File -E '${date_time_regex}{2}\\|${uuid}${audit_regex}GET_SCHEDULE_REQUEST' ${log_location}audit.log + @{get_grep_result}= Split to Lines ${result} + ${result}= Grep Local File -E '${date_time_regex}{2}\\|${uuid}${audit_regex}DELETE_SCHEDULE_REQUEST' ${log_location}audit.log + @{delete_grep_result}= Split to Lines ${result} + Close Connection + Log many ${create_grep_result} ${get_grep_result} ${delete_grep_result} + Should Contain ${create_grep_result}[1] Accepted #This is only present in logs for create schedule + Should Contain ${get_grep_result}[1] OK #This is only present in logs for get schedule + Should Contain ${delete_grep_result}[1] No Content #This is only present in logs for delete + + +Check Debug Logs + [Arguments] ${user-id} ${user-pass} ${request_file} ${template_folder} + ${uuid}= Generate UUID + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} + ${resp}= Get Change Management auth schedules/${uuid} + ${resp}= Delete Change Management auth schedules/${uuid} + Open Connection ${GLOBAL_SCHEDULER_HOST} port=22 + Login ${user-id} ${user-pass} + ${result}= Grep Local File -E '${date_time_regex}\\|${uuid}' /opt/app/ecomp-scheduler/debug-logs/debug.log + #THis regex string follows the current expected debug.log structure logging guidelines as of 1710 here https://wiki.web.att.com/pages/viewpage.action?pageId=545861390 + Close Connection + Should not be Empty ${result} + +Check Metric Logs + [Arguments] ${user-id} ${user-pass} ${request_file} ${template_folder} + ${uuid}= Generate UUID + ${resp}= Create Schedule ${uuid} ${request_file} ${template_folder} + ${resp}= Get Change Management auth schedules/${uuid} + ${resp}= Delete Change Management auth schedules/${uuid} + ${server}= Convert to String mtanjv9sdlg10 + ${log_level}= Convert to String (INFO|WARN|ERROR|FATAL) + ${log_msg}= Convert to String (Accepted|No Content|OK|[a-zA-Z]+) + ${status_codes}= Convert to String (204|202|200) + ${regex}= Convert To String \\|UNKNOWN\\|.*\\|ecomp-scheduler\\|.*\\|http://([a-zA-Z]*\.){2,}(:[0-9]{1,5})?\\|(.*/?){1,}\\|COMPLETE\\|${status codes}\\|${log_msg}\\|${uuid_regex}\\|${log_level}\\|.*\\|[0-9]{1,}\\|${server}\\|.* + #THis regex string follows the current expected metric.log structure logging guidelines as of 1710 here https://wiki.web.att.com/pages/viewpage.action?pageId=545861390 + Open Connection ${GLOBAL_SCHEDULER_HOST} port=22 + Login ${user-id} ${user-pass} + ${result}= Grep Local File '${date_time_regex}{2}\\|${uuid}${regex}' ${log_location}metrics.log + @{grep_result}= Split to Lines ${result} + Close Connection + Should Not be Empty ${grep_result} + Log ${grep_result} + + +Check Error Logs + [Arguments] ${user-id} ${user-pass} ${request_file} ${template_folder} + + Open Connection ${GLOBAL_SCHEDULER_HOST} port=22 + Login ${user-id} ${user-pass} + ${result}= Grep Local File '${date_time_regex}\\|${uuid_regex}\\|.*\\|ecomp-scheduler\\|.*\\|.*(WARN|ERROR|FATAL).*\\|.*\\|' ${log_location}error.log + #THis regex string follows the current expected error.log structure logging guidelines as of 1710 here https://wiki.web.att.com/pages/viewpage.action?pageId=545861390 + #It is difficult to generate errors that would be logged in error.log. so this only tests that any error in the log matches the expected format + @{grep_result}= Split to Lines ${result} + Close Connection + Should Not be Empty ${grep_result} + Log ${grep_result} +
\ No newline at end of file diff --git a/cmso-robot/robot/resources/vtm_common.robot b/cmso-robot/robot/resources/vtm_common.robot new file mode 100644 index 0000000..08061f5 --- /dev/null +++ b/cmso-robot/robot/resources/vtm_common.robot @@ -0,0 +1,93 @@ +*** Settings *** +Documentation The private interface for interacting with Openstack. It handles low level stuff like managing the authtoken and Openstack required fields + +Library Collections +Library RequestsLibrary +Library UUID +Library HTTPUtils +Library DateTime + +Resource misc.robot +*** Variables *** +*** Variables *** +# http://zld03290.vci.att.com:9018 +# +${CLOSE_PATH} /vtm/manageChangeRecord/v1/closeCancelChangeRecord +${CLOSE_PORT} 31127 + + +#**************** Test Case Variables ****************** + +*** Keywords *** + +vTM Query Template + [Documentation] + [Arguments] ${alias} ${offset}=0 ${numOfrows}=100 ${display}=[] ${filter}={} + ${request}= Create Dictionary offset=${offset} numOfRows=${numOfRows} displayTuple=${display} filterTuple=${filter} + Log ${request} + ${resp}= vTM Query ${alias} ${request} + [Return] ${resp} + + +vTM Query + [Documentation] + [Arguments] ${alias} ${request} + ${url}= Catenate ${GLOBAL_VTM_URL} + ${data_path}= Catenate ${GLOBAL_LISTCHANGE_PATH} + ${uuid}= Generate UUID + ${proxies}= Create Dictionary no=pass + ${session}= Create Session ${alias} ${url} verify=True + ${auth_string}= B64 Encode ${GLOBAL_VTM_USER}:${GLOBAL_VTM_PASSWORD} + #Authorization=Basic ${GLOBAL_POLICY_AUTH} ClientAuth=${GLOBAL_POLICY_CLIENTAUTH} + ${headers}= Create Dictionary Authorization=Basic ${auth_string} Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID} + ${resp}= Post Request ${alias} ${data_path} headers=${headers} data=${request} + Log Received response from vTM ${resp.text} + ${valid}= Create List 200 404 + Validate Status ${resp} ${valid} + [Return] ${resp} + + +vTM Close Ticket + [Documentation] + [Arguments] ${alias} ${ticket} ${changeClosedBy}=jf9860 + ${url}= Catenate ${GLOBAL_VTM_PROTO}://${GLOBAL_VTM_HOST}:${CLOSE_PORT} + ${data_path}= Catenate ${CLOSE_PATH} + ${uuid}= Generate UUID + ${proxies}= Create Dictionary no=pass + ${session}= Create Session ${alias} ${url} verify=True + ${auth_string}= B64 Encode ${GLOBAL_VTM_USER}:${GLOBAL_VTM_PASSWORD} + ${end}= Get Current Date result_format=epoch exclude_millis=True + ${end}= Convert To Integer ${end} + ${start}= Evaluate ${end}-60 + ${request}= Create Dictionary changeId=${ticket} status=Closed changeClosedBy=${changeClosedBy} closureCode=Successful As Scheduled + Set To Dictionary ${request} customerImpacted=Unknown actualStartDate=${start} actualEndDate=${end} + + #Authorization=Basic ${GLOBAL_POLICY_AUTH} ClientAuth=${GLOBAL_POLICY_CLIENTAUTH} + ${headers}= Create Dictionary Authorization=Basic ${auth_string} Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID} + ${resp}= Post Request ${alias} ${data_path} headers=${headers} data=${request} + Log Received response from vTM ${resp.json()} + ${valid}= Create List 200 404 + Validate Status ${resp} ${valid} + [Return] ${resp} + + +vTM Cancel Ticket + [Documentation] + [Arguments] ${alias} ${ticket} + ${url}= Catenate ${GLOBAL_VTM_PROTO}://${GLOBAL_VTM_HOST}:${CLOSE_PORT} + ${data_path}= Catenate ${CLOSE_PATH} + ${uuid}= Generate UUID + ${proxies}= Create Dictionary no=pass + ${session}= Create Session ${alias} ${url} verify=True + ${auth_string}= B64 Encode ${GLOBAL_VTM_USER}:${GLOBAL_VTM_PASSWORD} + ${end}= Get Current Date result_format=epoch exclude_millis=True + ${end}= Convert To Integer ${end} + ${start}= Evaluate ${end}-60 + ${request}= Create Dictionary changeId=${ticket} status=Closed changeClosedBy=${GLOBAL_VID_USERID} closureCode=Cancelled closingComments=Cancel requested by user + Set To Dictionary ${request} customerImpacted=No + ${headers}= Create Dictionary Authorization=Basic ${auth_string} Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID} + ${resp}= Post Request ${alias} ${data_path} headers=${headers} data=${request} + Log Received response from vTM ${resp.json()} + ${valid}= Create List 200 404 + Validate Status ${resp} ${valid} + [Return] ${resp} |