summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--jjb/calipso/calipso.yml61
-rw-r--r--jjb/compass4nfv/compass-ci-jobs.yml180
-rw-r--r--jjb/compass4nfv/compass-deploy.sh5
-rwxr-xr-xjjb/dovetail/dovetail-run.sh31
-rw-r--r--jjb/releng/automate.yml6
-rw-r--r--jjb/releng/docker-deploy.sh156
-rw-r--r--jjb/releng/opnfv-docker.yml5
-rw-r--r--jjb/xci/xci-verify-jobs.yml22
-rw-r--r--utils/push-test-logs.sh1
-rw-r--r--utils/test/reporting/api/handlers/landing.py78
-rw-r--r--utils/test/reporting/pages/app/scripts/controllers/table.controller.js504
-rw-r--r--utils/test/reporting/pages/app/scripts/factory/table.factory.js4
-rw-r--r--utils/test/reporting/pages/app/views/commons/table.html28
-rw-r--r--utils/test/testapi/opnfv_testapi/common/raises.py4
-rw-r--r--utils/test/testapi/opnfv_testapi/resources/handlers.py43
-rw-r--r--utils/test/testapi/opnfv_testapi/resources/models.py23
-rw-r--r--utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py350
-rw-r--r--utils/test/testapi/opnfv_testapi/resources/scenario_models.py7
-rw-r--r--utils/test/testapi/opnfv_testapi/router/url_mappings.py6
-rw-r--r--utils/test/testapi/opnfv_testapi/tests/unit/resources/test_base.py33
-rw-r--r--utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py118
-rw-r--r--utils/test/testapi/opnfv_testapi/tornado_swagger/swagger.py17
22 files changed, 1190 insertions, 492 deletions
diff --git a/jjb/calipso/calipso.yml b/jjb/calipso/calipso.yml
new file mode 100644
index 000000000..c808e9b3c
--- /dev/null
+++ b/jjb/calipso/calipso.yml
@@ -0,0 +1,61 @@
+- project:
+ name: calipso
+
+ project: '{name}'
+
+ jobs:
+ - 'calipso-verify-{stream}'
+
+ stream:
+ - master:
+ branch: '{stream}'
+ disabled: false
+
+- job-template:
+ name: 'calipso-verify-{stream}'
+
+ disabled: '{obj:disabled}'
+
+ parameters:
+ - project-parameter:
+ project: '{project}'
+ branch: '{branch}'
+ - 'opnfv-build-defaults'
+
+
+ scm:
+ - git-scm-gerrit
+
+ triggers:
+ - gerrit:
+ server-name: 'gerrit.opnfv.org'
+ trigger-on:
+ - patchset-created-event:
+ exclude-drafts: 'false'
+ exclude-trivial-rebase: 'false'
+ exclude-no-code-change: 'false'
+ - draft-published-event
+ - comment-added-contains-event:
+ comment-contains-value: 'recheck'
+ - comment-added-contains-event:
+ comment-contains-value: 'reverify'
+ projects:
+ - project-compare-type: 'ANT'
+ project-pattern: '{project}'
+ branches:
+ - branch-compare-type: 'ANT'
+ branch-pattern: '**/{branch}'
+
+ builders:
+ - verify-unit-tests
+
+- builder:
+ name: verify-unit-tests
+ builders:
+ - shell: |
+ #!/bin/bash
+ set -o errexit
+ set -o nounset
+ set -o pipefail
+ cd $WORKSPACE
+ PYTHONPATH=$PWD/app python3 -m unittest discover -s app/test/fetch
diff --git a/jjb/compass4nfv/compass-ci-jobs.yml b/jjb/compass4nfv/compass-ci-jobs.yml
index 4c12f199e..8b4a74bd1 100644
--- a/jjb/compass4nfv/compass-ci-jobs.yml
+++ b/jjb/compass4nfv/compass-ci-jobs.yml
@@ -87,6 +87,24 @@
- 'k8-nosdn-nofeature-ha':
disabled: false
auto-trigger-name: 'compass-{scenario}-{pod}-{stream}-trigger'
+ - 'os-nosdn-nofeature-noha':
+ disabled: false
+ auto-trigger-name: 'compass-{scenario}-{pod}-{stream}-trigger'
+ - 'os-odl_l3-nofeature-noha':
+ disabled: false
+ auto-trigger-name: 'compass-{scenario}-{pod}-{stream}-trigger'
+ - 'os-odl_l2-moon-noha':
+ disabled: false
+ auto-trigger-name: 'compass-{scenario}-{pod}-{stream}-trigger'
+ - 'os-nosdn-kvm-noha':
+ disabled: false
+ auto-trigger-name: 'compass-{scenario}-{pod}-{stream}-trigger'
+ - 'os-odl-sfc-noha':
+ disabled: false
+ auto-trigger-name: 'compass-{scenario}-{pod}-{stream}-trigger'
+ - 'os-nosdn-dpdk-noha':
+ disabled: false
+ auto-trigger-name: 'compass-{scenario}-{pod}-{stream}-trigger'
jobs:
@@ -351,6 +369,10 @@
########################
# trigger macros
########################
+
+#---------------------------
+# ha-baremetal-centos-master
+#---------------------------
- trigger:
name: 'compass-os-nosdn-nofeature-ha-baremetal-centos-master-trigger'
triggers:
@@ -400,10 +422,41 @@
triggers:
- timed: ''
+#-----------------------------
+# noha-baremetal-centos-master
+#-----------------------------
+- trigger:
+ name: 'compass-os-nosdn-nofeature-noha-baremetal-centos-master-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-odl_l3-nofeature-noha-baremetal-centos-master-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-odl_l2-moon-noha-baremetal-centos-master-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-nosdn-kvm-noha-baremetal-centos-master-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-odl-sfc-noha-baremetal-centos-master-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-nosdn-dpdk-noha-baremetal-centos-master-trigger'
+ triggers:
+ - timed: ''
+
+#--------------------
+# ha-baremetal-master
+#--------------------
- trigger:
name: 'compass-os-nosdn-nofeature-ha-baremetal-master-trigger'
triggers:
- - timed: '0 2 * * *'
+ - timed: '0 20 * * *'
- trigger:
name: 'compass-os-nosdn-openo-ha-baremetal-master-trigger'
triggers:
@@ -447,9 +500,39 @@
- trigger:
name: 'compass-os-odl-sfc-ha-baremetal-master-trigger'
triggers:
- - timed: '0 4 * * *'
+ - timed: '0 10 * * *'
+#----------------------
+# noha-baremetal-master
+#----------------------
+- trigger:
+ name: 'compass-os-nosdn-kvm-noha-baremetal-master-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-nosdn-nofeature-noha-baremetal-master-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-odl_l3-nofeature-noha-baremetal-master-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-odl_l2-moon-noha-baremetal-master-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-odl-sfc-noha-baremetal-master-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-nosdn-dpdk-noha-baremetal-master-trigger'
+ triggers:
+ - timed: ''
+#--------------------
+# ha-baremetal-danube
+#--------------------
- trigger:
name: 'compass-os-nosdn-nofeature-ha-baremetal-danube-trigger'
triggers:
@@ -499,7 +582,37 @@
triggers:
- timed: ''
+#----------------------
+# noha-baremetal-danube
+#----------------------
+- trigger:
+ name: 'compass-os-nosdn-kvm-noha-baremetal-danube-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-nosdn-nofeature-noha-baremetal-danube-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-odl_l3-nofeature-noha-baremetal-danube-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-odl_l2-moon-noha-baremetal-danube-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-odl-sfc-noha-baremetal-danube-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-nosdn-dpdk-noha-baremetal-danube-trigger'
+ triggers:
+ - timed: ''
+#------------------
+# ha-virtual-master
+#------------------
- trigger:
name: 'compass-os-nosdn-nofeature-ha-virtual-master-trigger'
triggers:
@@ -531,11 +644,11 @@
- trigger:
name: 'compass-os-odl_l2-moon-ha-virtual-master-trigger'
triggers:
- - timed: '0 22 * * *'
+ - timed: '0 12 * * *'
- trigger:
name: 'compass-os-nosdn-kvm-ha-virtual-master-trigger'
triggers:
- - timed: '0 23 * * *'
+ - timed: '0 13 * * *'
- trigger:
name: 'compass-os-nosdn-dpdk-ha-virtual-master-trigger'
triggers:
@@ -549,6 +662,37 @@
triggers:
- timed: '0 16 * * *'
+#--------------------
+# noha-virtual-master
+#--------------------
+- trigger:
+ name: 'compass-os-nosdn-kvm-noha-virtual-master-trigger'
+ triggers:
+ - timed: '0 13 * * *'
+- trigger:
+ name: 'compass-os-nosdn-nofeature-noha-virtual-master-trigger'
+ triggers:
+ - timed: '0 14 * * *'
+- trigger:
+ name: 'compass-os-odl_l3-nofeature-noha-virtual-master-trigger'
+ triggers:
+ - timed: '0 15 * * *'
+- trigger:
+ name: 'compass-os-odl_l2-moon-noha-virtual-master-trigger'
+ triggers:
+ - timed: '0 18 * * *'
+- trigger:
+ name: 'compass-os-odl-sfc-noha-virtual-master-trigger'
+ triggers:
+ - timed: '0 20 * * *'
+- trigger:
+ name: 'compass-os-nosdn-dpdk-noha-virtual-master-trigger'
+ triggers:
+ - timed: '0 11 * * *'
+
+#------------------
+# ha-virtual-danube
+#------------------
- trigger:
name: 'compass-os-nosdn-nofeature-ha-virtual-danube-trigger'
triggers:
@@ -597,3 +741,31 @@
name: 'compass-k8-nosdn-nofeature-ha-virtual-danube-trigger'
triggers:
- timed: ''
+
+#--------------------
+# noha-virtual-danube
+#--------------------
+- trigger:
+ name: 'compass-os-nosdn-kvm-noha-virtual-danube-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-nosdn-nofeature-noha-virtual-danube-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-odl_l3-nofeature-noha-virtual-danube-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-odl_l2-moon-noha-virtual-danube-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-odl-sfc-noha-virtual-danube-trigger'
+ triggers:
+ - timed: ''
+- trigger:
+ name: 'compass-os-nosdn-dpdk-noha-virtual-danube-trigger'
+ triggers:
+ - timed: ''
diff --git a/jjb/compass4nfv/compass-deploy.sh b/jjb/compass4nfv/compass-deploy.sh
index 7a5af5f5b..9d4ae5175 100644
--- a/jjb/compass4nfv/compass-deploy.sh
+++ b/jjb/compass4nfv/compass-deploy.sh
@@ -52,6 +52,11 @@ fi
if [[ "$NODE_NAME" =~ "-virtual" ]]; then
export NETWORK_CONF=$CONFDIR/vm_environment/$NODE_NAME/${NETWORK_CONF_FILE}
export DHA_CONF=$CONFDIR/vm_environment/${DEPLOY_SCENARIO}.yml
+ if [[ "${DEPLOY_SCENARIO}" =~ "-moon-noha" ]]; then
+ export VIRT_NUMBER=3
+ elif [[ "${DEPLOY_SCENARIO}" =~ "-noha" ]]; then
+ export VIRT_NUMBER=2
+ fi
else
export INSTALL_NIC=eth1
export NETWORK_CONF=$CONFDIR/hardware_environment/$NODE_NAME/${NETWORK_CONF_FILE}
diff --git a/jjb/dovetail/dovetail-run.sh b/jjb/dovetail/dovetail-run.sh
index 7bbecc129..346a1ef08 100755
--- a/jjb/dovetail/dovetail-run.sh
+++ b/jjb/dovetail/dovetail-run.sh
@@ -160,6 +160,37 @@ if [ $(docker ps | grep "opnfv/dovetail:${DOCKER_TAG}" | wc -l) == 0 ]; then
exit 1
fi
+# Modify tempest_conf.yaml file
+tempest_conf_file=${DOVETAIL_CONFIG}/tempest_conf.yaml
+if [ ${INSTALLER_TYPE} == 'compass' ]; then
+ volume_device='vdb'
+else
+ volume_device='vdc'
+fi
+
+cat << EOF >$tempest_conf_file
+
+compute:
+ min_compute_nodes: 2
+ volume_device_name: ${volume_device}
+ min_microversion: 2.2
+ max_microversion: latest
+
+compute-feature-enabled:
+ live_migration: True
+ block_migration_for_live_migration: True
+ block_migrate_cinder_iscsi: True
+ attach_encrypted_volume: True
+
+EOF
+
+echo "${tempest_conf_file}..."
+cat ${tempest_conf_file}
+
+cp_tempest_cmd="docker cp ${DOVETAIL_CONFIG}/tempest_conf.yaml $container_id:/home/opnfv/dovetail/dovetail/userconfig"
+echo "exec command: ${cp_tempest_cmd}"
+$cp_tempest_cmd
+
list_cmd="dovetail list ${TESTSUITE}"
run_cmd="dovetail run --testsuite ${TESTSUITE} -d"
echo "Container exec command: ${list_cmd}"
diff --git a/jjb/releng/automate.yml b/jjb/releng/automate.yml
index d12ee5d68..c6ca37fa9 100644
--- a/jjb/releng/automate.yml
+++ b/jjb/releng/automate.yml
@@ -237,16 +237,16 @@
name: 'testapi-automate-docker-deploy-macro'
builders:
- shell: |
- bash ./jjb/releng/docker-deploy.sh "sudo docker run -dti -p 8082:8000
+ sudo bash ./jjb/releng/docker-deploy.sh "sudo docker run -dti --name testapi -p 8082:8000
-e mongodb_url=mongodb://172.17.0.1:27017
-e base_url=http://testresults.opnfv.org/test opnfv/testapi" \
- "http://testresults.opnfv.org/test/swagger/APIs" "testapi"
+ "http://testresults.opnfv.org/test/" "testapi"
- builder:
name: 'reporting-automate-docker-deploy-macro'
builders:
- shell: |
- bash ./jjb/releng/docker-deploy.sh "sudo docker run -itd -p 8084:8000 opnfv/reporting" \
+ sudo bash ./jjb/releng/docker-deploy.sh "sudo docker run -itd --name reporting -p 8084:8000 opnfv/reporting" \
"http://testresults.opnfv.org/reporting2/reporting/index.html" "reporting"
- builder:
diff --git a/jjb/releng/docker-deploy.sh b/jjb/releng/docker-deploy.sh
index 2a3e078ae..1e8357717 100644
--- a/jjb/releng/docker-deploy.sh
+++ b/jjb/releng/docker-deploy.sh
@@ -16,89 +16,137 @@
# specific language governing permissions and limitations *
# under the License. *
-# Assigning Variables
+
command=$1
url=$2
module=$3
-function check() {
+REPO="opnfv"
+latest_image=$REPO/$module:latest
+old_image=$REPO/$module:old
+latest_container_name=$module
+old_container_name=$module"_old"
+latest_container_id=
+old_container_id=
+new_start_container=
+
+function DEBUG() {
+ echo `date "+%Y-%m-%d %H:%M:%S.%N"` ": $1"
+}
- # Verify hosted
+function check_connectivity() {
+ # check update status via test the connectivity of provide url
sleep 5
cmd=`curl -s --head --request GET ${url} | grep '200 OK' > /dev/null`
rc=$?
- echo $rc
-
- if [[ $rc == 0 ]]
- then
+ DEBUG $rc
+ if [[ $rc == 0 ]]; then
return 0
else
return 1
fi
-
}
-echo "Getting contianer Id of the currently running one"
-contId=$(sudo docker ps | grep "opnfv/${module}:latest" | awk '{print $1}')
-
-echo $contId
-echo "Pulling the latest image"
-sudo docker pull opnfv/${module}:latest
+function pull_latest_image() {
+ DEBUG "pull latest image $latest_image"
+ docker pull $latest_image
+}
-echo "Deleting old containers of opnfv/${module}:old"
-sudo docker ps -a | grep "opnfv/${module}" | grep "old" | awk '{print $1}' | xargs -r sudo docker rm -f
+function get_latest_running_container() {
+ latest_container_id=`docker ps -q --filter name=^/$latest_container_name$`
+}
-echo "Deleting old images of opnfv/${module}:latest"
-sudo docker images | grep "opnfv/${module}" | grep "old" | awk '{print $3}' | xargs -r sudo docker rmi -f
+function get_old_running_container() {
+ old_container_id=`docker ps -q --filter name=^/$old_container_name$`
+}
+function delete_old_image() {
+ DEBUG "delete old image: $old_image"
+ docker rmi -f $old_image
+}
-if [[ -z "$contId" ]]
-then
- echo "No running ${module} container"
+function delete_old_container() {
+ DEBUG "delete old container: $old_container_name"
+ docker ps -a -q --filter name=^/$old_container_name$ | xargs docker rm -f &>/dev/null
+}
- echo "Removing stopped ${module} containers in the previous iterations"
- sudo docker ps -f status=exited | grep "opnfv_${module}" | awk '{print $1}' | xargs -r sudo docker rm -f
-else
- echo $contId
+function delete_latest_container() {
+ DEBUG "delete latest container: $module"
+ docker ps -a -q --filter name=^/$latest_container_name$ | xargs docker rm -f &>/dev/null
+}
- echo "Get the image id of the currently running conatiner"
- currImgId=$(sudo docker ps | grep "$contId" | awk '{print $2}')
- echo $currImgId
+function delete_latest_image() {
+ DEBUG "delete latest image: $REPO/$module:latest"
+ docker rmi -f $latest_image
+}
- if [[ -z "$currImgId" ]]
- then
- echo "No image id found for the container id"
- exit 1
- fi
+function change_image_tag_2_old() {
+ DEBUG "change image tag 2 old"
+ docker tag $latest_image $old_image
+ docker rmi -f $latest_image
+}
- echo "Changing current image tag to old"
- sudo docker tag "$currImgId" opnfv/${module}:old
+function mark_latest_container_2_old() {
+ DEBUG "mark latest container to be old"
+ docker rename "$latest_container_name" "$old_container_name"
+}
- echo "Removing stopped ${module} containers in the previous iteration"
- sudo docker ps -f status=exited | grep "opnfv_${module}" | awk '{print $1}' | xargs -r sudo docker rm -f
+function stop_old_container() {
+ DEBUG "stop old container"
+ docker stop "$old_container_name"
+}
- echo "Renaming the running container name to opnfv_${module} as to identify it."
- sudo docker rename $contId opnfv_${module}
+function run_latest_image() {
+ new_start_container=`$command`
+ DEBUG "run latest image: $new_start_container"
+}
- echo "Stop the currently running container"
- sudo docker stop $contId
+get_latest_running_container
+get_old_running_container
+
+if [[ ! -z $latest_container_id ]]; then
+ DEBUG "latest container is running: $latest_container_id"
+ delete_old_container
+ delete_old_image
+ change_image_tag_2_old
+ mark_latest_container_2_old
+ pull_latest_image
+ stop_old_container
+ run_latest_image
+
+elif [[ ! -z $old_container_id ]]; then
+ DEBUG "old container is running: $old_container_id"
+ delete_latest_container
+ delete_latest_image
+ pull_latest_image
+ stop_old_container
+ run_latest_image
+else
+ DEBUG "no container is running"
+ delete_old_container
+ delete_old_image
+ delete_latest_container
+ delete_latest_image
+ pull_latest_image
+ run_latest_image
fi
-echo "Running a container with the new image"
-$command:latest
-
-if check; then
- echo "TestResults Module Hosted."
+if check_connectivity; then
+ DEBUG "CONGRATS: $module update successfully"
else
- echo "TestResults Module Failed"
- if [[ $(sudo docker images | grep "opnfv/${module}" | grep "old" | awk '{print $3}') ]]; then
- echo "Running old Image"
- $command:old
- exit 1
+ DEBUG "ATTENTION: $module update failed"
+ id=`docker ps -a -q --filter name=^/$old_container_name$`
+ if [[ ! -z $id ]]; then
+ DEBUG "start old container instead"
+ docker stop $new_start_container
+ docker start $id
+ fi
+ if ! check_connectivity; then
+ DEBUG "BIG ISSUE: no container is running normally"
fi
+ exit 1
fi
-# Echo Images and Containers
-sudo docker images
-sudo docker ps -a
+docker images
+docker ps -a
diff --git a/jjb/releng/opnfv-docker.yml b/jjb/releng/opnfv-docker.yml
index 7e605b9cb..9d27329ed 100644
--- a/jjb/releng/opnfv-docker.yml
+++ b/jjb/releng/opnfv-docker.yml
@@ -70,6 +70,11 @@
dockerdir: 'docker/storperf-reporting'
<<: *master
<<: *other-receivers
+ - 'storperf-swaggerui':
+ project: 'storperf'
+ dockerdir: 'docker/storperf-swaggerui'
+ <<: *master
+ <<: *other-receivers
- 'yardstick':
project: 'yardstick'
<<: *master
diff --git a/jjb/xci/xci-verify-jobs.yml b/jjb/xci/xci-verify-jobs.yml
index 6bc064253..8d1ee55a4 100644
--- a/jjb/xci/xci-verify-jobs.yml
+++ b/jjb/xci/xci-verify-jobs.yml
@@ -109,6 +109,10 @@
- label:
name: SLAVE_LABEL
default: 'xci-virtual-{distro}'
+ - string:
+ name: GIT_BASE
+ default: https://gerrit.opnfv.org/gerrit/$PROJECT
+ description: 'Git URL to use on this Jenkins Slave'
builders:
- description-setter:
@@ -130,7 +134,7 @@
condition: SUCCESSFUL
projects:
- name: 'xci-verify-healthcheck-{type}-{stream}'
- current-parameters: false
+ current-parameters: true
predefined-parameters: |
DISTRO={distro}
DEPLOY_SCENARIO=os-nosdn-nofeature-noha
@@ -162,7 +166,7 @@
parameters:
- string:
name: DISTRO
- default: '{distro}'
+ default: 'xenial'
- string:
name: DEPLOY_SCENARIO
default: 'os-nosdn-nofeature-noha'
@@ -173,11 +177,15 @@
name: XCI_FLAVOR
default: 'mini'
- string:
- name: XCI_DEVEL_ROOT
- default: $WORKSPACE
+ name: OPNFV_RELENG_DEV_PATH
+ default: $WORKSPACE/
- string:
name: ANSIBLE_VERBOSITY
default: '-vvvv'
+ - string:
+ name: GIT_BASE
+ default: https://gerrit.opnfv.org/gerrit/$PROJECT
+ description: 'Git URL to use on this Jenkins Slave'
wrappers:
- ssh-agent-wrapper
@@ -202,7 +210,11 @@
- shell: |
#!/bin/bash
- cd $WORKSPACE
+ # for some reason, the PATH is not set correctly
+ # setting PATH for ansible stuff
+ export PATH=/home/jenkins/.local/bin:$PATH
+
+ cd $WORKSPACE/xci
./xci-deploy.sh
- builder:
diff --git a/utils/push-test-logs.sh b/utils/push-test-logs.sh
index eb57deb7b..79190ec2f 100644
--- a/utils/push-test-logs.sh
+++ b/utils/push-test-logs.sh
@@ -31,6 +31,7 @@ node_list=(\
'huawei-pod1' 'huawei-pod2' 'huawei-pod3' 'huawei-pod4' 'huawei-pod5' \
'huawei-pod6' 'huawei-pod7' 'huawei-pod12' \
'huawei-virtual1' 'huawei-virtual2' 'huawei-virtual3' 'huawei-virtual4' \
+'huawei-virtual5' 'huawei-virtual8' 'huawei-virtual9' \
'zte-pod2' \
'zte-virtual1')
diff --git a/utils/test/reporting/api/handlers/landing.py b/utils/test/reporting/api/handlers/landing.py
index 749916fb6..0bf602dc9 100644
--- a/utils/test/reporting/api/handlers/landing.py
+++ b/utils/test/reporting/api/handlers/landing.py
@@ -7,6 +7,7 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
import requests
+import time
from tornado.escape import json_encode
from tornado.escape import json_decode
@@ -24,7 +25,7 @@ class FiltersHandler(BaseHandler):
'status': ['success', 'warning', 'danger'],
'projects': ['functest', 'yardstick'],
'installers': ['apex', 'compass', 'fuel', 'joid'],
- 'version': ['colorado', 'master'],
+ 'version': ['master', 'colorado', 'danube'],
'loops': ['daily', 'weekly', 'monthly'],
'time': ['10 days', '30 days']
}
@@ -53,27 +54,27 @@ class ScenariosHandler(BaseHandler):
def _get_scenario_result(self, scenario, data, args):
result = {
'status': data.get('status'),
- 'installers': self._get_installers_result(data['installers'], args)
+ 'installers': self._get_installers_result(data, args)
}
return result
def _get_installers_result(self, data, args):
func = self._get_installer_result
- return {k: func(k, data.get(k, {}), args) for k in args['installers']}
+ return {k: func(data.get(k, {}), args) for k in args['installers']}
- def _get_installer_result(self, installer, data, args):
- projects = data.get(args['version'], [])
- return [self._get_project_data(projects, p) for p in args['projects']]
+ def _get_installer_result(self, data, args):
+ return self._get_version_data(data.get(args['version'], {}), args)
- def _get_project_data(self, projects, project):
+ def _get_version_data(self, data, args):
+ return {k: self._get_project_data(data.get(k, {}))
+ for k in args['projects']}
+
+ def _get_project_data(self, data):
atom = {
- 'project': project,
- 'score': None,
- 'status': None
+ 'score': data.get('score', ''),
+ 'status': data.get('status', '')
}
- for p in projects:
- if p['project'] == project:
- return p
+
return atom
def _get_scenarios(self):
@@ -88,41 +89,42 @@ class ScenariosHandler(BaseHandler):
[])
) for a in data}
scenario = {
- 'status': self._get_status(),
- 'installers': installers
+ 'status': self._get_status()
}
+ scenario.update(installers)
+
return scenario
def _get_status(self):
return 'success'
def _get_installer(self, data):
- return {a.get('version'): self._get_version(a) for a in data}
+ return {a.get('version'): self._get_version(a.get('projects'))
+ for a in data}
def _get_version(self, data):
+ return {a.get('project'): self._get_project(a) for a in data}
+
+ def _get_project(self, data):
+ scores = data.get('scores', [])
+ trusts = data.get('trust_indicators', [])
+
try:
- scores = data.get('score', {}).get('projects')[0]
- trusts = data.get('trust_indicator', {}).get('projects')[0]
- except (TypeError, IndexError):
- return []
- else:
- scores = {key: [dict(date=a.get('date')[:10],
- score=a.get('score')
- ) for a in scores[key]] for key in scores}
- trusts = {key: [dict(date=a.get('date')[:10],
- status=a.get('status')
- ) for a in trusts[key]] for key in trusts}
- atom = self._get_atom(scores, trusts)
- return [dict(project=k,
- score=sorted(atom[k], reverse=True)[0].get('score'),
- status=sorted(atom[k], reverse=True)[0].get('status')
- ) for k in atom if atom[k]]
-
- def _get_atom(self, scores, trusts):
- s = {k: {a['date']: a['score'] for a in scores[k]} for k in scores}
- t = {k: {a['date']: a['status'] for a in trusts[k]} for k in trusts}
- return {k: [dict(score=s[k][a], status=t[k][a], data=a
- ) for a in s[k] if a in t[k]] for k in s}
+ date = sorted(scores, reverse=True)[0].get('date')
+ except IndexError:
+ data = time.time()
+
+ try:
+ score = sorted(scores, reverse=True)[0].get('score')
+ except IndexError:
+ score = None
+
+ try:
+ status = sorted(trusts, reverse=True)[0].get('status')
+ except IndexError:
+ status = None
+
+ return {'date': date, 'score': score, 'status': status}
def _change_to_utf8(self, obj):
if isinstance(obj, dict):
diff --git a/utils/test/reporting/pages/app/scripts/controllers/table.controller.js b/utils/test/reporting/pages/app/scripts/controllers/table.controller.js
index 44d9441de..8d494c3ae 100644
--- a/utils/test/reporting/pages/app/scripts/controllers/table.controller.js
+++ b/utils/test/reporting/pages/app/scripts/controllers/table.controller.js
@@ -11,396 +11,268 @@ angular.module('opnfvApp')
.controller('TableController', ['$scope', '$state', '$stateParams', '$http', 'TableFactory', '$timeout',
function($scope, $state, $stateParams, $http, TableFactory, $timeout) {
- $scope.filterlist = [];
- $scope.selection = [];
- $scope.statusList = [];
- $scope.projectList = [];
- $scope.installerList = [];
- $scope.versionlist = [];
- $scope.loopci = [];
- $scope.time = [];
- $scope.tableDataAll = {};
- $scope.tableInfoAll = {};
- $scope.scenario = {};
- // $scope.selectProjects = [];
-
-
- $scope.VersionConfig = {
- create: true,
- valueField: 'title',
- labelField: 'title',
- delimiter: '|',
- maxItems: 1,
- placeholder: 'Version',
- onChange: function(value) {
- checkElementArrayValue($scope.selection, $scope.VersionOption);
- $scope.selection.push(value);
- // console.log($scope.selection);
- getScenarioData();
+ init();
- }
- }
+ function init() {
+ $scope.filterlist = [];
+ $scope.selection = [];
- $scope.LoopConfig = {
- create: true,
- valueField: 'title',
- labelField: 'title',
- delimiter: '|',
- maxItems: 1,
- placeholder: 'Loop',
- onChange: function(value) {
- checkElementArrayValue($scope.selection, $scope.LoopOption);
- $scope.selection.push(value);
- // console.log($scope.selection);
- getScenarioData();
+ $scope.statusList = [];
+ $scope.projectList = [];
+ $scope.installerList = [];
+ $scope.versionlist = [];
+ $scope.loopList = [];
+ $scope.timeList = [];
- }
- }
+ $scope.selectStatus = [];
+ $scope.selectProjects = [];
+ $scope.selectInstallers = [];
+ $scope.selectVersion = null;
+ $scope.selectLoop = null;
+ $scope.selectTime = null;
+
+ $scope.statusClicked = false;
+ $scope.installerClicked = false;
+ $scope.projectClicked = false;
- $scope.TimeConfig = {
- create: true,
- valueField: 'title',
- labelField: 'title',
- delimiter: '|',
- maxItems: 1,
- placeholder: 'Time',
- onChange: function(value) {
- checkElementArrayValue($scope.selection, $scope.TimeOption);
- $scope.selection.push(value);
- // console.log($scope.selection)
- getScenarioData();
+ $scope.scenarios = {};
+ $scope.VersionConfig = {
+ create: true,
+ valueField: 'title',
+ labelField: 'title',
+ delimiter: '|',
+ maxItems: 1,
+ placeholder: 'Version',
+ onChange: function(value) {
+ $scope.selectVersion = value;
+ getScenarioData();
+
+ }
}
- }
+ $scope.LoopConfig = {
+ create: true,
+ valueField: 'title',
+ labelField: 'title',
+ delimiter: '|',
+ maxItems: 1,
+ placeholder: 'Loop',
+ onChange: function(value) {
+ $scope.selectLoop = value;
- init();
+ getScenarioData();
+
+ }
+ }
+
+ $scope.TimeConfig = {
+ create: true,
+ valueField: 'title',
+ labelField: 'title',
+ delimiter: '|',
+ maxItems: 1,
+ placeholder: 'Time',
+ onChange: function(value) {
+ $scope.selectTime = value;
+
+ getScenarioData();
+ }
+ }
- function init() {
- $scope.toggleSelection = toggleSelection;
- getScenarioData();
getFilters();
}
function getFilters() {
TableFactory.getFilter().get({
-
}).$promise.then(function(response) {
if (response != null) {
$scope.statusList = response.filters.status;
$scope.projectList = response.filters.projects;
$scope.installerList = response.filters.installers;
- $scope.versionlist = response.filters.version;
- $scope.loopci = response.filters.loops;
- $scope.time = response.filters.time;
-
- $scope.statusListString = $scope.statusList.toString();
- $scope.projectListString = $scope.projectList.toString();
- $scope.installerListString = $scope.installerList.toString();
- $scope.VersionSelected = $scope.versionlist[1];
- $scope.LoopCiSelected = $scope.loopci[0];
- $scope.TimeSelected = $scope.time[0];
- radioSetting($scope.versionlist, $scope.loopci, $scope.time);
+ $scope.versionList = toSelectList(response.filters.version);
+ $scope.loopList = toSelectList(response.filters.loops);
+ $scope.timeList = toSelectList(response.filters.time);
+
+ $scope.selectStatus = copy($scope.statusList);
+ $scope.selectInstallers = copy($scope.installerList);
+ $scope.selectProjects = copy($scope.projectList);
+ $scope.selectVersion = response.filters.version[0];
+ $scope.selectLoop = response.filters.loops[0];
+ $scope.selectTime = response.filters.time[0];
+
+ getScenarioData();
} else {
- alert("网络错误");
}
- })
+ });
+ }
+
+ function toSelectList(arr){
+ var tempList = [];
+ angular.forEach(arr, function(ele){
+ tempList.push({'title': ele});
+ });
+ return tempList;
+ }
+
+ function copy(arr){
+ var tempList = [];
+ angular.forEach(arr, function(ele){
+ tempList.push(ele);
+ });
+ return tempList;
}
function getScenarioData() {
- // var utl = BASE_URL + '/scenarios';
var data = {
- 'status': ['success', 'danger', 'warning'],
- 'projects': ['functest', 'yardstick'],
- 'installers': ['apex', 'compass', 'fuel', 'joid'],
- 'version': $scope.VersionSelected,
- 'loops': $scope.LoopCiSelected,
- 'time': $scope.TimeSelected
+ 'status': $scope.selectStatus,
+ 'projects': $scope.selectProjects,
+ 'installers': $scope.selectInstallers,
+ 'version': $scope.selectVersion,
+ 'loops': $scope.selectLoop,
+ 'time': $scope.selectTime
};
TableFactory.getScenario(data).then(function(response) {
if (response.status == 200) {
- $scope.scenario = response.data;
-
- reSettingcolspan();
+ $scope.scenarios = response.data.scenarios;
+ getScenario();
}
}, function(error) {
-
- })
+ });
}
- function reSettingcolspan() {
- if ($scope.selectProjects == undefined || $scope.selectProjects == null) {
- constructJson();
- $scope.colspan = $scope.tableDataAll.colspan;
+ function getScenario(){
- } else {
- constructJson();
- $scope.colspan = $scope.tempColspan;
- }
- // console.log("test")
- }
-
- //construct json
- function constructJson(selectProject) {
+ $scope.project_row = [];
+ angular.forEach($scope.selectInstallers, function(installer){
+ angular.forEach($scope.selectProjects, function(project){
+ var temp = {
+ 'installer': installer,
+ 'project': project
+ }
+ $scope.project_row.push(temp);
- var colspan;
- var InstallerData;
- var projectsInfo;
- $scope.tableDataAll["scenario"] = [];
+ });
+ });
- for (var item in $scope.scenario.scenarios) {
+ $scope.scenario_rows = [];
+ angular.forEach($scope.scenarios, function(scenario, name){
+ var scenario_row = {
+ 'name': null,
+ 'status': null,
+ 'statusDisplay': null,
+ 'datadisplay': [],
+ };
+ scenario_row.name = name;
+ scenario_row.status = scenario.status;
- var headData = Object.keys($scope.scenario.scenarios[item].installers).sort();
- var scenarioStatus = $scope.scenario.scenarios[item].status;
var scenarioStatusDisplay;
- if (scenarioStatus == "success") {
+ if (scenario.status == "success") {
scenarioStatusDisplay = "navy";
- } else if (scenarioStatus == "danger") {
+ } else if (scenario.status == "danger") {
scenarioStatusDisplay = "danger";
- } else if (scenarioStatus == "warning") {
+ } else if (scenario.status == "warning") {
scenarioStatusDisplay = "warning";
}
-
- InstallerData = headData;
- var projectData = [];
- var datadisplay = [];
- var projects = [];
-
- for (var j = 0; j < headData.length; j++) {
-
- projectData.push($scope.scenario.scenarios[item].installers[headData[j]]);
- }
- for (var j = 0; j < projectData.length; j++) {
-
- for (var k = 0; k < projectData[j].length; k++) {
- projects.push(projectData[j][k].project);
- var temArray = [];
- if (projectData[j][k].score == null) {
- temArray.push("null");
- temArray.push(projectData[j][k].project);
- temArray.push(headData[j]);
- } else {
- temArray.push(projectData[j][k].score);
- temArray.push(projectData[j][k].project);
- temArray.push(headData[j]);
- }
-
-
- if (projectData[j][k].status == "platinium") {
- temArray.push("primary");
- temArray.push("P");
- } else if (projectData[j][k].status == "gold") {
- temArray.push("danger");
- temArray.push("G");
- } else if (projectData[j][k].status == "silver") {
- temArray.push("warning");
- temArray.push("S");
- } else if (projectData[j][k].status == null) {
- temArray.push("null");
+ scenario_row.statusDisplay = scenarioStatusDisplay;
+
+ angular.forEach($scope.selectInstallers, function(installer){
+ angular.forEach($scope.selectProjects, function(project){
+ var datadisplay = {
+ 'installer': null,
+ 'project': null,
+ 'value': null,
+ 'label': null,
+ 'label_value': null
+ };
+ datadisplay.installer = installer;
+ datadisplay.project = project;
+ datadisplay.value = scenario.installers[installer][project].score;
+
+ var single_status = scenario.installers[installer][project].status;
+ if (single_status == "platinium") {
+ datadisplay.label = 'primary';
+ datadisplay.label_value = 'P';
+ } else if (single_status == "gold") {
+ datadisplay.label = 'danger';
+ datadisplay.label_value = 'G';
+ } else if (single_status == "silver") {
+ datadisplay.label = 'warning';
+ datadisplay.label_value = 'S';
+ } else if (single_status == null) {
}
+ scenario_row.datadisplay.push(datadisplay);
- datadisplay.push(temArray);
-
- }
-
- }
-
- colspan = projects.length / headData.length;
-
- var tabledata = {
- scenarioName: item,
- Installer: InstallerData,
- projectData: projectData,
- projects: projects,
- datadisplay: datadisplay,
- colspan: colspan,
- status: scenarioStatus,
- statusDisplay: scenarioStatusDisplay
- };
-
- JSON.stringify(tabledata);
- $scope.tableDataAll.scenario.push(tabledata);
-
-
- // console.log(tabledata);
-
- }
-
-
- projectsInfo = $scope.tableDataAll.scenario[0].projects;
-
- var tempHeadData = [];
-
- for (var i = 0; i < InstallerData.length; i++) {
- for (var j = 0; j < colspan; j++) {
- tempHeadData.push(InstallerData[i]);
- }
- }
-
- //console.log(tempHeadData);
-
- var projectsInfoAll = [];
-
- for (var i = 0; i < projectsInfo.length; i++) {
- var tempA = [];
- tempA.push(projectsInfo[i]);
- tempA.push(tempHeadData[i]);
- projectsInfoAll.push(tempA);
-
- }
- //console.log(projectsInfoAll);
-
- $scope.tableDataAll["colspan"] = colspan;
- $scope.tableDataAll["Installer"] = InstallerData;
- $scope.tableDataAll["Projects"] = projectsInfoAll;
-
- // console.log($scope.tableDataAll);
- $scope.colspan = $scope.tableDataAll.colspan;
- console.log($scope.tableDataAll);
-
- }
-
- //get json element size
- function getSize(jsondata) {
- var size = 0;
- for (var item in jsondata) {
- size++;
- }
- return size;
+ });
+ });
+ $scope.scenario_rows.push(scenario_row);
+ });
}
- // console.log($scope.colspan);
-
-
- //find all same element index
- function getSameElementIndex(array, element) {
- var indices = [];
- var idx = array.indexOf(element);
- while (idx != -1) {
- indices.push(idx);
- idx = array.indexOf(element, idx + 1);
+ function clickBase(eleList, ele){
+ var idx = eleList.indexOf(ele);
+ if(idx > -1){
+ eleList.splice(idx, 1);
+ }else{
+ eleList.push(ele);
}
- //return indices;
- var result = { element: element, index: indices };
- JSON.stringify(result);
- return result;
}
- //delete element in array
- function deletElement(array, index) {
- array.splice(index, 1);
+ $scope.clickStatus = function(status){
+ if($scope.selectStatus.length == $scope.statusList.length && $scope.statusClicked == false){
+ $scope.selectStatus = [];
+ $scope.statusClicked = true;
+ }
- }
+ clickBase($scope.selectStatus, status);
- function radioSetting(array1, array2, array3) {
- var tempVersion = [];
- var tempLoop = [];
- var tempTime = [];
- for (var i = 0; i < array1.length; i++) {
- var temp = {
- title: array1[i]
- };
- tempVersion.push(temp);
- }
- for (var i = 0; i < array2.length; i++) {
- var temp = {
- title: array2[i]
- };
- tempLoop.push(temp);
+ if($scope.selectStatus.length == 0 && $scope.statusClicked == true){
+ $scope.selectStatus = copy($scope.statusList);
+ $scope.statusClicked = false;
}
- for (var i = 0; i < array3.length; i++) {
- var temp = {
- title: array3[i]
- };
- tempTime.push(temp);
- }
- $scope.VersionOption = tempVersion;
- $scope.LoopOption = tempLoop;
- $scope.TimeOption = tempTime;
- }
- //remove element in the array
- function removeArrayValue(arr, value) {
- for (var i = 0; i < arr.length; i++) {
- if (arr[i] == value) {
- arr.splice(i, 1);
- break;
- }
- }
+ getScenarioData();
}
- //check if exist element
- function checkElementArrayValue(arrayA, arrayB) {
- for (var i = 0; i < arrayB.length; i++) {
- if (arrayA.indexOf(arrayB[i].title) > -1) {
- removeArrayValue(arrayA, arrayB[i].title);
- }
+ $scope.clickInstaller = function(installer){
+ if($scope.selectInstallers.length == $scope.installerList.length && $scope.installerClicked == false){
+ $scope.selectInstallers = [];
+ $scope.installerClicked = true;
}
- }
- function toggleSelection(status) {
- var idx = $scope.selection.indexOf(status);
+ clickBase($scope.selectInstallers, installer);
- if (idx > -1) {
- $scope.selection.splice(idx, 1);
- filterData($scope.selection)
- } else {
- $scope.selection.push(status);
- filterData($scope.selection)
+ if($scope.selectInstallers.length == 0 && $scope.installerClicked == true){
+ $scope.selectInstallers = copy($scope.installerList);
+ $scope.installerClicked = false;
}
- // console.log($scope.selection);
+ getScenarioData();
}
- //filter function
- function filterData(selection) {
-
- $scope.selectInstallers = [];
- $scope.selectProjects = [];
- $scope.selectStatus = [];
- for (var i = 0; i < selection.length; i++) {
- if ($scope.statusListString.indexOf(selection[i]) > -1) {
- $scope.selectStatus.push(selection[i]);
- }
- if ($scope.projectListString.indexOf(selection[i]) > -1) {
- $scope.selectProjects.push(selection[i]);
- }
- if ($scope.installerListString.indexOf(selection[i]) > -1) {
- $scope.selectInstallers.push(selection[i]);
- }
+ $scope.clickProject = function(project){
+ if($scope.selectProjects.length == $scope.projectList.length && $scope.projectClicked == false){
+ $scope.selectProjects = [];
+ $scope.projectClicked = true;
}
+ clickBase($scope.selectProjects, project);
- // $scope.colspan = $scope.selectProjects.length;
- //when some selection is empty, we set it full
- if ($scope.selectInstallers.length == 0) {
- $scope.selectInstallers = $scope.installerList;
-
- }
- if ($scope.selectProjects.length == 0) {
- $scope.selectProjects = $scope.projectList;
- $scope.colspan = $scope.tableDataAll.colspan;
- } else {
- $scope.colspan = $scope.selectProjects.length;
- $scope.tempColspan = $scope.colspan;
- }
- if ($scope.selectStatus.length == 0) {
- $scope.selectStatus = $scope.statusList
+ if($scope.selectProjects.length == 0 && $scope.projectClicked == true){
+ $scope.selectProjects = copy($scope.projectList);
+ $scope.projectClicked = false;
}
- // console.log($scope.selectStatus);
- // console.log($scope.selectProjects);
-
+ getScenarioData();
}
-
}
- ]); \ No newline at end of file
+ ]);
diff --git a/utils/test/reporting/pages/app/scripts/factory/table.factory.js b/utils/test/reporting/pages/app/scripts/factory/table.factory.js
index f0af34fb2..e715c5c28 100644
--- a/utils/test/reporting/pages/app/scripts/factory/table.factory.js
+++ b/utils/test/reporting/pages/app/scripts/factory/table.factory.js
@@ -28,7 +28,7 @@ angular.module('opnfvApp')
}
});
},
- getScenario: function() {
+ getScenario: function(data) {
var config = {
headers: {
@@ -36,7 +36,7 @@ angular.module('opnfvApp')
}
}
- return $http.post(BASE_URL + '/landing-page/scenarios', {}, config);
+ return $http.post(BASE_URL + '/landing-page/scenarios', data, config);
},
diff --git a/utils/test/reporting/pages/app/views/commons/table.html b/utils/test/reporting/pages/app/views/commons/table.html
index f504bd76b..a33c48312 100644
--- a/utils/test/reporting/pages/app/views/commons/table.html
+++ b/utils/test/reporting/pages/app/views/commons/table.html
@@ -29,9 +29,9 @@
<div class=" col-md-12" data-toggle="buttons" aria-pressed="false">
<label> Status </label> &nbsp;&nbsp; &nbsp;
- <label class="btn btn-outline btn-success btn-sm" style="height:25px; margin-right: 5px;" ng-repeat="status in statusList" value={{status}} ng-checked="selection.indexOf(status)>-1" ng-click="toggleSelection(status)">
+ <label class="btn btn-outline btn-success btn-sm" style="height:25px; margin-right: 5px;" ng-repeat="status in statusList" value={{status}} ng-checked="selectStatus.indexOf(status)>-1" ng-click="clickStatus(status)">
<input type="checkbox" disabled="disabled" > {{status}}
-
+
</label>
</div>
@@ -39,7 +39,7 @@
<div class=" col-md-12" data-toggle="buttons">
<label> Projects </label> &nbsp;
- <label class="btn btn-outline btn-success btn-sm " style="height:25px;margin-right: 5px;" ng-repeat="project in projectList" value={{project}} ng-checked="selection.indexOf(project)>-1" ng-click="toggleSelection(project)">
+ <label class="btn btn-outline btn-success btn-sm " style="height:25px;margin-right: 5px;" ng-repeat="project in projectList" value={{project}} ng-checked="selectProjects.indexOf(project)>-1" ng-click="clickProject(project)">
<input type="checkbox" disabled="disabled"> {{project}}
</label>
@@ -47,7 +47,7 @@
<hr class="myhr">
<div class=" col-md-12" data-toggle="buttons">
<label> Installers </label>
- <label class="btn btn-outline btn-success btn-sm" style="height:25px;margin-right: 5px;" ng-repeat="installer in installerList" value={{installer}} ng-checked="selection.indexOf(installer)>-1" ng-click="toggleSelection(installer)">
+ <label class="btn btn-outline btn-success btn-sm" style="height:25px;margin-right: 5px;" ng-repeat="installer in installerList" value={{installer}} ng-checked="selectInstallers.indexOf(installer)>-1" ng-click="clickInstaller(installer)">
<input type="checkbox" disabled="disabled"> {{installer}}
</label>
</div>
@@ -56,17 +56,17 @@
<div class=" col-md-1" style="margin-top:5px;margin-right: 5px;">
- <selectize options="VersionOption" ng-model="VersionSelected" config="VersionConfig"></selectize>
+ <selectize options="versionList" ng-model="selectVersion" config="VersionConfig"></selectize>
</div>
<div class=" col-md-1" style="margin-top:5px;margin-right: 5px;">
- <selectize options="LoopOption" ng-model="LoopCiSelected" config="LoopConfig"></selectize>
+ <selectize options="loopList" ng-model="selectLoop" config="LoopConfig"></selectize>
</div>
<div class=" col-md-1" style="margin-top:5px;margin-right: 5px;">
- <selectize options="TimeOption" ng-model="TimeSelected" config="TimeConfig"></selectize>
+ <selectize options="timeList" ng-model="selectTime" config="TimeConfig"></selectize>
</div>
</div>
<div class="table-responsive">
@@ -75,25 +75,25 @@
<thead class="thead">
<tr>
<th>Scenario </th>
- <th colspan={{colspan}} ng-show="selectInstallers.indexOf(key)!=-1" value={{key}} ng-repeat="key in tableDataAll.Installer"><a href="notfound.html">{{key}}</a> </th>
+ <th colspan={{selectProjects.length}} ng-show="selectInstallers.indexOf(key)!=-1" value={{key}} ng-repeat="key in selectInstallers"><a href="notfound.html">{{key}}</a> </th>
</tr>
<tr>
<td></td>
- <td ng-show="selectProjects.indexOf(project[0])!=-1 && selectInstallers.indexOf(project[1])!=-1" ng-repeat="project in tableDataAll.Projects track by $index" data={{project[1]}} value={{project[0]}}>{{project[0]}}</td>
+ <td ng-show="selectProjects.indexOf(project.project)!=-1 && selectInstallers.indexOf(project.installer)!=-1" ng-repeat="project in project_row track by $index" data={{project.installer}} value={{project.project}}>{{ project.project }}</td>
</tr>
</thead>
<tbody class="tbody">
- <tr ng-repeat="scenario in tableDataAll.scenario" ng-show="selectStatus.indexOf(scenario.status)!=-1">
+ <tr ng-repeat="scenario in scenario_rows" ng-show="selectStatus.indexOf(scenario.status)!=-1">
- <td nowrap="nowrap" data={{scenario.status}}><span class="fa fa-circle text-{{scenario.statusDisplay}}"></span> <a href="notfound.html">{{scenario.scenarioName}}</a> </td>
+ <td nowrap="nowrap" data={{scenario.status}}><span class="fa fa-circle text-{{scenario.statusDisplay}}"></span> <a href="notfound.html">{{scenario.name}}</a> </td>
<!--<td style="background-color:#e7eaec" align="justify" ng-if="data[0]=='Not Support'" ng-repeat="data in scenario.datadisplay track by $index" data={{data[1]}} value={{data[2]}}></td>-->
- <td nowrap="nowrap" ng-show="selectInstallers.indexOf(data[2])!=-1 && selectProjects.indexOf(data[1])!=-1" ng-repeat="data in scenario.datadisplay track by $index" data={{data[1]}} value={{data[2]}} class={{data[0]}}>
- <span class="label label-{{data[3]}}">{{data[4]}}</a></span> {{data[0]}}</td>
+ <td nowrap="nowrap" ng-show="selectInstallers.indexOf(data.installer)!=-1 && selectProjects.indexOf(data.project)!=-1" ng-repeat="data in scenario.datadisplay track by $index" data={{data.project}} value={{data.installer}} class={{data.value}}>
+ <span class="label label-{{data.label}}">{{data.label_value}}</a></span> {{data.value}}</td>
</tr>
@@ -110,4 +110,4 @@
</div>
</div>
-</section> \ No newline at end of file
+</section>
diff --git a/utils/test/testapi/opnfv_testapi/common/raises.py b/utils/test/testapi/opnfv_testapi/common/raises.py
index ec6b8a564..55c58c9e2 100644
--- a/utils/test/testapi/opnfv_testapi/common/raises.py
+++ b/utils/test/testapi/opnfv_testapi/common/raises.py
@@ -26,6 +26,10 @@ class Forbidden(Raiser):
code = httplib.FORBIDDEN
+class Conflict(Raiser):
+ code = httplib.CONFLICT
+
+
class NotFound(Raiser):
code = httplib.NOT_FOUND
diff --git a/utils/test/testapi/opnfv_testapi/resources/handlers.py b/utils/test/testapi/opnfv_testapi/resources/handlers.py
index 474a2033b..ed55c7028 100644
--- a/utils/test/testapi/opnfv_testapi/resources/handlers.py
+++ b/utils/test/testapi/opnfv_testapi/resources/handlers.py
@@ -50,7 +50,7 @@ class GenericApiHandler(web.RequestHandler):
self.auth = self.settings["auth"]
def prepare(self):
- if self.request.method != "GET" and self.request.method != "DELETE":
+ if self.request.body:
if self.request.headers.get("Content-Type") is not None:
if self.request.headers["Content-Type"].startswith(
DEFAULT_REPRESENTATION):
@@ -110,22 +110,23 @@ class GenericApiHandler(web.RequestHandler):
pipelines.append({'$match': query})
total_pages = 0
- if page > 0:
- cursor = dbapi.db_list(self.table, query)
- records_count = yield cursor.count()
- total_pages, return_nr = self._calc_total_pages(records_count,
- last,
- page,
- per_page)
- pipelines = self._set_pipelines(pipelines,
- sort,
- return_nr,
- page,
- per_page)
- cursor = dbapi.db_aggregate(self.table, pipelines)
data = list()
- while (yield cursor.fetch_next):
- data.append(self.format_data(cursor.next_object()))
+ cursor = dbapi.db_list(self.table, query)
+ records_count = yield cursor.count()
+ if records_count > 0:
+ if page > 0:
+ total_pages, return_nr = self._calc_total_pages(records_count,
+ last,
+ page,
+ per_page)
+ pipelines = self._set_pipelines(pipelines,
+ sort,
+ return_nr,
+ page,
+ per_page)
+ cursor = dbapi.db_aggregate(self.table, pipelines)
+ while (yield cursor.fetch_next):
+ data.append(self.format_data(cursor.next_object()))
if res_op is None:
res = {self.table: data}
else:
@@ -188,6 +189,16 @@ class GenericApiHandler(web.RequestHandler):
update_req['_id'] = str(data._id)
self.finish_request(update_req)
+ @check.authenticate
+ @check.no_body
+ @check.not_exist
+ @check.updated_one_not_exist
+ def pure_update(self, data, query=None, **kwargs):
+ data = self.table_cls.from_dict(data)
+ update_req = self._update_requests(data)
+ yield dbapi.db_update(self.table, query, update_req)
+ self.finish_request()
+
def _update_requests(self, data):
request = dict()
for k, v in self.json_args.iteritems():
diff --git a/utils/test/testapi/opnfv_testapi/resources/models.py b/utils/test/testapi/opnfv_testapi/resources/models.py
index e8fc532b7..6f04cc236 100644
--- a/utils/test/testapi/opnfv_testapi/resources/models.py
+++ b/utils/test/testapi/opnfv_testapi/resources/models.py
@@ -48,6 +48,29 @@ class ModelBase(object):
return t
+ @classmethod
+ def from_dict_with_raise(cls, a_dict):
+ if a_dict is None:
+ return None
+
+ attr_parser = cls.attr_parser()
+ t = cls()
+ for k, v in a_dict.iteritems():
+ if k not in t.__dict__:
+ raise AttributeError(
+ '{} has no attribute {}'.format(cls.__name__, k))
+ value = v
+ if isinstance(v, dict) and k in attr_parser:
+ value = attr_parser[k].from_dict(v)
+ elif isinstance(v, list) and k in attr_parser:
+ value = []
+ for item in v:
+ value.append(attr_parser[k].from_dict(item))
+
+ t.__setattr__(k, value)
+
+ return t
+
@staticmethod
def attr_parser():
return {}
diff --git a/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py b/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py
index 66e8559f7..bd06400b4 100644
--- a/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py
+++ b/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py
@@ -1,5 +1,7 @@
import functools
+from opnfv_testapi.common import message
+from opnfv_testapi.common import raises
from opnfv_testapi.resources import handlers
import opnfv_testapi.resources.scenario_models as models
from opnfv_testapi.tornado_swagger import swagger
@@ -138,6 +140,13 @@ class ScenarioUpdater(object):
updates = {
('scores', 'post'): self._update_requests_add_score,
('trust_indicators', 'post'): self._update_requests_add_ti,
+ ('customs', 'post'): self._update_requests_add_customs,
+ ('customs', 'put'): self._update_requests_update_customs,
+ ('customs', 'delete'): self._update_requests_delete_customs,
+ ('projects', 'post'): self._update_requests_add_projects,
+ ('projects', 'put'): self._update_requests_update_projects,
+ ('projects', 'delete'): self._update_requests_delete_projects,
+ ('owner', 'put'): self._update_requests_change_owner,
}
updates[(item, action)](self.data)
@@ -178,6 +187,76 @@ class ScenarioUpdater(object):
project.trust_indicators.append(
models.ScenarioTI.from_dict(self.body))
+ @iter_installers
+ @iter_versions
+ @iter_projects
+ def _update_requests_add_customs(self, project):
+ project.customs = list(set(project.customs + self.body))
+
+ @iter_installers
+ @iter_versions
+ @iter_projects
+ def _update_requests_update_customs(self, project):
+ project.customs = list(set(self.body))
+
+ @iter_installers
+ @iter_versions
+ @iter_projects
+ def _update_requests_delete_customs(self, project):
+ project.customs = filter(
+ lambda f: f not in self.body,
+ project.customs)
+
+ @iter_installers
+ @iter_versions
+ def _update_requests_add_projects(self, version):
+ exists = list()
+ malformat = list()
+ for n in self.body:
+ try:
+ f_n = models.ScenarioProject.from_dict_with_raise(n)
+ if not any(o.project == f_n.project for o in version.projects):
+ version.projects.append(f_n)
+ else:
+ exists.append(n['project'])
+ except Exception as e:
+ malformat.append(e.message)
+ if malformat:
+ raises.BadRequest(message.bad_format(malformat))
+ elif exists:
+ raises.Conflict(message.exist('projects', exists))
+
+ @iter_installers
+ @iter_versions
+ def _update_requests_update_projects(self, version):
+ exists = list()
+ malformat = list()
+ projects = list()
+ for n in self.body:
+ try:
+ f_n = models.ScenarioProject.from_dict_with_raise(n)
+ if not any(o.project == f_n.project for o in projects):
+ projects.append(models.ScenarioProject.from_dict(n))
+ else:
+ exists.append(n['project'])
+ except:
+ malformat.append(n)
+ if malformat:
+ raises.BadRequest(message.bad_format(malformat))
+ elif exists:
+ raises.Forbidden(message.exist('projects', exists))
+ version.projects = projects
+
+ @iter_installers
+ @iter_versions
+ def _update_requests_delete_projects(self, version):
+ version.projects = self._remove_projects(version.projects)
+
+ @iter_installers
+ @iter_versions
+ def _update_requests_change_owner(self, version):
+ version.owner = self.body
+
def _filter_installers(self, installers):
return self._filter('installer', installers)
@@ -187,11 +266,19 @@ class ScenarioUpdater(object):
def _filter_projects(self, projects):
return self._filter('project', projects)
+ def _remove_projects(self, projects):
+ return self._remove('project', projects)
+
def _filter(self, item, items):
return filter(
lambda f: getattr(f, item) == getattr(self, item),
items)
+ def _remove(self, field, fields):
+ return filter(
+ lambda f: getattr(f, field) not in self.body,
+ fields)
+
class GenericScenarioUpdateHandler(GenericScenarioHandler):
def __init__(self, application, request, **kwargs):
@@ -204,15 +291,15 @@ class GenericScenarioUpdateHandler(GenericScenarioHandler):
self.item = None
self.action = None
- def do_post(self, scenario, item, action, locators):
+ def do_update(self, item, action, locators):
self.item = item
self.action = action
- for k in locators.keys():
- v = self.get_query_argument(k)
- setattr(self, k, v)
- locators[k] = v
- db_keys = ['name']
- self._update(query=self.set_query(locators=locators), db_keys=db_keys)
+ for k, v in locators.iteritems():
+ if not v:
+ v = self.get_query_argument(k)
+ setattr(self, k, v)
+ locators[k] = v
+ self.pure_update(query=self.set_query(locators=locators))
def _update_requests(self, data):
return ScenarioUpdater(data,
@@ -247,16 +334,15 @@ class ScenarioScoresHandler(GenericScenarioUpdateHandler):
@type project: L{string}
@in project: query
@required project: True
- @rtype: L{Scenario}
@return 200: score is created.
@raise 404: scenario/installer/version/project not existed
"""
- self.do_post(scenario,
- 'scores',
- 'post',
- locators={'installer': None,
- 'version': None,
- 'project': None})
+ self.do_update('scores',
+ 'post',
+ locators={'scenario': scenario,
+ 'installer': None,
+ 'version': None,
+ 'project': None})
class ScenarioTIsHandler(GenericScenarioUpdateHandler):
@@ -284,13 +370,235 @@ class ScenarioTIsHandler(GenericScenarioUpdateHandler):
@type project: L{string}
@in project: query
@required project: True
- @rtype: L{Scenario}
@return 200: trust indicator is added.
@raise 404: scenario/installer/version/project not existed
"""
- self.do_post(scenario,
- 'trust_indicators',
- 'post',
- locators={'installer': None,
- 'version': None,
- 'project': None})
+ self.do_update('trust_indicators',
+ 'post',
+ locators={'scenario': scenario,
+ 'installer': None,
+ 'version': None,
+ 'project': None})
+
+
+class ScenarioCustomsHandler(GenericScenarioUpdateHandler):
+ @swagger.operation(nickname="addCustomizedTestCases")
+ def post(self, scenario):
+ """
+ @description: add customized test cases
+ @notes: add several test cases to a project
+ POST /api/v1/scenarios/<scenario_name>/customs? \
+ installer=<installer_name>& \
+ version=<version_name>& \
+ project=<project_name>
+ @param body: test cases to be added
+ @type body: C{list} of L{string}
+ @in body: body
+ @param installer: installer type
+ @type installer: L{string}
+ @in installer: query
+ @required installer: True
+ @param version: version
+ @type version: L{string}
+ @in version: query
+ @required version: True
+ @param project: project name
+ @type project: L{string}
+ @in project: query
+ @required project: True
+ @return 200: test cases are added.
+ @raise 404: scenario/installer/version/project not existed
+ """
+ self.do_update('customs',
+ 'post',
+ locators={'scenario': scenario,
+ 'installer': None,
+ 'version': None,
+ 'project': None})
+
+ @swagger.operation(nickname="updateCustomizedTestCases")
+ def put(self, scenario):
+ """
+ @description: update customized test cases
+ @notes: substitute all the customized test cases
+ PUT /api/v1/scenarios/<scenario_name>/customs? \
+ installer=<installer_name>& \
+ version=<version_name>& \
+ project=<project_name>
+ @param body: new supported test cases
+ @type body: C{list} of L{string}
+ @in body: body
+ @param installer: installer type
+ @type installer: L{string}
+ @in installer: query
+ @required installer: True
+ @param version: version
+ @type version: L{string}
+ @in version: query
+ @required version: True
+ @param project: project name
+ @type project: L{string}
+ @in project: query
+ @required project: True
+ @return 200: substitute test cases success.
+ @raise 404: scenario/installer/version/project not existed
+ """
+ self.do_update('customs',
+ 'put',
+ locators={'scenario': scenario,
+ 'installer': None,
+ 'version': None,
+ 'project': None})
+
+ @swagger.operation(nickname="deleteCustomizedTestCases")
+ def delete(self, scenario):
+ """
+ @description: delete one or several customized test cases
+ @notes: delete one or some customized test cases
+ DELETE /api/v1/scenarios/<scenario_name>/customs? \
+ installer=<installer_name>& \
+ version=<version_name>& \
+ project=<project_name>
+ @param body: test case(s) to be deleted
+ @type body: C{list} of L{string}
+ @in body: body
+ @param installer: installer type
+ @type installer: L{string}
+ @in installer: query
+ @required installer: True
+ @param version: version
+ @type version: L{string}
+ @in version: query
+ @required version: True
+ @param project: project name
+ @type project: L{string}
+ @in project: query
+ @required project: True
+ @return 200: delete test case(s) success.
+ @raise 404: scenario/installer/version/project not existed
+ """
+ self.do_update('customs',
+ 'delete',
+ locators={'scenario': scenario,
+ 'installer': None,
+ 'version': None,
+ 'project': None})
+
+
+class ScenarioProjectsHandler(GenericScenarioUpdateHandler):
+ @swagger.operation(nickname="addProjectsUnderScenario")
+ def post(self, scenario):
+ """
+ @description: add projects to scenario
+ @notes: add one or multiple projects
+ POST /api/v1/scenarios/<scenario_name>/projects? \
+ installer=<installer_name>& \
+ version=<version_name>
+ @param body: projects to be added
+ @type body: C{list} of L{ScenarioProject}
+ @in body: body
+ @param installer: installer type
+ @type installer: L{string}
+ @in installer: query
+ @required installer: True
+ @param version: version
+ @type version: L{string}
+ @in version: query
+ @required version: True
+ @return 200: projects are added.
+ @raise 400: bad schema
+ @raise 409: conflict, project already exists
+ @raise 404: scenario/installer/version not existed
+ """
+ self.do_update('projects',
+ 'post',
+ locators={'scenario': scenario,
+ 'installer': None,
+ 'version': None})
+
+ @swagger.operation(nickname="updateScenarioProjects")
+ def put(self, scenario):
+ """
+ @description: replace all projects
+ @notes: substitute all projects, delete existed ones with new provides
+ PUT /api/v1/scenarios/<scenario_name>/projects? \
+ installer=<installer_name>& \
+ version=<version_name>
+ @param body: new projects
+ @type body: C{list} of L{ScenarioProject}
+ @in body: body
+ @param installer: installer type
+ @type installer: L{string}
+ @in installer: query
+ @required installer: True
+ @param version: version
+ @type version: L{string}
+ @in version: query
+ @required version: True
+ @return 200: replace projects success.
+ @raise 400: bad schema
+ @raise 404: scenario/installer/version not existed
+ """
+ self.do_update('projects',
+ 'put',
+ locators={'scenario': scenario,
+ 'installer': None,
+ 'version': None})
+
+ @swagger.operation(nickname="deleteProjectsUnderScenario")
+ def delete(self, scenario):
+ """
+ @description: delete one or multiple projects
+ @notes: delete one or multiple projects
+ DELETE /api/v1/scenarios/<scenario_name>/projects? \
+ installer=<installer_name>& \
+ version=<version_name>
+ @param body: projects(names) to be deleted
+ @type body: C{list} of L{string}
+ @in body: body
+ @param installer: installer type
+ @type installer: L{string}
+ @in installer: query
+ @required installer: True
+ @param version: version
+ @type version: L{string}
+ @in version: query
+ @required version: True
+ @return 200: delete project(s) success.
+ @raise 404: scenario/installer/version not existed
+ """
+ self.do_update('projects',
+ 'delete',
+ locators={'scenario': scenario,
+ 'installer': None,
+ 'version': None})
+
+
+class ScenarioOwnerHandler(GenericScenarioUpdateHandler):
+ @swagger.operation(nickname="changeScenarioOwner")
+ def put(self, scenario):
+ """
+ @description: change scenario owner
+ @notes: substitute all projects, delete existed ones with new provides
+ PUT /api/v1/scenarios/<scenario_name>/owner? \
+ installer=<installer_name>& \
+ version=<version_name>
+ @param body: new owner
+ @type body: L{string}
+ @in body: body
+ @param installer: installer type
+ @type installer: L{string}
+ @in installer: query
+ @required installer: True
+ @param version: version
+ @type version: L{string}
+ @in version: query
+ @required version: True
+ @return 200: change owner success.
+ @raise 404: scenario/installer/version not existed
+ """
+ self.do_update('owner',
+ 'put',
+ locators={'scenario': scenario,
+ 'installer': None,
+ 'version': None})
diff --git a/utils/test/testapi/opnfv_testapi/resources/scenario_models.py b/utils/test/testapi/opnfv_testapi/resources/scenario_models.py
index 9f5a07434..7d0770759 100644
--- a/utils/test/testapi/opnfv_testapi/resources/scenario_models.py
+++ b/utils/test/testapi/opnfv_testapi/resources/scenario_models.py
@@ -74,7 +74,8 @@ class ScenarioVersion(models.ModelBase):
@property projects:
@ptype projects: C{list} of L{ScenarioProject}
"""
- def __init__(self, version=None, projects=None):
+ def __init__(self, owner=None, version=None, projects=None):
+ self.owner = owner
self.version = version
self.projects = list_default(projects)
@@ -83,7 +84,9 @@ class ScenarioVersion(models.ModelBase):
return {'projects': ScenarioProject}
def __eq__(self, other):
- return [self.version == other.version and self._projects_eq(other)]
+ return [self.version == other.version and
+ self.owner == other.owner and
+ self._projects_eq(other)]
def __ne__(self, other):
return not self.__eq__(other)
diff --git a/utils/test/testapi/opnfv_testapi/router/url_mappings.py b/utils/test/testapi/opnfv_testapi/router/url_mappings.py
index 458942576..9c9556c6b 100644
--- a/utils/test/testapi/opnfv_testapi/router/url_mappings.py
+++ b/utils/test/testapi/opnfv_testapi/router/url_mappings.py
@@ -58,6 +58,12 @@ mappings = [
scenario_handlers.ScenarioScoresHandler),
(r"/api/v1/scenarios/([^/]+)/trust_indicators",
scenario_handlers.ScenarioTIsHandler),
+ (r"/api/v1/scenarios/([^/]+)/customs",
+ scenario_handlers.ScenarioCustomsHandler),
+ (r"/api/v1/scenarios/([^/]+)/projects",
+ scenario_handlers.ScenarioProjectsHandler),
+ (r"/api/v1/scenarios/([^/]+)/owner",
+ scenario_handlers.ScenarioOwnerHandler),
# static path
(r'/(.*\.(css|png|gif|js|html|json|map|woff2|woff|ttf))',
diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_base.py b/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_base.py
index aa6b83544..77a8d18c1 100644
--- a/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_base.py
+++ b/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_base.py
@@ -92,21 +92,35 @@ class TestBase(testing.AsyncHTTPTestCase):
headers=self.headers)
return self._get_return(res, self.list_res)
- def update(self, new=None, *args):
- if new:
+ def update_direct_url(self, url, new=None):
+ if new and hasattr(new, 'format'):
new = new.format()
- res = self.fetch(self._get_uri(*args),
+ res = self.fetch(url,
method='PUT',
body=json.dumps(new),
headers=self.headers)
return self._get_return(res, self.update_res)
- def delete(self, *args):
- res = self.fetch(self._get_uri(*args),
- method='DELETE',
- headers=self.headers)
+ def update(self, new=None, *args):
+ return self.update_direct_url(self._get_uri(*args), new)
+
+ def delete_direct_url(self, url, body):
+ if body:
+ res = self.fetch(url,
+ method='DELETE',
+ body=json.dumps(body),
+ headers=self.headers,
+ allow_nonstandard_methods=True)
+ else:
+ res = self.fetch(url,
+ method='DELETE',
+ headers=self.headers)
+
return res.code, res.body
+ def delete(self, *args):
+ return self.delete_direct_url(self._get_uri(*args), None)
+
@staticmethod
def _get_valid_args(*args):
new_args = tuple(['%s' % arg for arg in args if arg is not None])
@@ -132,7 +146,10 @@ class TestBase(testing.AsyncHTTPTestCase):
def _get_return(self, res, cls):
code = res.code
body = res.body
- return code, self._get_return_body(code, body, cls)
+ if body:
+ return code, self._get_return_body(code, body, cls)
+ else:
+ return code, None
@staticmethod
def _get_return_body(code, body, cls):
diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py b/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py
index 0558ea30d..466caaf13 100644
--- a/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py
+++ b/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py
@@ -168,15 +168,30 @@ class TestScenarioUpdate(TestScenarioBase):
self.version,
'functest')
+ def update_url_fixture(item):
+ def _update_url_fixture(xstep):
+ def wrapper(self, *args, **kwargs):
+ locator = None
+ if item in ['projects', 'owner']:
+ locator = 'installer={}&version={}'.format(
+ self.installer,
+ self.version)
+ self.update_url = '{}/{}?{}'.format(self.scenario_url,
+ item,
+ locator)
+ xstep(self, *args, **kwargs)
+ return wrapper
+ return _update_url_fixture
+
def update_partial(operate, expected):
- def _update(set_update):
+ def _update_partial(set_update):
@functools.wraps(set_update)
- def wrap(self):
+ def wrapper(self):
update, scenario = set_update(self, deepcopy(self.req_d))
code, body = getattr(self, operate)(update, self.scenario)
getattr(self, expected)(code, scenario)
- return wrap
- return _update
+ return wrapper
+ return _update_partial
@update_partial('_add', '_success')
def test_addScore(self, scenario):
@@ -200,9 +215,101 @@ class TestScenarioUpdate(TestScenarioBase):
return add, scenario
+ @update_partial('_add', '_success')
+ def test_addCustoms(self, scenario):
+ add = ['odl', 'parser', 'vping_ssh']
+ projects = scenario['installers'][0]['versions'][0]['projects']
+ functest = filter(lambda f: f['project'] == 'functest', projects)[0]
+ functest['customs'] = list(set(functest['customs'] + add))
+ self.update_url = '{}/customs?{}'.format(self.scenario_url,
+ self.locate_project)
+ return add, scenario
+
+ @update_partial('_update', '_success')
+ def test_updateCustoms(self, scenario):
+ news = ['odl', 'parser', 'vping_ssh']
+ projects = scenario['installers'][0]['versions'][0]['projects']
+ functest = filter(lambda f: f['project'] == 'functest', projects)[0]
+ functest['customs'] = news
+ self.update_url = '{}/customs?{}'.format(self.scenario_url,
+ self.locate_project)
+
+ return news, scenario
+
+ @update_partial('_delete', '_success')
+ def test_deleteCustoms(self, scenario):
+ obsoletes = ['vping_ssh']
+ projects = scenario['installers'][0]['versions'][0]['projects']
+ functest = filter(lambda f: f['project'] == 'functest', projects)[0]
+ functest['customs'] = ['healthcheck']
+ self.update_url = '{}/customs?{}'.format(self.scenario_url,
+ self.locate_project)
+
+ return obsoletes, scenario
+
+ @update_url_fixture('projects')
+ @update_partial('_add', '_success')
+ def test_addProjects_succ(self, scenario):
+ add = models.ScenarioProject(project='qtip').format()
+ scenario['installers'][0]['versions'][0]['projects'].append(add)
+ return [add], scenario
+
+ @update_url_fixture('projects')
+ @update_partial('_add', '_conflict')
+ def test_addProjects_already_exist(self, scenario):
+ add = models.ScenarioProject(project='functest').format()
+ scenario['installers'][0]['versions'][0]['projects'].append(add)
+ return [add], scenario
+
+ @update_url_fixture('projects')
+ @update_partial('_add', '_bad_request')
+ def test_addProjects_bad_schema(self, scenario):
+ add = models.ScenarioProject(project='functest').format()
+ add['score'] = None
+ scenario['installers'][0]['versions'][0]['projects'].append(add)
+ return [add], scenario
+
+ @update_url_fixture('projects')
+ @update_partial('_update', '_success')
+ def test_updateProjects_succ(self, scenario):
+ update = models.ScenarioProject(project='qtip').format()
+ scenario['installers'][0]['versions'][0]['projects'] = [update]
+ return [update], scenario
+
+ @update_url_fixture('projects')
+ @update_partial('_update', '_bad_request')
+ def test_updateProjects_bad_schema(self, scenario):
+ update = models.ScenarioProject(project='functest').format()
+ update['score'] = None
+ scenario['installers'][0]['versions'][0]['projects'] = [update]
+ return [update], scenario
+
+ @update_url_fixture('projects')
+ @update_partial('_delete', '_success')
+ def test_deleteProjects(self, scenario):
+ deletes = ['functest']
+ projects = scenario['installers'][0]['versions'][0]['projects']
+ scenario['installers'][0]['versions'][0]['projects'] = filter(
+ lambda f: f['project'] != 'functest',
+ projects)
+ return deletes, scenario
+
+ @update_url_fixture('owner')
+ @update_partial('_update', '_success')
+ def test_changeOwner(self, scenario):
+ new_owner = 'new_owner'
+ scenario['installers'][0]['versions'][0]['owner'] = 'www'
+ return new_owner, scenario
+
def _add(self, update_req, new_scenario):
return self.post_direct_url(self.update_url, update_req)
+ def _update(self, update_req, new_scenario):
+ return self.update_direct_url(self.update_url, update_req)
+
+ def _delete(self, update_req, new_scenario):
+ return self.delete_direct_url(self.update_url, update_req)
+
def _success(self, status, new_scenario):
self.assertEqual(status, httplib.OK)
self._get_and_assert(new_scenario.get('name'), new_scenario)
@@ -212,3 +319,6 @@ class TestScenarioUpdate(TestScenarioBase):
def _bad_request(self, status, new_scenario):
self.assertEqual(status, httplib.BAD_REQUEST)
+
+ def _conflict(self, status, new_scenario):
+ self.assertEqual(status, httplib.CONFLICT)
diff --git a/utils/test/testapi/opnfv_testapi/tornado_swagger/swagger.py b/utils/test/testapi/opnfv_testapi/tornado_swagger/swagger.py
index 83f389a6b..6125c9554 100644
--- a/utils/test/testapi/opnfv_testapi/tornado_swagger/swagger.py
+++ b/utils/test/testapi/opnfv_testapi/tornado_swagger/swagger.py
@@ -94,11 +94,18 @@ class DocParser(object):
def _parse_type(self, **kwargs):
arg = kwargs.get('arg', None)
- body = self._get_body(**kwargs)
- self.params.setdefault(arg, {}).update({
- 'name': arg,
- 'dataType': body
- })
+ code = self._parse_epytext_para('code', **kwargs)
+ link = self._parse_epytext_para('link', **kwargs)
+ if code is None:
+ self.params.setdefault(arg, {}).update({
+ 'name': arg,
+ 'type': link
+ })
+ elif code == 'list':
+ self.params.setdefault(arg, {}).update({
+ 'type': 'array',
+ 'items': {'type': link}
+ })
def _parse_in(self, **kwargs):
arg = kwargs.get('arg', None)