Merge "[macro] property logrotate"
authorRyota Mibu <r-mibu@cq.jp.nec.com>
Tue, 24 Jan 2017 01:20:23 +0000 (01:20 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Tue, 24 Jan 2017 01:20:23 +0000 (01:20 +0000)
24 files changed:
INFO
jjb/compass4nfv/compass-verify-jobs.yml
jjb/infra/bifrost-upload-logs.sh [deleted file]
jjb/infra/bifrost-verify-jobs.yml
jjb/infra/bifrost-verify.sh
jjb/releng/testapi-automate.yml
jjb/releng/testapi-run-tests.sh [deleted file]
utils/push-test-logs.sh
utils/test/testapi/htmlize/doc-build.sh
utils/test/testapi/htmlize/htmlize.py
utils/test/testapi/opnfv_testapi/resources/handlers.py
utils/test/testapi/opnfv_testapi/resources/pod_handlers.py
utils/test/testapi/opnfv_testapi/resources/project_handlers.py
utils/test/testapi/opnfv_testapi/resources/result_handlers.py
utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py
utils/test/testapi/opnfv_testapi/resources/scenario_models.py
utils/test/testapi/opnfv_testapi/resources/testcase_handlers.py
utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py
utils/test/testapi/opnfv_testapi/tests/unit/scenario-c1.json [moved from utils/test/testapi/opnfv_testapi/tests/unit/scenario-create.json with 99% similarity]
utils/test/testapi/opnfv_testapi/tests/unit/scenario-c2.json [new file with mode: 0644]
utils/test/testapi/opnfv_testapi/tests/unit/test_base.py
utils/test/testapi/opnfv_testapi/tests/unit/test_scenario.py
utils/test/testapi/run_test.sh
utils/test/testapi/test-requirements.txt [deleted file]

diff --git a/INFO b/INFO
index 626637f..069d3d0 100644 (file)
--- a/INFO
+++ b/INFO
@@ -22,6 +22,7 @@ Mei Mei (Huawei, meimei@huawei.com)
 Trevor Bramwell (Linux Foundation, tbramwell@linuxfoundation.org)
 Serena Feng (ZTE, feng.xiaowei@zte.com.cn)
 Yolanda Robla Mota (Red Hat, yroblamo@redhat.com)
+Markos Chandras (SUSE, mchandras@suse.de)
 
 Link to TSC approval of the project: http://ircbot.wl.linuxfoundation.org/meetings/opnfv-meeting/2015/opnfv-meeting.2015-07-14-14.00.html
 Link to TSC voting for removal of Victor Laza as committer: http://meetbot.opnfv.org/meetings/opnfv-meeting/2016/opnfv-meeting.2016-02-16-14.59.html
index a279553..f5a54c8 100644 (file)
             disabled: false
             os-version: 'xenial'
             openstack-os-version: ''
+        - 'centos7':
+            disabled: false
+            os-version: 'centos7'
+            openstack-os-version: ''
 #####################################
 # patch verification phases
 #####################################
             name: COMPASS_OS_VERSION
             choices:
                 - 'xenial'
+                - 'centos7'
diff --git a/jjb/infra/bifrost-upload-logs.sh b/jjb/infra/bifrost-upload-logs.sh
deleted file mode 100755 (executable)
index 8e1982d..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/bash
-# SPDX-license-identifier: Apache-2.0
-##############################################################################
-# Copyright (c) 2016 SUSE.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-set -eu
-set -o pipefail
-
-BIFROST_CONSOLE_LOG="${BUILD_URL}/consoleText"
-BIFROST_GS_URL=${BIFROST_LOG_URL/http:/gs:}
-BIFROST_COMPRESS_SUFFIX="tar.gz"
-BIFROST_COMPRESSED_LOGS=()
-
-echo "Uploading build logs to ${BIFROST_LOG_URL}"
-
-echo "Uploading console output"
-curl -L ${BIFROST_CONSOLE_LOG} | gsutil cp - ${BIFROST_GS_URL}/build_log.txt
-
-[[ ! -d ${WORKSPACE}/logs ]] && exit 0
-
-pushd ${WORKSPACE}/logs/ &> /dev/null
-for x in *.log; do
-    echo "Compressing and uploading $x"
-    tar -czf - $x | gsutil cp - ${BIFROST_GS_URL}/${x}.${BIFROST_COMPRESS_SUFFIX} 1>/dev/null
-    BIFROST_COMPRESSED_LOGS+=(${x}.${BIFROST_COMPRESS_SUFFIX})
-done
-popd &> /dev/null
-
-echo "Generating the landing page"
-cat > index.html << EOF
-<html>
-<h1>Build results for <a href=https://$GERRIT_NAME/#/c/$GERRIT_CHANGE_NUMBER>$GERRIT_NAME/$GERRIT_CHANGE_NUMBER</a></h1>
-<h2>Job: $JOB_NAME</h2>
-<ul>
-<li><a href=${BIFROST_LOG_URL}/build_log.txt>build_log.txt</a></li>
-EOF
-
-for x in ${BIFROST_COMPRESSED_LOGS[@]}; do
-    echo "<li><a href=${BIFROST_LOG_URL}/${x}>${x}</a></li>" >> index.html
-done
-
-cat >> index.html << EOF
-</ul>
-</html>
-EOF
-
-gsutil cp index.html ${BIFROST_GS_URL}/index.html
index b485418..28e36aa 100644 (file)
     builders:
         - bifrost-set-name
         - bifrost-build
-        - bifrost-artifacts-upload
 
     publishers:
         - email:
     builders:
         - shell:
             !include-raw: ./bifrost-verify.sh
-
-- builder:
-    name: bifrost-artifacts-upload
-    builders:
-        - shell:
-            !include-raw: ./bifrost-upload-logs.sh
index 9fbb1d0..dbe3976 100755 (executable)
@@ -11,7 +11,51 @@ set -o errexit
 set -o nounset
 set -o pipefail
 
-trap fix_ownership EXIT
+trap cleanup_and_upload EXIT
+
+function upload_logs() {
+    BIFROST_CONSOLE_LOG="${BUILD_URL}/consoleText"
+    BIFROST_GS_URL=${BIFROST_LOG_URL/http:/gs:}
+
+    echo "Uploading build logs to ${BIFROST_LOG_URL}"
+
+    echo "Uploading console output"
+    curl -s -L ${BIFROST_CONSOLE_LOG} > ${WORKSPACE}/build_log.txt
+    gsutil -q cp -Z ${WORKSPACE}/build_log.txt ${BIFROST_GS_URL}/build_log.txt
+    rm ${WORKSPACE}/build_log.txt
+
+    [[ ! -d ${WORKSPACE}/logs ]] && exit 0
+
+    pushd ${WORKSPACE}/logs/ &> /dev/null
+    for x in *.log; do
+        echo "Compressing and uploading $x"
+        gsutil -q cp -Z ${x} ${BIFROST_GS_URL}/${x}
+    done
+
+    echo "Generating the landing page"
+    cat > index.html <<EOF
+<html>
+<h1>Build results for <a href=https://$GERRIT_NAME/#/c/$GERRIT_CHANGE_NUMBER/$GERRIT_PATCHSET_NUMBER>$GERRIT_NAME/$GERRIT_CHANGE_NUMBER/$GERRIT_PATCHSET_NUMBER</a></h1>
+<h2>Job: $JOB_NAME</h2>
+<ul>
+<li><a href=${BIFROST_LOG_URL}/build_log.txt>build_log.txt</a></li>
+EOF
+
+    for x in *.log; do
+        echo "<li><a href=${BIFROST_LOG_URL}/${x}>${x}</a></li>" >> index.html
+    done
+
+    cat >> index.html << EOF
+</ul>
+</html>
+EOF
+
+    gsutil -q cp index.html ${BIFROST_GS_URL}/index.html
+
+    rm index.html
+
+    popd &> /dev/null
+}
 
 function fix_ownership() {
     if [ -z "${JOB_URL+x}" ]; then
@@ -25,6 +69,13 @@ function fix_ownership() {
     fi
 }
 
+function cleanup_and_upload() {
+    original_exit=$?
+    fix_ownership
+    upload_logs
+    exit $original_exit
+}
+
 # check distro to see if we support it
 if [[ ! "$DISTRO" =~ (trusty|centos7|suse) ]]; then
     echo "Distro $DISTRO is not supported!"
index 552c25f..25ee687 100644 (file)
@@ -18,6 +18,7 @@
             project: '{project}'
         - gerrit-parameter:
             branch: '{branch}'
+        - 'opnfv-build-ubuntu-defaults'
 
     scm:
         - git-scm
     builders:
         - run-unit-tests
 
+    publishers:
+        - junit:
+            results: nosetests.xml
+        - cobertura:
+            report-file: "coverage.xml"
+            only-stable: "true"
+            health-auto-update: "true"
+            stability-auto-update: "true"
+            zoom-coverage-chart: "true"
+            targets:
+                - files:
+                    healthy: 10
+                    unhealthy: 20
+                    failing: 30
+                - method:
+                    healthy: 50
+                    unhealthy: 40
+                    failing: 30
+
 - job-template:
     name: 'testapi-automate-{stream}'
 
     name: run-unit-tests
     builders:
         - shell: |
-            bash ./jjb/releng/testapi-run-tests.sh
+            bash ./utils/test/testapi/run_test.sh
 
 - builder:
     name: docker-update
diff --git a/jjb/releng/testapi-run-tests.sh b/jjb/releng/testapi-run-tests.sh
deleted file mode 100644 (file)
index 47691ed..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-set -o errexit
-
-echo "Running unit tests..."
-
-# Creating virtual environment
-virtualenv $WORKSPACE/testapi_test_venv
-source $WORKSPACE/testapi_test_venv/bin/activate
-
-cd $WORKSPACE/utils/test/testapi/
-
-# Install requirements
-pip install -r requirements.txt
-pip install -r test-requirements.txt
-
-# Run unit tests
-bash run_test.sh
index 61a6c32..265ca61 100644 (file)
@@ -23,7 +23,7 @@ dir_result="${HOME}/opnfv/$project/results/${branch}"
 node_list=(\
 'lf-pod1' 'lf-pod2' 'intel-pod2' 'intel-pod3' \
 'intel-pod5' 'intel-pod6' 'intel-pod7' 'intel-pod8' \
-'ericsson-pod2' 'ericsson-pod3' 'ericsson-pod4' \
+'ericsson-pod1' 'ericsson-pod2' \
 'ericsson-virtual1' 'ericsson-virtual2'  'ericsson-virtual3' \
 'ericsson-virtual4' 'ericsson-virtual5' \
 'arm-pod1' 'arm-pod3' \
index e492c97..427b437 100644 (file)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+set -o errexit
+
 # Create virtual environment
 source $WORKSPACE/testapi_venv/bin/activate
 
index 68d02fe..c07f98e 100644 (file)
@@ -28,7 +28,10 @@ def main(args):
     # Generating html page
     cmd = 'java -jar swagger-codegen-cli.jar generate \
         -i specs.json -l html2 -o %s' % (args.output_directory)
-    os.system(cmd)
+    if os.system(cmd) == 0:
+        exit(0)
+    else:
+        exit(1)
 
 if __name__ == '__main__':
     parser = argparse.ArgumentParser(description='Create \
index 9fc5d6b..5f6c3df 100644 (file)
@@ -228,7 +228,7 @@ class GenericApiHandler(RequestHandler):
 
 
 class VersionHandler(GenericApiHandler):
-    @swagger.operation(nickname='List all versions')
+    @swagger.operation(nickname='listAllVersions')
     def get(self):
         """
             @description: list all supported versions
index 631d4a9..e1bd9d3 100644 (file)
@@ -20,7 +20,7 @@ class GenericPodHandler(GenericApiHandler):
 
 
 class PodCLHandler(GenericPodHandler):
-    @swagger.operation(nickname='List all Pods')
+    @swagger.operation(nickname='listAllPods')
     def get(self):
         """
             @description: list all pods
@@ -29,7 +29,7 @@ class PodCLHandler(GenericPodHandler):
         """
         self._list()
 
-    @swagger.operation(nickname='Create a Pod')
+    @swagger.operation(nickname='createPod')
     def post(self):
         """
             @description: create a pod
@@ -54,7 +54,7 @@ class PodCLHandler(GenericPodHandler):
 
 
 class PodGURHandler(GenericPodHandler):
-    @swagger.operation(nickname='Get a Pod by pod_name')
+    @swagger.operation(nickname='getPodByName')
     def get(self, pod_name):
         """
             @description: get a single pod by pod_name
index 9cf6986..94c65b7 100644 (file)
@@ -22,7 +22,7 @@ class GenericProjectHandler(GenericApiHandler):
 
 
 class ProjectCLHandler(GenericProjectHandler):
-    @swagger.operation(nickname="List all Projects")
+    @swagger.operation(nickname="listAllProjects")
     def get(self):
         """
             @description: list all projects
@@ -31,7 +31,7 @@ class ProjectCLHandler(GenericProjectHandler):
         """
         self._list()
 
-    @swagger.operation(nickname="Create a Project")
+    @swagger.operation(nickname="createProject")
     def post(self):
         """
             @description: create a project
@@ -56,7 +56,7 @@ class ProjectCLHandler(GenericProjectHandler):
 
 
 class ProjectGURHandler(GenericProjectHandler):
-    @swagger.operation(nickname='Get a Project by project_name')
+    @swagger.operation(nickname='getProjectByName')
     def get(self, project_name):
         """
             @description: get a single project by project_name
@@ -66,7 +66,7 @@ class ProjectGURHandler(GenericProjectHandler):
         """
         self._get_one({'name': project_name})
 
-    @swagger.operation(nickname="Update a Project by project_name")
+    @swagger.operation(nickname="updateProjectByName")
     def put(self, project_name):
         """
             @description: update a single project by project_name
@@ -82,7 +82,7 @@ class ProjectGURHandler(GenericProjectHandler):
         db_keys = ['name']
         self._update(query, db_keys)
 
-    @swagger.operation(nickname='Delete a Project by project_name')
+    @swagger.operation(nickname='deleteProjectByName')
     def delete(self, project_name):
         """
             @description: delete a project by project_name
index fe13c09..2a1ed56 100644 (file)
@@ -52,7 +52,7 @@ class GenericResultHandler(GenericApiHandler):
 
 
 class ResultsCLHandler(GenericResultHandler):
-    @swagger.operation(nickname="List all Test Results")
+    @swagger.operation(nickname="queryTestResults")
     def get(self):
         """
             @description: Retrieve result(s) for a test project
@@ -127,7 +127,7 @@ class ResultsCLHandler(GenericResultHandler):
 
         self._list(self.set_query(), sort=[('start_date', -1)], last=last)
 
-    @swagger.operation(nickname="Create a Test Result")
+    @swagger.operation(nickname="createTestResult")
     def post(self):
         """
             @description: create a test result
@@ -169,7 +169,7 @@ class ResultsCLHandler(GenericResultHandler):
 
 
 class ResultsGURHandler(GenericResultHandler):
-    @swagger.operation(nickname='Get a Test Result by result_id')
+    @swagger.operation(nickname='getTestResultById')
     def get(self, result_id):
         """
             @description: get a single result by result_id
@@ -181,7 +181,7 @@ class ResultsGURHandler(GenericResultHandler):
         query["_id"] = ObjectId(result_id)
         self._get_one(query)
 
-    @swagger.operation(nickname="Update a Test Result by result_id")
+    @swagger.operation(nickname="updateTestResultById")
     def put(self, result_id):
         """
             @description: update a single result by _id
index 7bf3d5d..a9b89eb 100644 (file)
@@ -14,18 +14,56 @@ class GenericScenarioHandler(GenericApiHandler):
 
 
 class ScenariosCLHandler(GenericScenarioHandler):
-    @swagger.operation(nickname="List scenarios by queries")
+    @swagger.operation(nickname="queryScenarios")
     def get(self):
         """
             @description: Retrieve scenario(s).
             @notes: Retrieve scenario(s)
-            @return 200: all scenarios consist with query,
+                Available filters for this request are :
+                 - name : scenario name
+
+                GET /scenarios?name=scenario_1
+            @param name: scenario name
+            @type name: L{string}
+            @in name: query
+            @required name: False
+            @param installer: installer type
+            @type installer: L{string}
+            @in installer: query
+            @required installer: False
+            @param version: version
+            @type version: L{string}
+            @in version: query
+            @required version: False
+            @param project: project name
+            @type project: L{string}
+            @in project: query
+            @required project: False
+            @return 200: all scenarios satisfy queries,
                          empty list if no scenario is found
             @rtype: L{Scenarios}
         """
-        self._list()
 
-    @swagger.operation(nickname="Create a new scenario")
+        def _set_query():
+            query = dict()
+            elem_query = dict()
+            for k in self.request.query_arguments.keys():
+                v = self.get_query_argument(k)
+                if k == 'installer':
+                    elem_query["installer"] = v
+                elif k == 'version':
+                    elem_query["versions.version"] = v
+                elif k == 'project':
+                    elem_query["versions.projects.project"] = v
+                else:
+                    query[k] = v
+            if elem_query:
+                query['installers'] = {'$elemMatch': elem_query}
+            return query
+
+        self._list(_set_query())
+
+    @swagger.operation(nickname="createScenario")
     def post(self):
         """
             @description: create a new scenario by name
@@ -50,7 +88,7 @@ class ScenariosCLHandler(GenericScenarioHandler):
 
 
 class ScenarioGURHandler(GenericScenarioHandler):
-    @swagger.operation(nickname='Get the scenario by name')
+    @swagger.operation(nickname='getScenarioByName')
     def get(self, name):
         """
             @description: get a single scenario by name
@@ -58,14 +96,15 @@ class ScenarioGURHandler(GenericScenarioHandler):
             @return 200: scenario exist
             @raise 404: scenario not exist
         """
+        self._get_one({'name': name})
         pass
 
-    @swagger.operation(nickname="Update the scenario by name")
+    @swagger.operation(nickname="updateScenarioByName")
     def put(self, name):
         """
             @description: update a single scenario by name
             @param body: fields to be updated
-            @type body: L{string}
+            @type body: L{ScenarioCreateRequest}
             @in body: body
             @rtype: L{Scenario}
             @return 200: update success
index b4bb363..f89a124 100644 (file)
@@ -11,7 +11,7 @@ class ScenarioTI(models.ModelBase):
 
 @swagger.model()
 class ScenarioScore(models.ModelBase):
-    def __init__(self, date=None, score=''):
+    def __init__(self, date=None, score='0'):
         self.date = date
         self.score = score
 
@@ -27,14 +27,19 @@ class ScenarioProject(models.ModelBase):
         @ptype trust_indicators: C{list} of L{ScenarioTI}
     """
     def __init__(self,
-                 name='',
+                 project='',
                  customs=None,
                  scores=None,
                  trust_indicators=None):
-        self.name = name
+        self.project = project
         self.customs = customs
         self.scores = scores
-        self.trust_indicator = trust_indicators
+        self.trust_indicators = trust_indicators
+
+    @staticmethod
+    def attr_parser():
+        return {'scores': ScenarioScore,
+                'trust_indicators': ScenarioTI}
 
 
 @swagger.model()
@@ -43,10 +48,14 @@ class ScenarioVersion(models.ModelBase):
         @property projects:
         @ptype projects: C{list} of L{ScenarioProject}
     """
-    def __init__(self, version, projects=None):
+    def __init__(self, version=None, projects=None):
         self.version = version
         self.projects = projects
 
+    @staticmethod
+    def attr_parser():
+        return {'projects': ScenarioProject}
+
 
 @swagger.model()
 class ScenarioInstaller(models.ModelBase):
@@ -54,11 +63,14 @@ class ScenarioInstaller(models.ModelBase):
         @property versions:
         @ptype versions: C{list} of L{ScenarioVersion}
     """
-    def __init__(self, installer=None, owner=None, versions=None):
+    def __init__(self, installer=None, versions=None):
         self.installer = installer
-        self.owner = owner
         self.versions = versions if versions else list()
 
+    @staticmethod
+    def attr_parser():
+        return {'versions': ScenarioVersion}
+
 
 @swagger.model()
 class ScenarioCreateRequest(models.ModelBase):
@@ -70,6 +82,10 @@ class ScenarioCreateRequest(models.ModelBase):
         self.name = name
         self.installers = installers if installers else list()
 
+    @staticmethod
+    def attr_parser():
+        return {'installers': ScenarioInstaller}
+
 
 @swagger.model()
 class Scenario(models.ModelBase):
@@ -83,6 +99,10 @@ class Scenario(models.ModelBase):
         self.creation_date = create_date
         self.installers = installers if installers else list()
 
+    @staticmethod
+    def attr_parser():
+        return {'installers': ScenarioInstaller}
+
 
 @swagger.model()
 class Scenarios(models.ModelBase):
index 3692b16..100a4fd 100644 (file)
@@ -22,7 +22,7 @@ class GenericTestcaseHandler(GenericApiHandler):
 
 
 class TestcaseCLHandler(GenericTestcaseHandler):
-    @swagger.operation(nickname="List all TestCases by project_name")
+    @swagger.operation(nickname="listAllTestCases")
     def get(self, project_name):
         """
             @description: list all testcases of a project by project_name
@@ -34,7 +34,7 @@ class TestcaseCLHandler(GenericTestcaseHandler):
         query['project_name'] = project_name
         self._list(query)
 
-    @swagger.operation(nickname="Create a TestCase by project_name")
+    @swagger.operation(nickname="createTestCase")
     def post(self, project_name):
         """
             @description: create a testcase of a project by project_name
@@ -72,7 +72,7 @@ class TestcaseCLHandler(GenericTestcaseHandler):
 
 
 class TestcaseGURHandler(GenericTestcaseHandler):
-    @swagger.operation(nickname='Get a TestCase by project and case name')
+    @swagger.operation(nickname='getTestCaseByName')
     def get(self, project_name, case_name):
         """
             @description: get a single testcase
@@ -86,7 +86,7 @@ class TestcaseGURHandler(GenericTestcaseHandler):
         query["name"] = case_name
         self._get_one(query)
 
-    @swagger.operation(nickname="Update a TestCase by project and case name")
+    @swagger.operation(nickname="updateTestCaseByName")
     def put(self, project_name, case_name):
         """
             @description: update a single testcase
@@ -104,7 +104,7 @@ class TestcaseGURHandler(GenericTestcaseHandler):
         db_keys = ['name', 'project_name']
         self._update(query, db_keys)
 
-    @swagger.operation(nickname='Delete a TestCase by project and case name')
+    @swagger.operation(nickname='deleteTestCaseByName')
     def delete(self, project_name, case_name):
         """
             @description: delete a testcase by project_name and case_name
index d86d8ea..3c4fd01 100644 (file)
@@ -55,7 +55,8 @@ class MemCursor(object):
 
 class MemDb(object):
 
-    def __init__(self):
+    def __init__(self, name):
+        self.name = name
         self.contents = []
         pass
 
@@ -109,8 +110,59 @@ class MemDb(object):
                 return True
         return False
 
-    @staticmethod
-    def _in(content, *args):
+    def _in(self, content, *args):
+        if self.name == 'scenarios':
+            return self._in_scenarios(content, *args)
+        else:
+            return self._in_others(content, *args)
+
+    def _in_scenarios_installer(self, installer, content):
+        hit = False
+        for s_installer in content['installers']:
+            if installer == s_installer['installer']:
+                hit = True
+
+        return hit
+
+    def _in_scenarios_version(self, version, content):
+        hit = False
+        for s_installer in content['installers']:
+            for s_version in s_installer['versions']:
+                if version == s_version['version']:
+                    hit = True
+        return hit
+
+    def _in_scenarios_project(self, project, content):
+        hit = False
+        for s_installer in content['installers']:
+            for s_version in s_installer['versions']:
+                for s_project in s_version['projects']:
+                    if project == s_project['project']:
+                        hit = True
+
+        return hit
+
+    def _in_scenarios(self, content, *args):
+        for arg in args:
+            for k, v in arg.iteritems():
+                if k == 'installers':
+                    for inner in v.values():
+                        for i_k, i_v in inner.iteritems():
+                            if i_k == 'installer':
+                                return self._in_scenarios_installer(i_v,
+                                                                    content)
+                            elif i_k == 'versions.version':
+                                return self._in_scenarios_version(i_v,
+                                                                  content)
+                            elif i_k == 'versions.projects.project':
+                                return self._in_scenarios_project(i_v,
+                                                                  content)
+                elif content.get(k, None) != v:
+                    return False
+
+        return True
+
+    def _in_others(self, content, *args):
         for arg in args:
             for k, v in arg.iteritems():
                 if k == 'start_date':
@@ -185,8 +237,8 @@ def __getattr__(name):
     return globals()[name]
 
 
-pods = MemDb()
-projects = MemDb()
-testcases = MemDb()
-results = MemDb()
-scenarios = MemDb()
+pods = MemDb('pods')
+projects = MemDb('projects')
+testcases = MemDb('testcases')
+results = MemDb('results')
+scenarios = MemDb('scenarios')
diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/scenario-c2.json b/utils/test/testapi/opnfv_testapi/tests/unit/scenario-c2.json
new file mode 100644 (file)
index 0000000..b6a3b83
--- /dev/null
@@ -0,0 +1,73 @@
+{
+  "name": "odl_2-nofeature-ha",
+  "installers":
+  [
+    {
+      "installer": "fuel",
+      "versions":
+      [
+        {
+          "owner": "Lucky",
+          "version": "colorado",
+          "projects":
+          [
+            {
+              "project": "functest",
+              "customs": [ "healthcheck", "vping_ssh"],
+              "scores": [],
+              "trust_indicators": [
+                {
+                  "date": "2017-01-18 22:46:44",
+                  "status": "silver"
+                }
+
+              ]
+            },
+            {
+              "project": "yardstick",
+              "customs": ["suite-a"],
+              "scores": [
+                {
+                  "date": "2017-01-08 22:46:44",
+                  "score": "0"
+                }
+              ],
+              "trust_indicators": [
+                {
+                  "date": "2017-01-18 22:46:44",
+                  "status": "gold"
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "owner": "Luke",
+          "version": "colorado",
+          "projects":
+          [
+            {
+              "project": "functest",
+              "customs": [ "healthcheck", "vping_ssh"],
+              "scores":
+              [
+                {
+                  "date": "2017-01-09 22:46:44",
+                  "score": "11/14"
+                }
+
+              ],
+              "trust_indicators": []
+            },
+            {
+              "project": "yardstick",
+              "customs": [],
+              "scores": [],
+              "trust_indicators": []
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
index 9343ab2..fc780e4 100644 (file)
@@ -47,11 +47,11 @@ class TestBase(AsyncHTTPTestCase):
         return self.create_help(self.basePath, req, *args)
 
     def create_help(self, uri, req, *args):
-        if req and not isinstance(req, str):
-            req = json.dumps(req.format())
+        if req and not isinstance(req, str) and hasattr(req, 'format'):
+            req = req.format()
         res = self.fetch(self._update_uri(uri, *args),
                          method='POST',
-                         body=req if req else json.dumps(None),
+                         body=json.dumps(req),
                          headers=self.headers)
 
         return self._get_return(res, self.create_res)
@@ -97,7 +97,7 @@ class TestBase(AsyncHTTPTestCase):
         return uri.count('%s')
 
     def _get_query_uri(self, query):
-        return self.basePath + '?' + query
+        return self.basePath + '?' + query if query else self.basePath
 
     def _get_uri(self, *args):
         return self._update_uri(self.basePath, *args)
index 8e82781..ff59795 100644 (file)
@@ -4,15 +4,20 @@ import os
 from opnfv_testapi.common.constants import HTTP_BAD_REQUEST
 from opnfv_testapi.common.constants import HTTP_FORBIDDEN
 from opnfv_testapi.common.constants import HTTP_OK
+from opnfv_testapi.resources.scenario_models import Scenario
 from opnfv_testapi.resources.scenario_models import ScenarioCreateRequest
+from opnfv_testapi.resources.scenario_models import Scenarios
 from test_testcase import TestBase
 
 
 class TestScenarioBase(TestBase):
     def setUp(self):
         super(TestScenarioBase, self).setUp()
+        self.get_res = Scenario
+        self.list_res = Scenarios
         self.basePath = '/api/v1/scenarios'
-        self.load_request('scenario-create.json')
+        self.req_d = self._load_request('scenario-c1.json')
+        self.req_2 = self._load_request('scenario-c2.json')
 
     def tearDown(self):
         pass
@@ -20,10 +25,26 @@ class TestScenarioBase(TestBase):
     def assert_body(self, project, req=None):
         pass
 
-    def load_request(self, f_req):
-        with open(os.path.join(os.path.dirname(__file__), f_req), 'r') as f:
-            self.req_d = json.dumps(json.load(f))
+    @staticmethod
+    def _load_request(f_req):
+        abs_file = os.path.join(os.path.dirname(__file__), f_req)
+        with open(abs_file, 'r') as f:
+            loader = json.load(f)
             f.close()
+        return loader
+
+    def create_return_name(self, req):
+        _, res = self.create(req)
+        return res.href.split('/')[-1]
+
+    def assert_res(self, code, scenario, req=None):
+        self.assertEqual(code, HTTP_OK)
+        if req is None:
+            req = self.req_d
+        scenario_dict = scenario.format_http()
+        self.assertIsNotNone(scenario_dict['_id'])
+        self.assertIsNotNone(scenario_dict['creation_date'])
+        self.assertDictContainsSubset(req, scenario_dict)
 
 
 class TestScenarioCreate(TestScenarioBase):
@@ -53,3 +74,60 @@ class TestScenarioCreate(TestScenarioBase):
         (code, body) = self.create_d()
         self.assertEqual(code, HTTP_FORBIDDEN)
         self.assertIn('already exists', body)
+
+
+class TestScenarioGet(TestScenarioBase):
+    def setUp(self):
+        super(TestScenarioGet, self).setUp()
+        self.scenario_1 = self.create_return_name(self.req_d)
+        self.scenario_2 = self.create_return_name(self.req_2)
+
+    def test_getByName(self):
+        code, body = self.get(self.scenario_1)
+        self.assert_res(code, body, req=self.req_d)
+
+    def test_getAll(self):
+        self._query_and_assert(query=None, reqs=[self.req_d, self.req_2])
+
+    def test_queryName(self):
+        query = self._set_query('name=nosdn-nofeature-ha')
+        self._query_and_assert(query, reqs=[self.req_d])
+
+    def test_queryInstaller(self):
+        query = self._set_query('installer=apex')
+        self._query_and_assert(query, reqs=[self.req_d])
+
+    def test_queryVersion(self):
+        query = self._set_query('version=master')
+        self._query_and_assert(query, reqs=[self.req_d])
+
+    def test_queryProject(self):
+        query = self._set_query('project=functest')
+        self._query_and_assert(query, reqs=[self.req_d, self.req_2])
+
+    def test_queryCombination(self):
+        query = self._set_query('name=nosdn-nofeature-ha',
+                                'installer=apex',
+                                'version=master',
+                                'project=functest')
+
+        self._query_and_assert(query, reqs=[self.req_d])
+
+    @staticmethod
+    def _set_query(*args):
+        uri = ''
+        for arg in args:
+            uri += arg + '&'
+        return uri[0: -1]
+
+    def _query_and_assert(self, query, found=True, reqs=None):
+        code, body = self.query(query)
+        if not found:
+            self.assertEqual(code, HTTP_OK)
+            self.assertEqual(0, len(body.scenarios))
+        else:
+            self.assertEqual(len(reqs), len(body.scenarios))
+            for req in reqs:
+                for scenario in body.scenarios:
+                    if req['name'] == scenario.name:
+                        self.assert_res(code, scenario, req)
index 9b25f8f..d1f05f2 100755 (executable)
@@ -1,10 +1,40 @@
-#! /bin/bash
+#!/bin/bash
 
-# Before run this script, make sure that testtools and discover
-# had been installed in your env
-# or else using pip to install them as follows:
-# pip install testtools, discover
+set -o errexit
+
+# Get script directory
+SCRIPTDIR=`dirname $0`
+
+# Either Workspace is set (CI)
+if [ -z $WORKSPACE ]
+then
+    WORKSPACE="."
+fi
+
+echo "Running unit tests..."
+
+# Creating virtual environment
+virtualenv $WORKSPACE/testapi_venv
+source $WORKSPACE/testapi_venv/bin/activate
+
+# Install requirements
+pip install -r $SCRIPTDIR/requirements.txt
 
 find . -type f -name "*.pyc" -delete
-testrargs="discover ./opnfv_testapi/tests/unit"
-python -m testtools.run $testrargs
+
+nosetests --with-xunit \
+    --with-coverage \
+    --cover-erase \
+    --cover-package=$SCRIPTDIR/opnfv_testapi/cmd \
+    --cover-package=$SCRIPTDIR/opnfv_testapi/commonn \
+    --cover-package=$SCRIPTDIR/opnfv_testapi/resources \
+    --cover-package=$SCRIPTDIR/opnfv_testapi/router \
+    --cover-xml \
+    --cover-html \
+    $SCRIPTDIR/opnfv_testapi/tests
+
+exit_code=$?
+
+deactivate
+
+exit $exit_code
diff --git a/utils/test/testapi/test-requirements.txt b/utils/test/testapi/test-requirements.txt
deleted file mode 100644 (file)
index ddbdefc..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# The order of packages is significant, because pip processes them in the order
-# of appearance. Changing the order has an impact on the overall integration
-# process, which may cause wedges in the gate later.
-
-testtools>=1.4.0
-discover
-futures
\ No newline at end of file