Merge "[Daisy] Add docker image tarball builder"
authorTrevor Bramwell <tbramwell@linuxfoundation.org>
Fri, 3 Nov 2017 20:45:21 +0000 (20:45 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Fri, 3 Nov 2017 20:45:21 +0000 (20:45 +0000)
97 files changed:
.gitignore
docs/jenkins-job-builder/opnfv-jjb-usage.rst
jjb/bottlenecks/bottlenecks-run-suite.sh
jjb/compass4nfv/compass-dovetail-jobs.yml
jjb/container4nfv/container4nfv-project.yml
jjb/daisy4nfv/daisy-daily-jobs.yml
jjb/doctor/doctor.yml
jjb/dovetail/dovetail-ci-jobs.yml
jjb/global/installer-params.yml
jjb/global/releng-macros.yml
jjb/global/slave-params.yml
jjb/kvmfornfv/kvmfornfv.yml
jjb/opnfvdocs/docs-rtd.yaml
jjb/opnfvdocs/opnfvdocs.yml
jjb/pharos/pharos.yml
jjb/qtip/qtip-experimental-jobs.yml
jjb/qtip/qtip-validate-jobs.yml
jjb/releng/functest-docker.yml [new file with mode: 0644]
jjb/releng/opnfv-docs.yml [deleted file]
jjb/releng/opnfv-manifest.sh [new file with mode: 0755]
jjb/vswitchperf/vswitchperf.yml
jjb/yardstick/yardstick-daily-jobs.yml
modules/opnfv/utils/ovs_logger.py
modules/requirements.txt
modules/setup.py
modules/test-requirements.txt
utils/test/testapi/.gitignore
utils/test/testapi/3rd_party/static/testapi-ui/Gruntfile.js [new file with mode: 0644]
utils/test/testapi/3rd_party/static/testapi-ui/package.json [new file with mode: 0644]
utils/test/testapi/docs/Makefile [new file with mode: 0644]
utils/test/testapi/docs/conf.py [new file with mode: 0644]
utils/test/testapi/docs/developer/devguide/api.rst [new file with mode: 0644]
utils/test/testapi/docs/developer/devguide/framework.rst [moved from utils/test/testapi/README.rst with 92% similarity]
utils/test/testapi/docs/developer/devguide/index.rst [new file with mode: 0644]
utils/test/testapi/docs/developer/devguide/overview.rst [new file with mode: 0644]
utils/test/testapi/docs/developer/devguide/swagger-ui.rst [new file with mode: 0644]
utils/test/testapi/docs/developer/devguide/testapi-client.rst [new file with mode: 0644]
utils/test/testapi/docs/developer/devguide/web-portal.rst [new file with mode: 0644]
utils/test/testapi/docs/index.rst [new file with mode: 0644]
utils/test/testapi/opnfv_testapi/common/config.py
utils/test/testapi/opnfv_testapi/handlers/__init__.py [moved from utils/test/testapi/opnfv_testapi/tests/unit/resources/__init__.py with 100% similarity]
utils/test/testapi/opnfv_testapi/handlers/base_handlers.py [moved from utils/test/testapi/opnfv_testapi/resources/handlers.py with 98% similarity]
utils/test/testapi/opnfv_testapi/handlers/pod_handlers.py [moved from utils/test/testapi/opnfv_testapi/resources/pod_handlers.py with 94% similarity]
utils/test/testapi/opnfv_testapi/handlers/project_handlers.py [moved from utils/test/testapi/opnfv_testapi/resources/project_handlers.py with 95% similarity]
utils/test/testapi/opnfv_testapi/handlers/result_handlers.py [moved from utils/test/testapi/opnfv_testapi/resources/result_handlers.py with 98% similarity]
utils/test/testapi/opnfv_testapi/handlers/root_handlers.py [moved from utils/test/testapi/opnfv_testapi/ui/root.py with 64% similarity]
utils/test/testapi/opnfv_testapi/handlers/scenario_handlers.py [moved from utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py with 99% similarity]
utils/test/testapi/opnfv_testapi/handlers/sign_handlers.py [moved from utils/test/testapi/opnfv_testapi/ui/auth/sign.py with 94% similarity]
utils/test/testapi/opnfv_testapi/handlers/testcase_handlers.py [moved from utils/test/testapi/opnfv_testapi/resources/testcase_handlers.py with 96% similarity]
utils/test/testapi/opnfv_testapi/handlers/user_handlers.py [moved from utils/test/testapi/opnfv_testapi/ui/auth/user.py with 70% similarity]
utils/test/testapi/opnfv_testapi/models/__init__.py [moved from utils/test/testapi/opnfv_testapi/resources/__init__.py with 100% similarity]
utils/test/testapi/opnfv_testapi/models/base_models.py [moved from utils/test/testapi/opnfv_testapi/resources/models.py with 98% similarity]
utils/test/testapi/opnfv_testapi/models/pod_models.py [moved from utils/test/testapi/opnfv_testapi/resources/pod_models.py with 89% similarity]
utils/test/testapi/opnfv_testapi/models/project_models.py [moved from utils/test/testapi/opnfv_testapi/resources/project_models.py with 85% similarity]
utils/test/testapi/opnfv_testapi/models/result_models.py [moved from utils/test/testapi/opnfv_testapi/resources/result_models.py with 92% similarity]
utils/test/testapi/opnfv_testapi/models/scenario_models.py [moved from utils/test/testapi/opnfv_testapi/resources/scenario_models.py with 91% similarity]
utils/test/testapi/opnfv_testapi/models/testcase_models.py [moved from utils/test/testapi/opnfv_testapi/resources/testcase_models.py with 93% similarity]
utils/test/testapi/opnfv_testapi/models/user_models.py [new file with mode: 0644]
utils/test/testapi/opnfv_testapi/router/url_mappings.py
utils/test/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js [new file with mode: 0644]
utils/test/testapi/opnfv_testapi/tests/UI/karma.conf.js [new file with mode: 0644]
utils/test/testapi/opnfv_testapi/tests/UI/protractor-conf.js [new file with mode: 0644]
utils/test/testapi/opnfv_testapi/tests/unit/executor.py
utils/test/testapi/opnfv_testapi/tests/unit/handlers/__init__.py [moved from utils/test/testapi/opnfv_testapi/ui/__init__.py with 100% similarity]
utils/test/testapi/opnfv_testapi/tests/unit/handlers/scenario-c1.json [moved from utils/test/testapi/opnfv_testapi/tests/unit/resources/scenario-c1.json with 100% similarity]
utils/test/testapi/opnfv_testapi/tests/unit/handlers/scenario-c2.json [moved from utils/test/testapi/opnfv_testapi/tests/unit/resources/scenario-c2.json with 100% similarity]
utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_base.py [moved from utils/test/testapi/opnfv_testapi/tests/unit/resources/test_base.py with 98% similarity]
utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_pod.py [moved from utils/test/testapi/opnfv_testapi/tests/unit/resources/test_pod.py with 97% similarity]
utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_project.py [moved from utils/test/testapi/opnfv_testapi/tests/unit/resources/test_project.py with 97% similarity]
utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_result.py [moved from utils/test/testapi/opnfv_testapi/tests/unit/resources/test_result.py with 98% similarity]
utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py [moved from utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py with 99% similarity]
utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py [moved from utils/test/testapi/opnfv_testapi/tests/unit/resources/test_testcase.py with 97% similarity]
utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_token.py [moved from utils/test/testapi/opnfv_testapi/tests/unit/resources/test_token.py with 96% similarity]
utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_version.py [moved from utils/test/testapi/opnfv_testapi/tests/unit/resources/test_version.py with 87% similarity]
utils/test/testapi/opnfv_testapi/tests/unit/resources/test_fake_pymongo.py [deleted file]
utils/test/testapi/opnfv_testapi/tornado_swagger/handlers.py
utils/test/testapi/opnfv_testapi/ui/about/about.html [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/about/about.html with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/auth-failure/authFailureController.js [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/auth-failure/authFailureController.js with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/auth/__init__.py [deleted file]
utils/test/testapi/opnfv_testapi/ui/home/home.html [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/home/home.html with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/logout/logout.html [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/logout/logout.html with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/logout/logoutController.js [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/logout/logoutController.js with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/pods/pods.html [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/pods/pods.html with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/pods/podsController.js [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/pods/podsController.js with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/profile/importPubKeyModal.html [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/profile/importPubKeyModal.html with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/profile/profile.html [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/profile/profile.html with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/profile/profileController.js [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/profile/profileController.js with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/profile/showPubKeyModal.html [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/profile/showPubKeyModal.html with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/results-report/partials/editTestModal.html [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/results-report/partials/editTestModal.html with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/results-report/partials/fullTestListModal.html [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/results-report/partials/fullTestListModal.html with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/results-report/partials/reportDetails.html [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/results-report/partials/reportDetails.html with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/results-report/resultsReport.html [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/results-report/resultsReport.html with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/results-report/resultsReportController.js [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/results-report/resultsReportController.js with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/results/results.html [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/results/results.html with 100% similarity]
utils/test/testapi/opnfv_testapi/ui/results/resultsController.js [moved from utils/test/testapi/3rd_party/static/testapi-ui/components/results/resultsController.js with 100% similarity]
utils/test/testapi/setup.cfg
utils/test/testapi/tox.ini

index eeabaeb..2c18948 100644 (file)
@@ -36,3 +36,4 @@ testapi_venv/
 .tox
 *.retry
 job_output/
+utils/test/testapi/opnfv_testapi/tests/UI/coverage
index f34833f..062cf82 100644 (file)
@@ -29,7 +29,7 @@ Submit the change to gerrit::
 
     git review -v
 
-Follow the link to gerrit https://gerrit.opnfv.org/gerrit/51 in a few moments
+Follow the link given in the stdoutput to gerrit eg: https://gerrit.opnfv.org/gerrit/"Your_Change_ID"
 the verify job will have completed and you will see Verified +1 jenkins-ci in
 the gerrit ui.
 
@@ -65,24 +65,12 @@ it will reset the verified status to 0. If you want to keep the verified
 status, use **recheck-experimental** in commit message to trigger both
 verify and experimental jobs.
 
-You can add below persons as reviewers to your patch in order to get it
+You can look in the releng/INFO file for a list of current committers to add as reviewers to your patch in order to get it
 reviewed and submitted.
 
-* fatih.degirmenci@ericsson.com
-* agardner@linuxfoundation.org
-* trozet@redhat.com
-* morgan.richomme@orange.com
-* vlaza@cloudbasesolutions.com
-* matthew.lijun@huawei.com
-* meimei@huawei.com
-* jose.lausuch@ericsson.com
-* koffirodrigue@gmail.com
-* r-mibu@cq.jp.nec.com
-* tbramwell@linuxfoundation.org
-
 Or Add the group releng-contributors
 
-Or just email a request for submission to opnfv-helpdesk@rt.linuxfoundation.org
+Or just email a request for review to helpdesk@opnfv.org
 
 The Current merge and verify jobs for jenkins job builder can be found
 in `releng-jobs.yaml`_.
index cdcf0f0..ebd905e 100644 (file)
@@ -32,16 +32,12 @@ if [[ $SUITE_NAME == *posca* ]]; then
     # Preparing OpenStack RC and Cacert files
     echo "BOTTLENECKS INFO: fetching os credentials from $INSTALLER_TYPE"
     if [[ $INSTALLER_TYPE == 'compass' ]]; then
-        if [[ ${BRANCH} == 'master' ]]; then
-            ${RELENG_REPO}/utils/fetch_os_creds.sh -d ${OPENRC} -i ${INSTALLER_TYPE} -a ${INSTALLER_IP} -o ${OS_CACERT} >${redirect}
-            if [[ -f ${OS_CACERT} ]]; then
-                echo "BOTTLENECKS INFO: successfully fetching os_cacert for openstack: ${OS_CACERT}"
-            else
-                echo "BOTTLENECKS ERROR: couldn't find os_cacert file: ${OS_CACERT}, please check if the it's been properly provided."
-                exit 1
-            fi
+        ${RELENG_REPO}/utils/fetch_os_creds.sh -d ${OPENRC} -i ${INSTALLER_TYPE} -a ${INSTALLER_IP} -o ${OS_CACERT} >${redirect}
+        if [[ -f ${OS_CACERT} ]]; then
+            echo "BOTTLENECKS INFO: successfully fetching os_cacert for openstack: ${OS_CACERT}"
         else
-            ${RELENG_REPO}/utils/fetch_os_creds.sh -d ${OPENRC} -i ${INSTALLER_TYPE} -a ${INSTALLER_IP}  >${redirect}
+            echo "BOTTLENECKS ERROR: couldn't find os_cacert file: ${OS_CACERT}, please check if the it's been properly provided."
+            exit 1
         fi
     fi
 
index f0e1c2d..c090863 100644 (file)
 - trigger:
     name: 'compass-os-nosdn-nofeature-ha-baremetal-weekly-danube-trigger'
     triggers:
-      - timed: 'H H * * 0'
+      - timed: ''  # 'H H * * 0'
 
 - trigger:
     name: 'dovetail-weekly-trigger'
     triggers:
-      - timed: 'H H * * 0'
+      - timed: ''  # 'H H * * 0'
index c7666a1..9e2d313 100644 (file)
@@ -10,6 +10,7 @@
 
     jobs:
       - 'container4nfv-verify-{stream}'
+      - 'container4nfv-daily-{stream}'
 
     stream:
       - master:
       - project-parameter:
           project: '{project}'
           branch: '{branch}'
+      # yamllint disable rule:line-length
+      - string:
+          name: GIT_BASE
+          default: https://gerrit.opnfv.org/gerrit/$PROJECT
+          description: "Used for overriding the GIT URL coming from Global Jenkins configuration in case if the stuff is done on none-LF HW."
+      # yamllint enable rule:line-length
       - 'opnfv-build-ubuntu-defaults'
 
     scm:
       - shell: |
           cd $WORKSPACE/ci
           ./build.sh
+
+
+- job-template:
+    name: 'container4nfv-daily-{stream}'
+
+    project-type: freestyle
+
+    disabled: '{obj:disabled}'
+
+    concurrent: false
+
+    properties:
+      - logrotate-default
+
+    parameters:
+      - project-parameter:
+          project: '{project}'
+          branch: '{branch}'
+      # yamllint disable rule:line-length
+      - string:
+          name: GIT_BASE
+          default: https://gerrit.opnfv.org/gerrit/$PROJECT
+          description: "Used for overriding the GIT URL coming from Global Jenkins configuration in case if the stuff is done on none-LF HW."
+      # yamllint enable rule:line-length
+      - node:
+          name: SLAVE_NAME
+          description: 'Slave name on Jenkins'
+          allowed-slaves:
+            - huawei-virtual6
+          default-slaves:
+            - huawei-virtual6
+
+    scm:
+      - git-scm
+
+    triggers:
+      - timed: '@midnight'
+
+    builders:
+      - shell: |
+          cd $WORKSPACE/ci
+          ./deploy.sh
index 2f09149..00024e8 100644 (file)
               build-step-failure-threshold: 'never'
               failure-threshold: 'never'
               unstable-threshold: 'FAILURE'
+      - conditional-step:
+          condition-kind: and
+          condition-operands:
+            - condition-kind: regex-match
+              regex: 'baremetal'
+              label: '{pod}'
+            - condition-kind: regex-match
+              regex: 'master'
+              label: '{stream}'
+          steps:
+            - trigger-builds:
+                - project: 'yardstick-daisy-{pod}-daily-{stream}'
+                  current-parameters: false
+                  predefined-parameters:
+                    DEPLOY_SCENARIO={scenario}
+                  block: true
+                  same-node: true
+                  block-thresholds:
+                    build-step-failure-threshold: 'never'
+                    failure-threshold: 'never'
+                    unstable-threshold: 'FAILURE'
 
 - job-template:
     name: '{project}-deploy-{pod}-daily-{stream}'
 - trigger:
     name: 'daisy-os-nosdn-nofeature-ha-baremetal-daily-master-trigger'
     triggers:
-      - timed: '0 16 * * *'
+      - timed: '0 18 * * *'
 # Basic NOHA Scenarios
 - trigger:
     name: 'daisy-os-nosdn-nofeature-noha-baremetal-daily-master-trigger'
index 6a04c5f..e28f744 100644 (file)
     #     slave-label: 'ool-virtual3'
     #     pod: 'ool-virtual3'
 
+    phase:
+      - 'build-x86_64':
+          slave-label: 'opnfv-build-ubuntu'
+      - 'build-aarch64':
+          slave-label: 'opnfv-build-ubuntu-arm'
+
     inspector:
       - 'sample'
       - 'congress'
           auto-trigger-name: 'doctor-verify'
           is-python: true
 
-    pod:
-      - armband-baremetal:
-          slave-label: '{pod}'
-      - armband-virtual:
-          slave-label: '{pod}'
+    exclude:
+      - installer: 'apex'
+        phase: 'build-aarch64'
 
     jobs:
       - 'doctor-verify-{stream}'
-      - 'doctor-{task}-{installer}-{inspector}-{pod}-{stream}'
+      - 'doctor-verify-unit-test-{stream}'
       - 'doctor-{task}-{installer}-{inspector}-{stream}'
+      - 'doctor-{task}-{installer}-{inspector}-{phase}-{stream}'
 
 - job-template:
     name: 'doctor-verify-{stream}'
 
     disabled: '{obj:disabled}'
 
+    project-type: 'multijob'
+
     parameters:
       - project-parameter:
           project: '{project}'
                   pattern: 'doctor_tests/**'
 
     builders:
-      - shell: "[ -e tests/run.sh ] && bash -n ./tests/run.sh"
+      - shell: |
+         #!/bin/bash
+         # we do nothing here as the main stuff will be done
+         # in phase jobs
+         echo "Triggering phase jobs!"
+      - multijob:
+          name: 'doctor-build-and-unittest'
+          execution-type: PARALLEL
+          projects:
+            - name: 'doctor-verify-unit-test-{stream}'
+              current-parameters: false
+              predefined-parameters: |
+                GERRIT_BRANCH=$GERRIT_BRANCH
+                GERRIT_REFSPEC=$GERRIT_REFSPEC
+                GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER
+                GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE
+              git-revision: true
+              node-parameters: false
+              kill-phase-on: FAILURE
+              abort-all-job: false
 
 - job-template:
-    name: 'doctor-{task}-{installer}-{inspector}-{pod}-{stream}'
-
-    node: '{slave-label}'
-
+    name: 'doctor-verify-unit-test-{stream}'
     disabled: '{obj:disabled}'
-
+    wrappers:
+      - ssh-agent-wrapper
+      - build-timeout:
+          timeout: 60
     parameters:
       - project-parameter:
           project: '{project}'
           branch: '{branch}'
       - 'opnfv-build-ubuntu-defaults'
-
     scm:
       - git-scm-gerrit
-
-
-    triggers:
-      - '{auto-trigger-name}':
-          project: '{project}'
-          branch: '{branch}'
-          files: 'doctor_tests/**'
-
     builders:
-      - shell: "[ -e tests/run.sh ] && bash -n ./tests/run.sh"
+      - 'doctor-verify-unit-test-builders-macro'
+    publishers:
+      - 'doctor-verify-unit-test-publishers-macro'
 
 
 - job-template:
     name: 'doctor-{task}-{installer}-{inspector}-{stream}'
 
+    disabled: '{obj:disabled}'
+
+    project-type: 'multijob'
+
     node: '{slave-label}'
 
     parameters:
           default: 'doctor-notification'
       - string:
           name: TESTCASE_OPTIONS
+          # yamllint disable rule:line-length
           default: '-e INSPECTOR_TYPE={inspector} -e PYTHON_ENABLE={is-python} -v $WORKSPACE:/home/opnfv/repos/doctor'
+          # yamllint enable rule:line-length
           description: 'Addtional parameters specific to test case(s)'
       # functest-parameter
       - string:
           name: GS_PATHNAME
           default: '{gs-pathname}'
+          # yamllint disable rule:line-length
           description: "Version directory where the opnfv documents will be stored in gs repository"
+          # yamllint enable rule:line-length
       - string:
           name: FUNCTEST_REPO_DIR
           default: "/home/opnfv/repos/functest"
           branch: '{branch}'
           files: 'doctor_tests/**'
 
+    builders:
+      - shell: |
+         #!/bin/bash
+         # we do nothing here as the main stuff will be done
+         # in phase jobs
+         echo "Triggering phase jobs!"
+      - multijob:
+          name: 'doctor-verify-installer-inspector'
+          execution-type: PARALLEL
+          projects:
+            - name: 'doctor-{task}-{installer}-{inspector}-build-x86_64-{stream}'
+              current-parameters: false
+              git-revision: true
+              node-parameters: false
+              kill-phase-on: FAILURE
+              abort-all-job: false
+            - name: 'doctor-{task}-{installer}-{inspector}-build-aarch64-{stream}'
+              current-parameters: false
+              git-revision: true
+              node-parameters: false
+              kill-phase-on: FAILURE
+              abort-all-job: false
+
+- job-template:
+    name: 'doctor-{task}-{installer}-{inspector}-{phase}-{stream}'
+    disabled: '{obj:disabled}'
+    wrappers:
+      - ssh-agent-wrapper
+      - build-timeout:
+          timeout: 30
+    parameters:
+      - project-parameter:
+          project: '{project}'
+          branch: '{branch}'
+      - '{slave-label}-defaults'
+    scm:
+      - git-scm-gerrit
+    builders:
+      - 'doctor-verify-installer-inspector-builders-macro'
+    publishers:
+      - 'doctor-verify-publishers-macro'
+# -------------------------------
+# builder macros
+# -------------------------------
+
+- builder:
+    name: 'doctor-verify-unit-test-builders-macro'
+    builders:
+      - shell: "[ -e tests/run.sh ] && bash -n ./tests/run.sh"
+- builder:
+    name: 'doctor-verify-installer-inspector-builders-macro'
     builders:
       - 'clean-workspace-log'
+      # yamllint disable rule:line-length
       - shell: |
           # NOTE: Create symbolic link, so that we can archive file outside
           #       of $WORKSPACE .
           # NOTE: checking the test result, as the previous job could return
           #       0 regardless the result of doctor test scenario.
           grep -e 'doctor test successfully' $functest_log || exit 1
+      # yamllint enable rule:line-length
 
+# -------------------------------
+# publisher macros
+# -------------------------------
+- publisher:
+    name: 'doctor-verify-publishers-macro'
     publishers:
       - archive:
           artifacts: 'doctor_tests/*.log'
       - archive:
           artifacts: 'functest_results/$FUNCTEST_SUITE_NAME.log'
       - email-jenkins-admins-on-failure
-
+- publisher:
+    name: 'doctor-verify-unit-test-publishers-macro'
+    publishers:
+      - email-jenkins-admins-on-failure
 
 #####################################
 # trigger macros
index 9fde120..6efe128 100644 (file)
@@ -25,7 +25,7 @@
       branch: 'stable/{stream}'
       dovetail-branch: master
       gs-pathname: '/{stream}'
-      docker-tag: 'cvp.0.7.0'
+      docker-tag: 'cvp.0.8.0'
 
     # ----------------------------------
     # POD, PLATFORM, AND BRANCH MAPPING
index 1415a6e..916db80 100644 (file)
           name: BRIDGE
           default: 'br7'
           description: 'pxe bridge for booting of Daisy master'
+      - string:
+          name: EXTERNAL_NETWORK
+          default: 'admin_external'
+          description: 'external network for test'
 
 - parameter:
     name: 'infra-defaults'
index 59415f5..17c451c 100644 (file)
                 - compare-type: 'ANT'
                   pattern: '{files}'
 
+- trigger:
+    name: gerrit-trigger-tag-created
+    triggers:
+      - gerrit:
+          server-name: 'gerrit.opnfv.org'
+          trigger-on:
+            - ref-updated
+          projects:
+            - project-compare-type: 'ANT'
+              project-pattern: '{project}'
+              branches:
+                - branch-compare-type: 'ANT'
+                  branch-pattern: 'refs/tags/**'
+
 - trigger:
     name: 'experimental'
     triggers:
              #!/bin/bash
              sudo chown -R $USER:$USER $WORKSPACE || exit 1
 
-- builder:
-    name: build-html-and-pdf-docs-output
-    builders:
-      - shell: |
-          #!/bin/bash
-          set -o errexit
-          set -o xtrace
-          export PATH=$PATH:/usr/local/bin/
-          git clone ssh://gerrit.opnfv.org:29418/opnfvdocs docs_build/_opnfvdocs
-          GERRIT_COMMENT=gerrit_comment.txt ./docs_build/_opnfvdocs/scripts/docs-build.sh
-
 - builder:
     name: upload-under-review-docs-to-opnfv-artifacts
     builders:
           export PATH=$PATH:/usr/local/bin/
 
           [[ $GERRIT_CHANGE_NUMBER =~ .+ ]]
-          [[ -d docs_output ]] || exit 0
+          [[ -d docs/_build/ ]] || exit 0
 
           echo
           echo "###########################"
           local_path="upload/$GERRIT_CHANGE_NUMBER"
 
           mkdir -p upload
-          mv docs_output "$local_path"
+          mv docs/_build/html/ "$local_path"
           gsutil -m cp -r "$local_path" "gs://$gs_base"
 
           gsutil -m setmeta \
           find "$local_path" | grep -e 'index.html$' -e 'pdf$' | \
               sed -e "s|^$local_path|    http://$gs_path|" >> gerrit_comment.txt
 
-- builder:
-    name: upload-generated-docs-to-opnfv-artifacts
-    builders:
-      - shell: |
-          #!/bin/bash
-          set -o errexit
-          set -o pipefail
-          set -o xtrace
-          export PATH=$PATH:/usr/local/bin/
-
-          [[ -d docs_output ]] || exit 0
-
-          echo
-          echo "########################"
-          echo "UPLOADING GENERATED DOCS"
-          echo "########################"
-          echo
-
-          echo "gs_path="$GS_URL/docs""
-          echo "local_path="upload/docs""
-
-          gs_path="$GS_URL/docs"
-          local_path="upload/docs"
-
-          mkdir -p upload
-          mv docs_output "$local_path"
-          ls "$local_path"
-
-          echo "gsutil -m cp -r "$local_path"/* "gs://$gs_path""
-          gsutil -m cp -r "$local_path"/* "gs://$gs_path"
-
-          gsutil -m setmeta \
-              -h "Content-Type:text/html" \
-              -h "Cache-Control:private, max-age=0, no-transform" \
-              "gs://$gs_path"/**.html > /dev/null 2>&1
-
-          echo "Document link(s):" >> gerrit_comment.txt
-          find "$local_path" | grep -e 'index.html$' -e 'pdf$' | \
-              sed -e "s|^$local_path|    http://$gs_path|" >> gerrit_comment.txt
-
 # To take advantage of this macro, have your build write
 # out the file 'gerrit_comment.txt' with information to post
 # back to gerrit and include this macro in the list of builders.
 - builder:
     name: upload-review-docs
     builders:
-      - build-html-and-pdf-docs-output
       - upload-under-review-docs-to-opnfv-artifacts
       - report-build-result-to-gerrit
 
-- builder:
-    name: upload-merged-docs
-    builders:
-      - build-html-and-pdf-docs-output
-      - upload-generated-docs-to-opnfv-artifacts
-      - report-build-result-to-gerrit
-      - remove-old-docs-from-opnfv-artifacts
-
 - builder:
     name: check-bash-syntax
     builders:
           # generate and upload lint log
           echo "Running yaml code on $PROJECT ..."
 
+          # Get list of yaml files
+          YAML_FILES=$(git --no-pager diff --diff-filter=MCRAT --name-only HEAD^1 | egrep "ya?ml$")
+
           # Ensure we start with a clean environment
           rm -f yaml-violation.log lint.log
 
-          # Get number of yaml violations. If none, this will be an
-          # empty string: ""
-          find . \
-              -type f -name "*.yml" -print \
-              -o -name "*.yaml" -print | \
-              xargs yamllint > yaml-violation.log || true
+          # Yamllint files only in patchset
+          for yamlfile in $YAML_FILES; do
+            yamllint $yamlfile >> yaml-violation.log || true
+          done
 
           if [ -s "yaml-violation.log" ]; then
-            SHOWN=$(cat yaml-violation.log| grep -v "^$" |wc -l)
+            SHOWN=$(grep -c -v "^$" yaml-violation.log)
             echo -e "First $SHOWN shown\n---" > lint.log
             cat yaml-violation.log >> lint.log
             sed -r -i '4,$s/^/ /g' lint.log
index 5b94607..0ea37d9 100644 (file)
           description: 'pxe bridge for booting of Daisy master'
 
 - parameter:
-    name: zte-pod4-defaults
+    name: zte-virtual5-defaults
     parameters:
       - node:
           name: SLAVE_NAME
           description: 'Slave name on Jenkins'
           allowed-slaves:
-            - zte-pod4
+            - zte-virtual5
           default-slaves:
-            - zte-pod4
+            - zte-virtual5
       - string:
           name: GIT_BASE
           default: https://gerrit.opnfv.org/gerrit/$PROJECT
index ad497e9..aae6e02 100644 (file)
@@ -8,7 +8,7 @@
       - master:
           branch: '{stream}'
           gs-pathname: ''
-          disabled: false
+          disabled: true
       - euphrates:
           branch: 'stable/{stream}'
           gs-pathname: '/{stream}'
index c989595..28f9354 100644 (file)
@@ -8,6 +8,8 @@
     stream:
       - master:
           branch: 'master'
+      - danube:
+          branch: 'stable/{stream}'
       - euphrates:
           branch: 'stable/{stream}'
 
@@ -36,6 +38,7 @@
           files: 'docs/**/*.*'
 
     builders:
+      - 'remove-old-docs-from-opnfv-artifacts'
       - shell: |
           if [ $GERRIT_BRANCH == "master" ]; then
             RTD_BUILD_VERSION=latest
@@ -89,4 +92,6 @@
           pip install --upgrade pip
           pip freeze
           pip install tox
+          sed -i s,\-b\ html,\-b\ singlehtml,g tox.ini
           tox -edocs
+      - 'upload-review-docs'
index 95bc8a9..3dfb9d1 100644 (file)
@@ -11,7 +11,6 @@
     jobs:
       - 'opnfvdocs-verify-shellcheck-{stream}'
       - 'opnfvdocs-merge-shellcheck-{stream}'
-      - 'opnfvdocs-daily-{stream}'
 
     stream:
       - master:
 
     builders:
       - check-bash-syntax
-
-- job-template:
-    name: 'opnfvdocs-daily-{stream}'
-
-    disabled: true
-
-    parameters:
-      - project-parameter:
-          project: '{project}'
-          branch: '{branch}'
-      - string:
-          name: GS_URL
-          default: '$GS_BASE{gs-pathname}'
-          description: "Directory where the build artifact will be located upon the completion of the build."
-      - string:
-          name: GIT_CLONE_BASE
-          default: ssh://gerrit.opnfv.org:29418
-          description: "Used for overriding the GIT URL coming from parameters macro."
-
-    scm:
-      - git-scm
-
-    triggers:
-      - timed: '0 H/6 * * *'
-
-    builders:
-      - build-html-and-pdf-docs-output
-#     - upload-generated-docs-to-opnfv-artifacts
index 0c104c0..7af4f0f 100644 (file)
@@ -6,10 +6,12 @@
 - project:
     name: pharos
 
-    project: '{name}'
+    project:
+      - '{name}'
+      - '{name}-tools'
 
     jobs:
-      - 'pharos-verify-{stream}'
+      - '{project}-verify-{stream}'
 
     stream:
       - master:
@@ -22,7 +24,7 @@
           disabled: false
 
 - job-template:
-    name: 'pharos-verify-{stream}'
+    name: '{project}-verify-{stream}'
 
     disabled: '{obj:disabled}'
 
index 4c336d1..fdfed26 100644 (file)
@@ -33,7 +33,7 @@
           branch: '{branch}'
       # Pin the tests on zte-pod4 with apex deployment
       - apex-defaults
-      - zte-pod4-defaults
+      - zte-virtual5-defaults
     scm:
       - git-scm-gerrit
 
index 42240ed..febe286 100644 (file)
     qpi:
       - compute:
           installer: apex
-          pod: zte-pod4
+          pod: zte-virtual5
           <<: *master
       - storage:
           installer: apex
-          pod: zte-pod4
+          pod: zte-virtual5
           <<: *master
       - compute:
           installer: apex
-          pod: zte-pod4
+          pod: zte-virtual5
           <<: *euphrates
       - storage:
           installer: apex
-          pod: zte-pod4
+          pod: zte-virtual5
           <<: *euphrates
 
     # -------------------------------
diff --git a/jjb/releng/functest-docker.yml b/jjb/releng/functest-docker.yml
new file mode 100644 (file)
index 0000000..2e24685
--- /dev/null
@@ -0,0 +1,256 @@
+---
+##############################################
+# job configuration for docker build and push
+##############################################
+- project:
+
+    name: functest-docker
+
+    project: functest
+
+    stream:
+      - master:
+          branch: '{stream}'
+          disabled: false
+      - euphrates:
+          branch: 'stable/{stream}'
+          disabled: false
+
+    arch_tag:
+      - 'amd64':
+          slave_label: 'opnfv-build-ubuntu'
+      - 'arm64':
+          slave_label: 'opnfv-build-ubuntu-arm'
+
+    # yamllint disable rule:key-duplicates
+    image:
+      - 'core'
+      - 'healthcheck'
+      - 'features'
+      - 'components'
+      - 'parser'
+      - 'smoke'
+      - 'vnf'
+      - 'restapi'
+
+    # settings for jobs run in multijob phases
+    build-job-settings: &build-job-settings
+      current-parameters: false
+      git-revision: true
+      node-parameters: true
+      predefined-parameters: |
+        PUSH_IMAGE=$PUSH_IMAGE
+        COMMIT_ID=$COMMIT_ID
+        RELEASE_VERSION=$RELEASE_VERSION
+        DOCKERFILE=$DOCKERFILE
+        ARCH_TAG=$ARCH_TAG
+      kill-phase-on: FAILURE
+      abort-all-jobs: false
+
+    manifest-job-settings: &manifest-job-settings
+      current-parameters: false
+      git-revision: true
+      node-parameters: true
+      predefined-parameters: |
+        RELEASE_VERSION=$RELEASE_VERSION
+        ARCH_TAG=$ARCH_TAG
+      kill-phase-on: FAILURE
+      abort-all-jobs: false
+
+    # yamllint enable rule:key-duplicates
+    jobs:
+      - "functest-docker-build-push-{arch_tag}-{stream}"
+      - "functest-{image}-build-push-{arch_tag}-{stream}"
+      - "functest-{image}-create-manifest-{arch_tag}-{stream}"
+########################
+# job templates
+########################
+- job-template:
+    name: 'functest-docker-build-push-{arch_tag}-{stream}'
+
+    project-type: multijob
+
+    disabled: '{obj:disabled}'
+
+    parameters:
+      - job-parameters:
+          project: '{project}'
+          branch: '{branch}'
+          slave_label: '{slave_label}'
+          arch_tag: '{arch_tag}'
+      - string:
+          name: ARCH_TAG
+          default: "{arch_tag}"
+          description: "If set, this value will be added to the docker image tag as a prefix"
+
+    properties:
+      - throttle:
+          max-per-node: 1
+          option: 'project'
+
+    scm:
+      - git-scm
+
+    triggers:
+      - pollscm:
+          cron: "*/30 * * * *"
+
+    builders:
+      - multijob:
+          name: 'build-base-img-create-manifest'
+          execution-type: SEQUENTIAL
+          projects:
+            - name: 'functest-core-build-push-{stream}'
+              <<: *build-job-settings
+            - name: 'functest-core-create-manifest-{stream}'
+              <<: *manifest-job-settings
+      - multijob:
+          name: 'build-child-img'
+          condition: SUCCESSFUL
+          execution-type: PARALLEL
+          projects:
+            - name: 'functest-healthcheck-build-push-{stream}'
+              <<: *build-job-settings
+            - name: 'functest-features-build-push-{stream}'
+              <<: *build-job-settings
+            - name: 'functest-components-build-push-{stream}'
+              <<: *build-job-settings
+            - name: 'functest-parser-build-push-{stream}'
+              <<: *build-job-settings
+            - name: 'functest-smoke-build-push-{stream}'
+              <<: *build-job-settings
+            - name: 'functest-vnf-build-push-{stream}'
+              <<: *build-job-settings
+            - name: 'functest-restapi-build-push-{stream}'
+              <<: *build-job-settings
+      - multijob:
+          name: 'create-img-manifest'
+          condition: SUCCESSFUL
+          execution-type: PARALLEL
+          projects:
+            - name: 'functest-healthcheck-create-manifest-{stream}'
+              <<: *manifest-job-settings
+            - name: 'functest-features-create-manifest-{stream}'
+              <<: *manifest-job-settings
+            - name: 'functest-components-create-manifest-{stream}'
+              <<: *manifest-job-settings
+            - name: 'functest-parser-create-manifest-{stream}'
+              <<: *manifest-job-settings
+            - name: 'functest-smoke-create-manifest-{stream}'
+              <<: *manifest-job-settings
+            - name: 'functest-vnf-create-manifest-{stream}'
+              <<: *manifest-job-settings
+            - name: 'functest-restapi-create-manifest-{stream}'
+              <<: *manifest-job-settings
+
+    publishers:
+      - 'functest-{arch_tag}-recipients'
+
+- job-template:
+
+    name: 'functest-{image}-build-push-{arch_tag}-{stream}'
+
+    disabled: '{obj:disabled}'
+
+    parameters:
+      - job-parameters:
+          project: '{project}'
+          branch: '{branch}'
+          slave_label: '{slave_label}'
+          arch_tag: '{arch_tag}'
+      - string:
+          name: DOCKER_REPO_NAME
+          default: "opnfv/functest-{image}"
+          description: "Dockerhub repo to be pushed to."
+      - string:
+          name: DOCKER_DIR
+          default: "docker/{image}"
+          description: "Directory containing files needed by the Dockerfile"
+
+    builders:
+      - shell:
+          !include-raw-escape: ./opnfv-docker.sh
+
+- job-template:
+
+    name: 'functest-{image}-create-manifest-{arch_tag}-{stream}'
+
+    disabled: '{obj:disabled}'
+
+    parameters:
+      - job-parameters:
+          project: '{project}'
+          branch: '{branch}'
+          slave_label: '{slave_label}'
+          arch_tag: '{arch_tag}'
+      - string:
+          name: DOCKER_REPO_NAME
+          default: "opnfv/functest-{image}"
+          description: "Dockerhub repo to be pushed to."
+      - string:
+          name: DOCKER_DIR
+          default: "docker/{image}"
+          description: "Directory containing files needed by the Dockerfile"
+
+    builders:
+      - shell:
+          !include-raw-escape: ./opnfv-manifest.sh
+
+# parameter macro
+- parameter:
+    name: job-parameters
+    parameters:
+      - project-parameter:
+          project: '{project}'
+          branch: '{branch}'
+      - label:
+          name: SLAVE_LABEL
+          default: '{slave_label}'
+          description: 'Slave label on Jenkins'
+      - string:
+          name: GIT_BASE
+          default: https://gerrit.opnfv.org/gerrit/$PROJECT
+          description: 'Git URL to use on this Jenkins Slave'
+      - string:
+          name: PUSH_IMAGE
+          default: "true"
+          description: "To enable/disable pushing the image to Dockerhub."
+      - string:
+          name: COMMIT_ID
+          default: ""
+          description: "commit id to make a snapshot docker image"
+      - string:
+          name: RELEASE_VERSION
+          default: ""
+          description: "Docker tag to be built, e.g. 5.0.0, opnfv-5.0.0, 5.0.RC1"
+      - string:
+          name: DOCKERFILE
+          default: "Dockerfile"
+          description: "Dockerfile to use for creating the image."
+      - string:
+          name: ARCH_TAG
+          default: "{arch_tag}"
+          description: "If set, this value will be added to the docker image tag as a prefix"
+      - string:
+          name: PROJECT
+          default: "{project}"
+          description: "Project name used to enable job conditions"
+
+# publisher macros
+- publisher:
+    name: 'functest-arm64-recipients'
+    publishers:
+      - email:
+          recipients: >
+            cristina.pauna@enea.com
+            alexandru.avadanii@enea.com
+            delia.popescu@enea.com
+
+- publisher:
+    name: 'functest-amd64-recipients'
+    publishers:
+      - email:
+          recipients: >
+            jalausuch@suse.com morgan.richomme@orange.com
+            cedric.ollivier@orange.com feng.xiaowei@zte.com.cn
+            juha.kosonen@nokia.com wangwulin@huawei.com
diff --git a/jjb/releng/opnfv-docs.yml b/jjb/releng/opnfv-docs.yml
deleted file mode 100644 (file)
index 7402745..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
----
-########################
-# Job configuration for opnfv-docs
-########################
-- project:
-
-    name: opnfv-docs
-
-    project: opnfv-docs
-
-    jobs:
-      - 'opnfv-docs-verify-{stream}'
-      - 'opnfv-docs-merge-{stream}'
-
-    stream:
-      - master:
-          branch: '{stream}'
-          doc-version: ''
-          gs-pathname: ''
-          disabled: false
-      - euphrates:
-          branch: 'stable/{stream}'
-          doc-version: '5.0.0'
-          gs-pathname: '/{stream}/{doc-version}'
-          disabled: false
-
-########################
-# job templates
-########################
-
-- job-template:
-    name: 'opnfv-docs-verify-{stream}'
-
-    disabled: '{obj:disabled}'
-
-    parameters:
-      - project-parameter:
-          project: $GERRIT_PROJECT
-          branch: '{branch}'
-
-    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: '*'
-              branches:
-                - branch-compare-type: 'ANT'
-                  branch-pattern: '**/{branch}'
-              file-paths:
-                - compare-type: ANT
-                  pattern: docs/**
-                - compare-type: ANT
-                  pattern: yardstick/**
-
-    builders:
-      - upload-review-docs
-
-- job-template:
-    name: 'opnfv-docs-merge-{stream}'
-
-    disabled: '{obj:disabled}'
-
-    parameters:
-      - project-parameter:
-          project: $GERRIT_PROJECT
-          branch: '{branch}'
-      - string:
-          name: GS_URL
-          default: '$GS_BASE{gs-pathname}'
-          description: "Directory where the build artifact will be located upon the completion of the build."
-      - string:
-          name: GERRIT_REFSPEC
-          default: 'refs/heads/{branch}'
-          description: "JJB configured GERRIT_REFSPEC parameter"
-
-    scm:
-      - git-scm
-
-    triggers:
-      - gerrit:
-          server-name: 'gerrit.opnfv.org'
-          trigger-on:
-            - change-merged-event
-            - comment-added-contains-event:
-                comment-contains-value: 'remerge'
-            - comment-added-contains-event:
-                comment-contains-value: 'rebuild docs'
-          projects:
-            - project-compare-type: 'ANT'
-              project-pattern: '*'
-              branches:
-                - branch-compare-type: 'ANT'
-                  branch-pattern: '**/{branch}'
-              file-paths:
-                - compare-type: ANT
-                  pattern: docs/**
-                - compare-type: ANT
-                  pattern: yardstick/**
-
-    builders:
-      - upload-merged-docs
diff --git a/jjb/releng/opnfv-manifest.sh b/jjb/releng/opnfv-manifest.sh
new file mode 100755 (executable)
index 0000000..a740491
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/bash
+# SPDX-license-identifier: Apache-2.0
+##############################################################################
+# 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 -o errexit
+set -o nounset
+set -o pipefail
+
+# Starting creating manifest image for $DOCKER_REPO_NAME
+
+ARCH=(amd64 arm64)
+DOCKER_REPO_NAME=${DOCKER_REPO_NAME-}
+RELEASE_VERSION=${RELEASE_VERSION-}
+BRANCH=${BRANCH-}
+ARCH_TAG=${ARCH_TAG-}
+
+# Before script install manifest-tool:
+# cd .. && git clone https://github.com/estesp/manifest-tool
+# cd ../manifest-tool && sudo -E make && sudo -E make install
+
+if [[ "$BRANCH" == "master" ]]; then
+        DOCKER_TAG="latest"
+elif [[ "$BRANCH" == "euphrates" ]]; then
+        DOCKER_TAG="euphrates"
+elif [[ -n "${RELEASE_VERSION}" ]]; then
+        DOCKER_TAG="${RELEASE_VERSION}"
+else
+        DOCKER_TAG="stable"
+fi
+if [[ "${ARCH_TAG}" =~ "arm64" || "${ARCH_TAG}" =~ "amd64" ]]; then
+        sudo manifest-tool push from-args --platforms linux/amd64,linux/arm64 \
+           --template "${DOCKER_REPO_NAME}":"${ARCH[0]}"-"${DOCKER_TAG}" \
+           --template "${DOCKER_REPO_NAME}":"${ARCH[1]}"-"${DOCKER_TAG}" \
+           --target "${DOCKER_REPO_NAME}":"${DOCKER_TAG}"
+fi
+
index bab8b24..16ceb2e 100644 (file)
           branch: '{stream}'
           gs-pathname: ''
           disabled: false
-          slave-label: 'opnfv-build-ubuntu'
       - euphrates:
           branch: 'stable/{stream}'
           gs-pathname: '/{stream}'
           disabled: false
-          slave-label: 'opnfv-build-ubuntu'
 
 - job-template:
 
       - project-parameter:
           project: '{project}'
           branch: '{branch}'
-      - '{slave-label}-defaults'
+      - string:
+          name: GIT_BASE
+          default: https://gerrit.opnfv.org/gerrit/$PROJECT
+          description: 'Git URL to use on this Jenkins Slave'
+      - node:
+          name: SLAVE_NAME
+          description: 'Slave name on Jenkins'
+          allowed-slaves:
+            - ericsson-build4
+          default-slaves:
+            - ericsson-build4
 
     scm:
       - git-scm-gerrit
       - project-parameter:
           project: '{project}'
           branch: '{branch}'
-      - '{slave-label}-defaults'
+      - string:
+          name: GIT_BASE
+          default: https://gerrit.opnfv.org/gerrit/$PROJECT
+          description: 'Git URL to use on this Jenkins Slave'
+      - node:
+          name: SLAVE_NAME
+          description: 'Slave name on Jenkins'
+          allowed-slaves:
+            - ericsson-build4
+          default-slaves:
+            - ericsson-build4
 
     scm:
       - git-scm
index 15686a2..481af2a 100644 (file)
           installer: compass
           auto-trigger-name: 'daily-trigger-disabled'
           <<: *euphrates
+      # daisy CI PODs
+      - baremetal:
+          slave-label: zte-pod3
+          installer: daisy
+          auto-trigger-name: 'daily-trigger-disabled'
+          <<: *master
+      - virtual:
+          slave-label: daisy-virtual
+          installer: daisy
+          auto-trigger-name: 'daily-trigger-disabled'
+          <<: *master
       # -------------------------------
       #        None-CI PODs
       # -------------------------------
           <<: *euphrates
       - zte-pod2:
           slave-label: '{pod}'
-          installer: fuel
+          installer: daisy
           auto-trigger-name: 'daily-trigger-disabled'
           <<: *master
       - zte-pod3:
           slave-label: '{pod}'
-          installer: fuel
+          installer: daisy
           auto-trigger-name: 'daily-trigger-disabled'
           <<: *master
-      - zte-pod3:
-          slave-label: '{pod}'
-          installer: fuel
-          auto-trigger-name: 'daily-trigger-disabled'
-          <<: *euphrates
       - orange-pod2:
           slave-label: '{pod}'
           installer: joid
           default: '-i 104.197.68.199:8086'
           description: 'Arguments to use in order to choose the backend DB'
 
+- parameter:
+    name: 'yardstick-params-daisy-baremetal'
+    parameters:
+      - string:
+          name: YARDSTICK_DB_BACKEND
+          default: '-i 104.197.68.199:8086'
+          description: 'Arguments to use in order to choose the backend DB'
+
+- parameter:
+    name: 'yardstick-params-daisy-virtual'
+    parameters:
+      - string:
+          name: YARDSTICK_DB_BACKEND
+          default: '-i 104.197.68.199:8086'
+          description: 'Arguments to use in order to choose the backend DB'
+
 - parameter:
     name: 'yardstick-params-zte-pod1'
     parameters:
index eb070e3..2107bdc 100644 (file)
@@ -70,7 +70,7 @@ class OVSLogger(object):
     def ofctl_dump_flows(self, ssh_conn, br='br-int',
                          choose_table=None, timestamp=None):
         try:
-            cmd = 'ovs-ofctl -OOpenFlow13 dump-flows {0}'.format(br)
+            cmd = 'sudo ovs-ofctl -OOpenFlow13 dump-flows {0}'.format(br)
             if choose_table is not None:
                 cmd = '{0} table={1}'.format(cmd, choose_table)
             output = self.__remote_cmd(ssh_conn, cmd)
@@ -85,7 +85,7 @@ class OVSLogger(object):
 
     def vsctl_show(self, ssh_conn, timestamp=None):
         try:
-            cmd = 'ovs-vsctl show'
+            cmd = 'sudo ovs-vsctl show'
             output = self.__remote_cmd(ssh_conn, cmd)
             operation = 'vsctl_show'
             host = self.__ssh_host(ssh_conn)
index 2793dd4..0718fa3 100644 (file)
@@ -1,3 +1,3 @@
 paramiko>=2.0 # LGPLv2.1+
 mock>=2.0 # BSD
-requests!=2.12.2,>=2.10.0 # Apache-2.0
+requests>=2.14.2 # Apache-2.0
index a1e9b3b..46309ef 100644 (file)
@@ -18,5 +18,5 @@ except ImportError:
     pass
 
 setuptools.setup(
-    setup_requires=['pbr>=1.8'],
+    setup_requires=['pbr>=2.0.0'],
     pbr=True)
index c264540..1ae13c0 100644 (file)
@@ -1,2 +1,2 @@
 nose # LGPL
-coverage>=4.0 # Apache-2.0
+coverage!=4.4,>=4.0 # Apache-2.0
index a3d6e01..e34365e 100644 (file)
@@ -6,3 +6,10 @@ build
 *.egg-info
 3rd_party/static/static
 *.pyc
+.cache
+.eggs
+.tox
+.ven
+docs/_build
+opnfv_testapi/tests/UI/coverage
+3rd_party/static/testapi-ui/testapi-ui
\ No newline at end of file
diff --git a/utils/test/testapi/3rd_party/static/testapi-ui/Gruntfile.js b/utils/test/testapi/3rd_party/static/testapi-ui/Gruntfile.js
new file mode 100644 (file)
index 0000000..8ff2802
--- /dev/null
@@ -0,0 +1,155 @@
+
+module.exports = function (grunt) {
+       require('load-grunt-tasks')(grunt);
+       require('grunt-protractor-coverage')(grunt);
+       grunt.loadNpmTasks('grunt-shell-spawn');
+       grunt.loadNpmTasks('grunt-wait');
+       grunt.loadNpmTasks('grunt-contrib-copy');
+       grunt.loadNpmTasks('grunt-contrib-connect');
+       grunt.initConfig({
+               connect: {
+                       server: {
+                               options: {
+                                       port: 8000,
+                                       base: './',
+                                       middleware: function(connect, options, middlewares) {
+                                               middlewares.unshift(function(req, res, next) {
+                                                       if (req.method.toUpperCase() == 'POST') req.method='GET';
+                                                       return next();
+                                               });
+                                               return middlewares;
+                                       }
+                               }
+                       }
+               },
+               copy: {
+                       assets: {
+                         expand: true,
+                         cwd: 'assets',
+                         src: '**',
+                         dest: 'testapi-ui/assets',
+                       },
+                       components: {
+                               expand: true,
+                               cwd: 'components',
+                               src: '**',
+                               dest: 'testapi-ui/components',
+                       },
+                       shared: {
+                               expand: true,
+                               cwd: 'shared',
+                               src: '**',
+                               dest: 'testapi-ui/shared',
+                       },
+                       filesPng: {
+                               expand: true,
+                               src: '*.png',
+                               dest: 'testapi-ui/',
+                       },
+                       filesIco: {
+                               expand: true,
+                               src: '*.ico',
+                               dest: 'testapi-ui/',
+                       },
+                       filesJs: {
+                               expand: true,
+                               src: 'app.js',
+                               dest: 'testapi-ui/',
+                       },
+                       filesJson: {
+                               expand: true,
+                               src: 'config.json',
+                               dest: 'testapi-ui/',
+                       }
+               },
+               wait: {
+                       default: {
+                               options: {
+                                       delay: 3000
+                               }
+                       }
+               },
+               shell: {
+                       updateSelenium: {
+                               command: 'node_modules/protractor/bin/webdriver-manager update',
+                               options: {
+                               async: false
+                       }
+                       },
+                       startSelenium: {
+                               command: 'node_modules/protractor/bin/webdriver-manager start',
+                               options: {
+                             async: true
+                           }
+                       },
+                       options: {
+                       stdout: false,
+                       stderr: false
+                   }
+               },
+               instrument: {
+               files: ['components/**/*.js'],
+               options: {
+               lazy: false,
+                   basePath: "./testapi-ui/"
+               }
+           },
+               karma: {
+                       unit: {
+                               configFile: '../../../opnfv_testapi/tests/UI/karma.conf.js'
+                       }
+               },
+               protractor_coverage: {
+                   options: {
+                       keepAlive: true,
+                       noColor: false,
+                       coverageDir: '../../../opnfv_testapi/tests/UI/coverage',
+                       args: {
+                           specs: ['../../../opnfv_testapi/tests/UI/e2e/podsControllerSpec.js']
+                       }
+                   },
+                   local: {
+                       options: {
+                           configFile: '../../../opnfv_testapi/tests/UI/protractor-conf.js'
+                       }
+                   }
+               },
+               makeReport: {
+               src: '../../../opnfv_testapi/tests/UI/coverage/*.json',
+               options: {
+                   print: 'detail'
+               }
+           },
+               protractor: {
+                       e2e: {
+                               options: {
+                                       args: {
+                                               specs: ['../../../opnfv_testapi/tests/UI/e2e/podsControllerSpec.js']
+                                       },
+                                       configFile: '../../../opnfv_testapi/tests/UI/protractor-conf.js',
+                                       keepAlive: true
+                               }
+                       }
+               }
+       });
+       grunt.registerTask('test', [
+               'karma:unit'
+       ]);
+       grunt.registerTask('e2e', [
+               'copy:assets',
+               'copy:components',
+               'copy:shared',
+               'copy:filesPng',
+               'copy:filesIco',
+               'copy:filesJs',
+               'copy:filesJson',
+               'instrument',
+               'connect',
+               'shell:updateSelenium',
+               'shell:startSelenium',
+               'wait:default',
+               'protractor_coverage',
+               'makeReport'
+               // 'protractor'
+       ]);
+}
diff --git a/utils/test/testapi/3rd_party/static/testapi-ui/package.json b/utils/test/testapi/3rd_party/static/testapi-ui/package.json
new file mode 100644 (file)
index 0000000..dc99239
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "devDependencies": {
+    "grunt": "~1.0.1",
+    "grunt-contrib-connect": "^1.0.2",
+    "grunt-contrib-copy": "^1.0.0",
+    "grunt-karma": "~2.0.0",
+    "grunt-protractor-coverage": "^0.2.18",
+    "grunt-protractor-runner": "~5.0.0",
+    "grunt-shell-spawn": "~0.3.10",
+    "grunt-wait": "~0.1.0",
+    "karma": "~1.7.1",
+    "karma-chrome-launcher": "~2.2.0",
+    "karma-coverage": "~1.1.1",
+    "karma-jasmine": "~1.1.0",
+    "load-grunt-tasks": "~3.5.2",
+    "protractor-http-mock": "^0.10.0"
+  }
+}
diff --git a/utils/test/testapi/docs/Makefile b/utils/test/testapi/docs/Makefile
new file mode 100644 (file)
index 0000000..11e9eb6
--- /dev/null
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+SPHINXPROJ    = OPNFVTestAPI
+SOURCEDIR     = .
+BUILDDIR      = _build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+       @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+       @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
\ No newline at end of file
diff --git a/utils/test/testapi/docs/conf.py b/utils/test/testapi/docs/conf.py
new file mode 100644 (file)
index 0000000..eaf1501
--- /dev/null
@@ -0,0 +1,165 @@
+# -*- coding: utf-8 -*-
+#
+# OPNFV TestAPI documentation build configuration file, created by
+# sphinx-quickstart on Thu Oct 26 10:23:57 2017.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = []
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'OPNFV TestAPI'
+copyright = u'2017, SerenaFeng'
+author = u'SerenaFeng'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = u'v1.0'
+# The full version, including alpha/beta/rc tags.
+release = u'v1.0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'alabaster'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#
+# html_theme_options = {}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+# html_static_path = ['_static']
+
+# Custom sidebar templates, must be a dictionary that maps document names
+# to template names.
+#
+# This is required for the alabaster theme
+# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
+html_sidebars = {
+    '**': [
+        'relations.html',  # needs 'show_related': True theme option to display
+        'searchbox.html',
+    ]
+}
+
+
+# -- Options for HTMLHelp output ------------------------------------------
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'OPNFVTestAPIdoc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+    # The paper size ('letterpaper' or 'a4paper').
+    #
+    # 'papersize': 'letterpaper',
+
+    # The font size ('10pt', '11pt' or '12pt').
+    #
+    # 'pointsize': '10pt',
+
+    # Additional stuff for the LaTeX preamble.
+    #
+    # 'preamble': '',
+
+    # Latex figure (float) alignment
+    #
+    # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+latex_documents = [
+    (master_doc, 'OPNFVTestAPI.tex', u'OPNFV TestAPI Documentation',
+     u'SerenaFeng', 'manual'),
+]
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    (master_doc, 'opnfvtestapi', u'OPNFV TestAPI Documentation',
+     [author], 1)
+]
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+    (master_doc, 'OPNFVTestAPI', u'OPNFV TestAPI Documentation',
+     author, 'OPNFVTestAPI', 'One line description of project.',
+     'Miscellaneous'),
+]
diff --git a/utils/test/testapi/docs/developer/devguide/api.rst b/utils/test/testapi/docs/developer/devguide/api.rst
new file mode 100644 (file)
index 0000000..cd2ca27
--- /dev/null
@@ -0,0 +1,10 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) 2017 ZTE Corp.
+
+============
+Restful APIs
+============
+
+.. toctree::
+   :maxdepth: 2
similarity index 92%
rename from utils/test/testapi/README.rst
rename to utils/test/testapi/docs/developer/devguide/framework.rst
index 0d18b7e..f7a7605 100644 (file)
@@ -1,6 +1,14 @@
-=============
-opnfv-testapi
-=============
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) 2017 ZTE Corp.
+
+
+.. toctree::
+   :maxdepth: 2
+
+=========
+Framework
+=========
 
 **Test Results Collector of OPNFV Test Projects**:
 
diff --git a/utils/test/testapi/docs/developer/devguide/index.rst b/utils/test/testapi/docs/developer/devguide/index.rst
new file mode 100644 (file)
index 0000000..7afcd96
--- /dev/null
@@ -0,0 +1,18 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) 2017 ZTE Corp.
+
+
+***********************
+TestAPI Developer Guide
+***********************
+
+.. toctree::
+   :maxdepth: 2
+
+   overview.rst
+   framework.rst
+   api.rst
+   swagger-ui.rst
+   web-portal.rst
+   testapi-client.rst
diff --git a/utils/test/testapi/docs/developer/devguide/overview.rst b/utils/test/testapi/docs/developer/devguide/overview.rst
new file mode 100644 (file)
index 0000000..b6475f3
--- /dev/null
@@ -0,0 +1,98 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) 2017 ZTE Corporation
+
+
+********
+Overview
+********
+
+TestAPI uses Python as primary programming language and build the framework from the following packages
+
+======== ===============================================================================================================
+Module   Package
+======== ===============================================================================================================
+api      `Tornado-Motor`_ - API applications using Motor with tornado
+swagger  `tornado-swagger`_ - a wrapper for tornado which enables swagger-ui-v1.2 support
+web      `angular`_ - a superheroic JavaScript MVW framework, the version is AngularJS v1.3.15
+docs     `sphinx`_ - a tool that makes it easy to create intelligent and beautiful documentation
+testing  `pytest`_ - a mature full-featured Python testing tool that helps you write better programs
+======== ===============================================================================================================
+
+
+Source Code
+===========
+
+The structure of repository is based on the recommended sample in `The Hitchhiker's Guide to Python`_
+
+==========================  ====================================================================================================
+Path                        Content
+==========================  ====================================================================================================
+``./3rd_party/``            third part included in TestAPI project
+``./docker/``               configuration for building Docker image for TestAPI deployment
+``./docs/``                 user and developer documentation, design proposals
+``./etc/``                  configuration files used to install opnfv-testapi
+``./opnfv_testapi/``        the actual package
+``./opnfv_testapi/tests/``  package functional and unit tests
+``./opts/``                 optional components, e.g. one click deployment script
+==========================  ====================================================================================================
+
+
+Coding Style
+============
+
+TestAPI follows `OpenStack Style Guidelines`_ for source code and commit message.
+
+Specially, it is recommended to link each patch set with a JIRA issue. Put::
+
+    JIRA: RELENG-n
+
+in commit message to create an automatic link.
+
+
+Testing
+=======
+
+All testing related code are stored in ``./opnfv_testapi/tests/``
+
+==================  ====================================================================================================
+Path                Content
+==================  ====================================================================================================
+``./tests/unit/``   unit test for each module, follow the same layout as ./opnfv_testapi/
+``./conftest.py``   pytest configuration in project scope
+==================  ====================================================================================================
+
+`tox`_ is used to automate the testing tasks
+
+.. code-block:: shell
+
+    cd <project_root>
+    pip install tox
+    tox
+
+The test cases are written in `pytest`_. You may run it selectively with
+
+.. code-block:: shell
+
+    pytest opnfv_testapi/tests/unit/common/test_config.py
+
+
+Branching
+=========
+
+Currently, no branching for TestAPI, only master branch
+
+
+Releasing
+=========
+
+Currently, TestAPI does not follow community's milestones and releases
+
+.. _Tornado-Motor: https://motor.readthedocs.io/en/stable/tutorial-tornado.html
+.. _tornado-swagger: https://github.com/SerenaFeng/tornado-swagger
+.. _angular: https://code.angularjs.org/1.3.15/docs/guide
+.. _sphinx: http://www.sphinx-doc.org/en/stable/
+.. _pytest: http://doc.pytest.org/
+.. _OpenStack Style Guidelines: http://docs.openstack.org/developer/hacking/
+.. _The Hitchhiker's Guide to Python: http://python-guide-pt-br.readthedocs.io/en/latest/writing/structure/
+.. _tox: https://tox.readthedocs.io/
diff --git a/utils/test/testapi/docs/developer/devguide/swagger-ui.rst b/utils/test/testapi/docs/developer/devguide/swagger-ui.rst
new file mode 100644 (file)
index 0000000..7f53047
--- /dev/null
@@ -0,0 +1,10 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) 2017 ZTE Corp.
+
+============
+Swagger page
+============
+
+.. toctree::
+   :maxdepth: 2
diff --git a/utils/test/testapi/docs/developer/devguide/testapi-client.rst b/utils/test/testapi/docs/developer/devguide/testapi-client.rst
new file mode 100644 (file)
index 0000000..ab4c8e8
--- /dev/null
@@ -0,0 +1,10 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) 2017 ZTE Corp.
+
+==============
+TestAPI client
+==============
+
+.. toctree::
+   :maxdepth: 2
diff --git a/utils/test/testapi/docs/developer/devguide/web-portal.rst b/utils/test/testapi/docs/developer/devguide/web-portal.rst
new file mode 100644 (file)
index 0000000..62b2f17
--- /dev/null
@@ -0,0 +1,10 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) 2017 ZTE Corp.
+
+==========
+Web portal
+==========
+
+.. toctree::
+   :maxdepth: 2
diff --git a/utils/test/testapi/docs/index.rst b/utils/test/testapi/docs/index.rst
new file mode 100644 (file)
index 0000000..017282a
--- /dev/null
@@ -0,0 +1,20 @@
+.. OPNFV TestAPI documentation master file, created by
+   sphinx-quickstart on Thu Oct 26 10:23:57 2017.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+Welcome to OPNFV TestAPI's documentation!
+=========================================
+
+.. toctree::
+   :maxdepth: 2
+   :caption: Contents:
+
+
+Developer Guide
+===============
+
+.. toctree::
+   :maxdepth: 2
+
+   developer/devguide/index.rst
index 140e492..f888b07 100644 (file)
@@ -44,7 +44,7 @@ class Config(object):
     def _parse_value(value):
         try:
             value = int(value)
-        except:
+        except Exception:
             if str(value).lower() == 'true':
                 value = True
             elif str(value).lower() == 'false':
@@ -20,8 +20,8 @@
 # feng.xiaowei@zte.com.cn remove DashboardHandler            5-30-2016
 ##############################################################################
 
-import json
 from datetime import datetime
+import json
 
 from tornado import gen
 from tornado import web
@@ -30,7 +30,7 @@ from opnfv_testapi.common import check
 from opnfv_testapi.common import message
 from opnfv_testapi.common import raises
 from opnfv_testapi.db import api as dbapi
-from opnfv_testapi.resources import models
+from opnfv_testapi.models import base_models
 from opnfv_testapi.tornado_swagger import swagger
 
 DEFAULT_REPRESENTATION = "application/json"
@@ -67,7 +67,7 @@ class GenericApiHandler(web.RequestHandler):
 
     def _create_response(self, resource):
         href = self.request.full_url() + '/' + str(resource)
-        return models.CreateResponse(href=href).format()
+        return base_models.CreateResponse(href=href).format()
 
     def format_data(self, data):
         cls_data = self.table_cls.from_dict(data)
@@ -6,12 +6,12 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
-import handlers
-from opnfv_testapi.resources import pod_models
+from opnfv_testapi.handlers import base_handlers
+from opnfv_testapi.models import pod_models
 from opnfv_testapi.tornado_swagger import swagger
 
 
-class GenericPodHandler(handlers.GenericApiHandler):
+class GenericPodHandler(base_handlers.GenericApiHandler):
     def __init__(self, application, request, **kwargs):
         super(GenericPodHandler, self).__init__(application, request, **kwargs)
         self.table = 'pods'
@@ -7,12 +7,12 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-from opnfv_testapi.resources import handlers
-from opnfv_testapi.resources import project_models
+from opnfv_testapi.handlers import base_handlers
+from opnfv_testapi.models import project_models
 from opnfv_testapi.tornado_swagger import swagger
 
 
-class GenericProjectHandler(handlers.GenericApiHandler):
+class GenericProjectHandler(base_handlers.GenericApiHandler):
     def __init__(self, application, request, **kwargs):
         super(GenericProjectHandler, self).__init__(application,
                                                     request,
@@ -6,23 +6,23 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
+from datetime import datetime
+from datetime import timedelta
 import json
 import logging
 
 from bson import objectid
-from datetime import datetime
-from datetime import timedelta
 
 from opnfv_testapi.common import constants
 from opnfv_testapi.common import message
 from opnfv_testapi.common import raises
 from opnfv_testapi.common.config import CONF
-from opnfv_testapi.resources import handlers
-from opnfv_testapi.resources import result_models
+from opnfv_testapi.handlers import base_handlers
+from opnfv_testapi.models import result_models
 from opnfv_testapi.tornado_swagger import swagger
 
 
-class GenericResultHandler(handlers.GenericApiHandler):
+class GenericResultHandler(base_handlers.GenericApiHandler):
     def __init__(self, application, request, **kwargs):
         super(GenericResultHandler, self).__init__(application,
                                                    request,
@@ -33,7 +33,7 @@ class GenericResultHandler(handlers.GenericApiHandler):
     def get_int(self, key, value):
         try:
             value = int(value)
-        except:
+        except Exception:
             raises.BadRequest(message.must_int(key))
         return value
 
@@ -1,8 +1,8 @@
 from opnfv_testapi.common.config import CONF
-from opnfv_testapi.resources import handlers
+from opnfv_testapi.handlers import base_handlers
 
 
-class RootHandler(handlers.GenericApiHandler):
+class RootHandler(base_handlers.GenericApiHandler):
     def get_template_path(self):
         return CONF.ui_static_path
 
@@ -2,12 +2,12 @@ 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.handlers import base_handlers
+import opnfv_testapi.models.scenario_models as models
 from opnfv_testapi.tornado_swagger import swagger
 
 
-class GenericScenarioHandler(handlers.GenericApiHandler):
+class GenericScenarioHandler(base_handlers.GenericApiHandler):
     def __init__(self, application, request, **kwargs):
         super(GenericScenarioHandler, self).__init__(application,
                                                      request,
@@ -5,10 +5,10 @@ from tornado import web
 from opnfv_testapi.common import constants
 from opnfv_testapi.common.config import CONF
 from opnfv_testapi.db import api as dbapi
-from opnfv_testapi.resources import handlers
+from opnfv_testapi.handlers import base_handlers
 
 
-class SignBaseHandler(handlers.GenericApiHandler):
+class SignBaseHandler(base_handlers.GenericApiHandler):
     def __init__(self, application, request, **kwargs):
         super(SignBaseHandler, self).__init__(application, request, **kwargs)
         self.table = 'users'
@@ -7,12 +7,12 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-from opnfv_testapi.resources import handlers
-from opnfv_testapi.resources import testcase_models
+from opnfv_testapi.handlers import base_handlers
+from opnfv_testapi.models import testcase_models
 from opnfv_testapi.tornado_swagger import swagger
 
 
-class GenericTestcaseHandler(handlers.GenericApiHandler):
+class GenericTestcaseHandler(base_handlers.GenericApiHandler):
     def __init__(self, application, request, **kwargs):
         super(GenericTestcaseHandler, self).__init__(application,
                                                      request,
@@ -1,19 +1,11 @@
 from opnfv_testapi.common import constants
 from opnfv_testapi.common import raises
 from opnfv_testapi.common.config import CONF
-from opnfv_testapi.resources import handlers
-from opnfv_testapi.resources import models
+from opnfv_testapi.handlers import base_handlers
+from opnfv_testapi.models.user_models import User
 
 
-class User(models.ModelBase):
-    def __init__(self, user=None, email=None, fullname=None, groups=None):
-        self.user = user
-        self.email = email
-        self.fullname = fullname
-        self.groups = groups
-
-
-class UserHandler(handlers.GenericApiHandler):
+class UserHandler(base_handlers.GenericApiHandler):
     def __init__(self, application, request, **kwargs):
         super(UserHandler, self).__init__(application, request, **kwargs)
         self.table = 'users'
@@ -91,10 +91,10 @@ class ModelBase(object):
         elif isinstance(obj, unicode):
             try:
                 obj = self._obj_format(ast.literal_eval(obj))
-            except:
+            except Exception:
                 try:
                     obj = str(obj)
-                except:
+                except Exception:
                     obj = obj
         elif isinstance(obj, list):
             hs = list()
@@ -6,7 +6,7 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
-from opnfv_testapi.resources import models
+from opnfv_testapi.models import base_models
 from opnfv_testapi.tornado_swagger import swagger
 
 
@@ -17,7 +17,7 @@ from opnfv_testapi.tornado_swagger import swagger
 
 
 @swagger.model()
-class PodCreateRequest(models.ModelBase):
+class PodCreateRequest(base_models.ModelBase):
     def __init__(self, name, mode='', details='', role=""):
         self.name = name
         self.mode = mode
@@ -26,7 +26,7 @@ class PodCreateRequest(models.ModelBase):
 
 
 @swagger.model()
-class Pod(models.ModelBase):
+class Pod(base_models.ModelBase):
     def __init__(self,
                  name='', mode='', details='',
                  role="", _id='', create_date='', owner=''):
@@ -40,7 +40,7 @@ class Pod(models.ModelBase):
 
 
 @swagger.model()
-class Pods(models.ModelBase):
+class Pods(base_models.ModelBase):
     """
         @property pods:
         @ptype pods: C{list} of L{Pod}
@@ -6,26 +6,26 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
-from opnfv_testapi.resources import models
+from opnfv_testapi.models import base_models
 from opnfv_testapi.tornado_swagger import swagger
 
 
 @swagger.model()
-class ProjectCreateRequest(models.ModelBase):
+class ProjectCreateRequest(base_models.ModelBase):
     def __init__(self, name, description=''):
         self.name = name
         self.description = description
 
 
 @swagger.model()
-class ProjectUpdateRequest(models.ModelBase):
+class ProjectUpdateRequest(base_models.ModelBase):
     def __init__(self, name='', description=''):
         self.name = name
         self.description = description
 
 
 @swagger.model()
-class Project(models.ModelBase):
+class Project(base_models.ModelBase):
     def __init__(self,
                  name=None, _id=None, description=None, create_date=None):
         self._id = _id
@@ -35,7 +35,7 @@ class Project(models.ModelBase):
 
 
 @swagger.model()
-class Projects(models.ModelBase):
+class Projects(base_models.ModelBase):
     """
         @property projects:
         @ptype projects: C{list} of L{Project}
@@ -6,12 +6,12 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
-from opnfv_testapi.resources import models
+from opnfv_testapi.models import base_models
 from opnfv_testapi.tornado_swagger import swagger
 
 
 @swagger.model()
-class TIHistory(models.ModelBase):
+class TIHistory(base_models.ModelBase):
     """
         @ptype step: L{float}
     """
@@ -21,7 +21,7 @@ class TIHistory(models.ModelBase):
 
 
 @swagger.model()
-class TI(models.ModelBase):
+class TI(base_models.ModelBase):
     """
         @property histories: trust_indicator update histories
         @ptype histories: C{list} of L{TIHistory}
@@ -37,7 +37,7 @@ class TI(models.ModelBase):
 
 
 @swagger.model()
-class ResultCreateRequest(models.ModelBase):
+class ResultCreateRequest(base_models.ModelBase):
     """
         @property trust_indicator:
         @ptype trust_indicator: L{TI}
@@ -74,7 +74,7 @@ class ResultCreateRequest(models.ModelBase):
 
 
 @swagger.model()
-class ResultUpdateRequest(models.ModelBase):
+class ResultUpdateRequest(base_models.ModelBase):
     """
         @property trust_indicator:
         @ptype trust_indicator: L{TI}
@@ -84,7 +84,7 @@ class ResultUpdateRequest(models.ModelBase):
 
 
 @swagger.model()
-class TestResult(models.ModelBase):
+class TestResult(base_models.ModelBase):
     """
         @property trust_indicator: used for long duration test case
         @ptype trust_indicator: L{TI}
@@ -116,7 +116,7 @@ class TestResult(models.ModelBase):
 
 
 @swagger.model()
-class TestResults(models.ModelBase):
+class TestResults(base_models.ModelBase):
     """
         @property results:
         @ptype results: C{list} of L{TestResult}
@@ -1,4 +1,4 @@
-from opnfv_testapi.resources import models
+from opnfv_testapi.models import base_models
 from opnfv_testapi.tornado_swagger import swagger
 
 
@@ -11,7 +11,7 @@ def dict_default(value):
 
 
 @swagger.model()
-class ScenarioTI(models.ModelBase):
+class ScenarioTI(base_models.ModelBase):
     def __init__(self, date=None, status='silver'):
         self.date = date
         self.status = status
@@ -25,7 +25,7 @@ class ScenarioTI(models.ModelBase):
 
 
 @swagger.model()
-class ScenarioScore(models.ModelBase):
+class ScenarioScore(base_models.ModelBase):
     def __init__(self, date=None, score='0'):
         self.date = date
         self.score = score
@@ -39,7 +39,7 @@ class ScenarioScore(models.ModelBase):
 
 
 @swagger.model()
-class ScenarioProject(models.ModelBase):
+class ScenarioProject(base_models.ModelBase):
     """
         @property customs:
         @ptype customs: C{list} of L{string}
@@ -83,7 +83,7 @@ class ScenarioProject(models.ModelBase):
 
 
 @swagger.model()
-class ScenarioVersion(models.ModelBase):
+class ScenarioVersion(base_models.ModelBase):
     """
         @property projects:
         @ptype projects: C{list} of L{ScenarioProject}
@@ -116,7 +116,7 @@ class ScenarioVersion(models.ModelBase):
 
 
 @swagger.model()
-class ScenarioInstaller(models.ModelBase):
+class ScenarioInstaller(base_models.ModelBase):
     """
         @property versions:
         @ptype versions: C{list} of L{ScenarioVersion}
@@ -146,7 +146,7 @@ class ScenarioInstaller(models.ModelBase):
 
 
 @swagger.model()
-class ScenarioCreateRequest(models.ModelBase):
+class ScenarioCreateRequest(base_models.ModelBase):
     """
         @property installers:
         @ptype installers: C{list} of L{ScenarioInstaller}
@@ -161,19 +161,19 @@ class ScenarioCreateRequest(models.ModelBase):
 
 
 @swagger.model()
-class ScenarioChangeOwnerRequest(models.ModelBase):
+class ScenarioChangeOwnerRequest(base_models.ModelBase):
     def __init__(self, owner=None):
         self.owner = owner
 
 
 @swagger.model()
-class ScenarioUpdateRequest(models.ModelBase):
+class ScenarioUpdateRequest(base_models.ModelBase):
     def __init__(self, name=None):
         self.name = name
 
 
 @swagger.model()
-class Scenario(models.ModelBase):
+class Scenario(base_models.ModelBase):
     """
         @property installers:
         @ptype installers: C{list} of L{ScenarioInstaller}
@@ -205,7 +205,7 @@ class Scenario(models.ModelBase):
 
 
 @swagger.model()
-class Scenarios(models.ModelBase):
+class Scenarios(base_models.ModelBase):
     """
         @property scenarios:
         @ptype scenarios: C{list} of L{Scenario}
@@ -6,12 +6,12 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
-from opnfv_testapi.resources import models
+from opnfv_testapi.models import base_models
 from opnfv_testapi.tornado_swagger import swagger
 
 
 @swagger.model()
-class TestcaseCreateRequest(models.ModelBase):
+class TestcaseCreateRequest(base_models.ModelBase):
     def __init__(self, name, url=None, description=None,
                  catalog_description=None, tier=None, ci_loop=None,
                  criteria=None, blocking=None, dependencies=None, run=None,
@@ -33,7 +33,7 @@ class TestcaseCreateRequest(models.ModelBase):
 
 
 @swagger.model()
-class TestcaseUpdateRequest(models.ModelBase):
+class TestcaseUpdateRequest(base_models.ModelBase):
     def __init__(self, name=None, description=None, project_name=None,
                  catalog_description=None, tier=None, ci_loop=None,
                  criteria=None, blocking=None, dependencies=None, run=None,
@@ -55,7 +55,7 @@ class TestcaseUpdateRequest(models.ModelBase):
 
 
 @swagger.model()
-class Testcase(models.ModelBase):
+class Testcase(base_models.ModelBase):
     def __init__(self, _id=None, name=None, project_name=None,
                  description=None, url=None, creation_date=None,
                  catalog_description=None, tier=None, ci_loop=None,
@@ -82,7 +82,7 @@ class Testcase(models.ModelBase):
 
 
 @swagger.model()
-class Testcases(models.ModelBase):
+class Testcases(base_models.ModelBase):
     """
         @property testcases:
         @ptype testcases: C{list} of L{Testcase}
diff --git a/utils/test/testapi/opnfv_testapi/models/user_models.py b/utils/test/testapi/opnfv_testapi/models/user_models.py
new file mode 100644 (file)
index 0000000..90fbadc
--- /dev/null
@@ -0,0 +1,9 @@
+from opnfv_testapi.models import base_models
+
+
+class User(base_models.ModelBase):
+    def __init__(self, user=None, email=None, fullname=None, groups=None):
+        self.user = user
+        self.email = email
+        self.fullname = fullname
+        self.groups = groups
index ce0a3ee..349d557 100644 (file)
@@ -9,19 +9,19 @@
 import tornado.web
 
 from opnfv_testapi.common.config import CONF
-from opnfv_testapi.resources import handlers
-from opnfv_testapi.resources import pod_handlers
-from opnfv_testapi.resources import project_handlers
-from opnfv_testapi.resources import result_handlers
-from opnfv_testapi.resources import scenario_handlers
-from opnfv_testapi.resources import testcase_handlers
-from opnfv_testapi.ui import root
-from opnfv_testapi.ui.auth import sign
-from opnfv_testapi.ui.auth import user
+from opnfv_testapi.handlers import base_handlers
+from opnfv_testapi.handlers import pod_handlers
+from opnfv_testapi.handlers import project_handlers
+from opnfv_testapi.handlers import result_handlers
+from opnfv_testapi.handlers import root_handlers
+from opnfv_testapi.handlers import scenario_handlers
+from opnfv_testapi.handlers import sign_handlers
+from opnfv_testapi.handlers import testcase_handlers
+from opnfv_testapi.handlers import user_handlers
 
 mappings = [
     # GET /versions => GET API version
-    (r"/versions", handlers.VersionHandler),
+    (r"/versions", base_handlers.VersionHandler),
 
     # few examples:
     # GET /api/v1/pods => Get all pods
@@ -74,10 +74,11 @@ mappings = [
      tornado.web.StaticFileHandler,
      {'path': CONF.ui_static_path}),
 
-    (r'/', root.RootHandler),
-    (r'/api/v1/auth/signin', sign.SigninHandler),
-    (r'/{}'.format(CONF.lfid_signin_return), sign.SigninReturnHandler),
-    (r'/api/v1/auth/signout', sign.SignoutHandler),
-    (r'/api/v1/profile', user.UserHandler),
+    (r'/', root_handlers.RootHandler),
+    (r'/api/v1/auth/signin', sign_handlers.SigninHandler),
+    (r'/{}'.format(CONF.lfid_signin_return),
+     sign_handlers.SigninReturnHandler),
+    (r'/api/v1/auth/signout', sign_handlers.SignoutHandler),
+    (r'/api/v1/profile', user_handlers.UserHandler),
 
 ]
diff --git a/utils/test/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js b/utils/test/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js
new file mode 100644 (file)
index 0000000..66a57f2
--- /dev/null
@@ -0,0 +1,188 @@
+'use strict';
+
+var mock = require('protractor-http-mock');
+var baseURL = "http://localhost:8000"
+describe('testing the Pods page for anonymous user', function () {
+
+       beforeEach(function(){
+               mock([{
+                       request: {
+                         path: '/api/v1/pods',
+                         method: 'GET'
+                       },
+                       response: {
+                               data: {
+                                       pods: [{role: "community-ci", name: "test", owner: "testUser", details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed", creation_date: "2017-10-25 11:58:25.926168"}]
+                               }
+                       }
+                 }]);
+       });
+
+       it( 'should navigate to pods link ', function() {
+               browser.get(baseURL);
+               var podslink = element(by.linkText('Pods')).click();
+               var EC = browser.ExpectedConditions;
+               browser.wait(EC.urlContains(baseURL+ '/#/pods'), 10000);
+       });
+
+       it('create button is not visible for anonymous user', function () {
+               browser.get(baseURL+'#/pods');
+               var buttonCreate = element(by.buttonText('Create'));
+               expect(buttonCreate.isDisplayed()).toBeFalsy();
+       });
+
+       it('filter button is visible for anonymous user', function () {
+               var buttonFilter = element(by.buttonText('Filter'));
+               expect(buttonFilter.isDisplayed()).toBe(true)
+       });
+
+       it('clear button is visible for anonymous user', function () {
+               var buttonClear = element(by.buttonText('Clear'));
+               expect(buttonClear.isDisplayed()).toBe(true)
+       });
+
+       it('Show results when click filter button', function () {
+               var buttonFilter = element(by.buttonText('Filter'));
+               buttonFilter.click();
+               var pod = element(by.css('.show-pod'));
+               expect(pod.isPresent()).toBe(true);
+       });
+
+       it('Show results when click clear button', function () {
+               browser.get(baseURL+'#/pods');
+               var buttonClear = element(by.buttonText('Clear'));
+               buttonClear.click();
+               var pod = element(by.css('.show-pod'));
+               expect(pod.isPresent()).toBe(true);
+       });
+
+       it('If details is not shown then show details when click the link',function() {
+               expect(element(by.css('.show-pod.hidden')).isPresent()).toBe(true);
+               var podslink = element(by.linkText('test')).click();
+               expect(element(by.css('.show-pod.hidden')).isPresent()).toBe(false);
+       });
+
+       it('If details is shown then hide details when click the link',function() {
+               expect(element(by.css('.show-pod.hidden')).isPresent()).toBe(false);
+               var podslink = element(by.linkText('test')).click();
+               expect(element(by.css('.show-pod.hidden')).isPresent()).toBe(true);
+       });
+
+       it('If backend is not responding then show error when click filter button', function () {
+               browser.get(baseURL + '/#/pods');
+               mock.teardown();
+               var buttonFilter = element(by.buttonText('Filter'));
+               buttonFilter.click().then(function(){
+                       expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope')).isDisplayed()).toBe(true);
+               });
+       });
+
+});
+
+describe('testing the Pods page for authorized user', function () {
+
+       beforeEach(function(){
+               mock([
+                       {
+                               request: {
+                                 path: '/api/v1/pods',
+                                 method: 'POST'
+                               },
+                               response: {
+                                       data: {
+                                               href: baseURL+"/api/v1/pods/test"
+                                       }
+                               }
+                         },
+                         {
+                               request: {
+                                 path: '/api/v1/pods',
+                                 method: 'POST',
+                                 data: {
+                                       name: 'test1',
+                                       details : 'DemoDetails',
+                                       role : 'community-ci',
+                                       mode : 'metal'
+                                 }
+                               },
+                               response: {
+                                       status : 403
+                               }
+                         },
+                         {
+                               request: {
+                               path: '/api/v1/profile',
+                               method: 'GET'
+                               },
+                               response: {
+                                       data: {
+                                               "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", "user": "testUser", "groups": ["opnfv-testapi-users"], "email": "testuser@test.com"
+                                       }
+                               }
+                       }
+               ]);
+       });
+
+       it('create button is visible for authorized user', function () {
+               browser.get(baseURL + '/#/pods');
+               var buttonCreate = element(by.buttonText('Create'));
+               expect(buttonCreate.isDisplayed()).toBe(true);
+       });
+
+       it('Do not show error if input is acceptable', function () {
+               var name = element(by.model('ctrl.name'));
+               var details = element(by.model('ctrl.details'));
+               name.sendKeys('test');
+               details.sendKeys('DemoDetails');
+               var buttonCreate = element(by.buttonText('Create'));
+               buttonCreate.click().then(function(){
+                       expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope')).isDisplayed()).toBe(false);
+               });
+       });
+
+       it('Show error when user click the create button with a empty name', function () {
+               browser.get(baseURL+ '/#/pods');
+               var details = element(by.model('ctrl.details'));
+               details.sendKeys('DemoDetails');
+               var buttonCreate = element(by.buttonText('Create'));
+               buttonCreate.click();
+               expect(element(by.cssContainingText(".alert","Name is missing.")).isDisplayed()).toBe(true);
+       });
+
+       it('Show error when user click the create button with an already existing name', function () {
+               browser.get(baseURL+ '/#/pods');
+               var name = element(by.model('ctrl.name'));
+               var details = element(by.model('ctrl.details'));
+               name.sendKeys('test1');
+               details.sendKeys('DemoDetails');
+               var buttonCreate = element(by.buttonText('Create'));
+               buttonCreate.click();
+               expect(element(by.cssContainingText(".alert","Error creating the new pod from server: Pod's name already exists")).isDisplayed()).toBe(true);
+       });
+
+       it('If backend is not responding then show error when user click the create button',function(){
+               mock.teardown();
+               mock([
+                         {
+                               request: {
+                               path: '/api/v1/profile',
+                               method: 'GET'
+                               },
+                               response: {
+                                       data: {
+                                               "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", "user": "testUser", "groups": ["opnfv-testapi-users"], "email": "testuser@test.com"
+                                       }
+                               }
+                       }
+               ]);
+               browser.get(baseURL+ '/#/pods');
+               var name = element(by.model('ctrl.name'));
+               var details = element(by.model('ctrl.details'));
+               name.sendKeys('test');
+               details.sendKeys('DemoDetails');
+               var buttonCreate = element(by.buttonText('Create'));
+               buttonCreate.click().then(function(){
+                       expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope')).isDisplayed()).toBe(true);
+               });
+       })
+});
\ No newline at end of file
diff --git a/utils/test/testapi/opnfv_testapi/tests/UI/karma.conf.js b/utils/test/testapi/opnfv_testapi/tests/UI/karma.conf.js
new file mode 100644 (file)
index 0000000..eaded5a
--- /dev/null
@@ -0,0 +1,14 @@
+module.exports = function (config) {
+       config.set({
+               frameworks: ['jasmine'],
+               files: [
+                       "assets/lib/angular/angular.js",
+                       "assets/lib/angular-mocks/angular-mocks.js",
+               ],
+               autoWatch: true,
+               browsers: ['Chrome'],
+               singleRun: true,
+               reporters: ['progress', 'coverage'],
+        preprocessors: { 'src/*.js': ['coverage'] }
+       });
+};
diff --git a/utils/test/testapi/opnfv_testapi/tests/UI/protractor-conf.js b/utils/test/testapi/opnfv_testapi/tests/UI/protractor-conf.js
new file mode 100644 (file)
index 0000000..affbe5d
--- /dev/null
@@ -0,0 +1,18 @@
+exports.config = {
+       seleniumAddress: 'http://localhost:4444/wd/hub',
+       capabilities: {
+               'browserName': 'chrome',
+               'chromeOptions': {
+                       'args': ['show-fps-counter=true', '--disable-web-security', "no-sandbox", "--headless", "--disable-gpu"]
+               }
+       },
+       jasmineNodeOpts: {
+               showColors: true,
+               defaultTimeoutInterval: 30000
+       },
+       onPrepare: function(){
+               require('protractor-http-mock').config = {
+                       rootDirectory: __dirname
+               };
+       }
+};
index aa99b90..743c076 100644 (file)
@@ -14,7 +14,7 @@ import mock
 
 
 O_get_secure_cookie = (
-    'opnfv_testapi.resources.handlers.GenericApiHandler.get_secure_cookie')
+    'opnfv_testapi.handlers.base_handlers.GenericApiHandler.get_secure_cookie')
 
 
 def thread_execute(method, *args, **kwargs):
@@ -14,8 +14,8 @@ from bson.objectid import ObjectId
 import mock
 from tornado import testing
 
-from opnfv_testapi.resources import models
-from opnfv_testapi.resources import pod_models
+from opnfv_testapi.models import base_models
+from opnfv_testapi.models import pod_models
 from opnfv_testapi.tests.unit import fake_pymongo
 
 
@@ -25,7 +25,7 @@ class TestBase(testing.AsyncHTTPTestCase):
     def setUp(self):
         self._patch_server()
         self.basePath = ''
-        self.create_res = models.CreateResponse
+        self.create_res = base_models.CreateResponse
         self.get_res = None
         self.list_res = None
         self.update_res = None
@@ -10,10 +10,10 @@ import httplib
 import unittest
 
 from opnfv_testapi.common import message
-from opnfv_testapi.resources import pod_models
+from opnfv_testapi.models import pod_models
 from opnfv_testapi.tests.unit import executor
 from opnfv_testapi.tests.unit import fake_pymongo
-from opnfv_testapi.tests.unit.resources import test_base as base
+from opnfv_testapi.tests.unit.handlers import test_base as base
 
 
 class TestPodBase(base.TestBase):
@@ -2,9 +2,9 @@ import httplib
 import unittest
 
 from opnfv_testapi.common import message
-from opnfv_testapi.resources import project_models
+from opnfv_testapi.models import project_models
 from opnfv_testapi.tests.unit import executor
-from opnfv_testapi.tests.unit.resources import test_base as base
+from opnfv_testapi.tests.unit.handlers import test_base as base
 
 
 class TestProjectBase(base.TestBase):
@@ -15,12 +15,12 @@ import urllib
 import unittest
 
 from opnfv_testapi.common import message
-from opnfv_testapi.resources import project_models
-from opnfv_testapi.resources import result_models
-from opnfv_testapi.resources import testcase_models
+from opnfv_testapi.models import project_models
+from opnfv_testapi.models import result_models
+from opnfv_testapi.models import testcase_models
 from opnfv_testapi.tests.unit import executor
 from opnfv_testapi.tests.unit import fake_pymongo
-from opnfv_testapi.tests.unit.resources import test_base as base
+from opnfv_testapi.tests.unit.handlers import test_base as base
 
 
 class Details(object):
@@ -6,8 +6,8 @@ import os
 from datetime import datetime
 
 from opnfv_testapi.common import message
-import opnfv_testapi.resources.scenario_models as models
-from opnfv_testapi.tests.unit.resources import test_base as base
+import opnfv_testapi.models.scenario_models as models
+from opnfv_testapi.tests.unit.handlers import test_base as base
 
 
 def _none_default(check, default):
@@ -11,10 +11,10 @@ import httplib
 import unittest
 
 from opnfv_testapi.common import message
-from opnfv_testapi.resources import project_models
-from opnfv_testapi.resources import testcase_models
+from opnfv_testapi.models import project_models
+from opnfv_testapi.models import testcase_models
 from opnfv_testapi.tests.unit import executor
-from opnfv_testapi.tests.unit.resources import test_base as base
+from opnfv_testapi.tests.unit.handlers import test_base as base
 
 
 class TestCaseBase(base.TestBase):
@@ -11,7 +11,7 @@ from tornado import web
 from opnfv_testapi.common import message
 from opnfv_testapi.tests.unit import executor
 from opnfv_testapi.tests.unit import fake_pymongo
-from opnfv_testapi.tests.unit.resources import test_result
+from opnfv_testapi.tests.unit.handlers import test_result
 
 
 class TestTokenCreateResult(test_result.TestResultBase):
@@ -9,15 +9,15 @@
 import httplib
 import unittest
 
-from opnfv_testapi.resources import models
+from opnfv_testapi.models import base_models
 from opnfv_testapi.tests.unit import executor
-from opnfv_testapi.tests.unit.resources import test_base as base
+from opnfv_testapi.tests.unit.handlers import test_base as base
 
 
 class TestVersionBase(base.TestBase):
     def setUp(self):
         super(TestVersionBase, self).setUp()
-        self.list_res = models.Versions
+        self.list_res = base_models.Versions
         self.basePath = '/versions'
 
 
diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_fake_pymongo.py b/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_fake_pymongo.py
deleted file mode 100644 (file)
index 1ebc96f..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 ZTE Corporation
-# feng.xiaowei@zte.com.cn
-# 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
-##############################################################################
-import unittest
-
-from tornado import gen
-from tornado import testing
-from tornado import web
-
-from opnfv_testapi.tests.unit import fake_pymongo
-
-
-class MyTest(testing.AsyncHTTPTestCase):
-    def setUp(self):
-        super(MyTest, self).setUp()
-        self.db = fake_pymongo
-        self.addCleanup(self._clear)
-        self.io_loop.run_sync(self.fixture_setup)
-
-    def get_app(self):
-        return web.Application()
-
-    @gen.coroutine
-    def fixture_setup(self):
-        self.test1 = {'_id': '1', 'name': 'test1'}
-        self.test2 = {'name': 'test2'}
-        yield self.db.pods.insert({'_id': '1', 'name': 'test1'})
-        yield self.db.pods.insert({'name': 'test2'})
-
-    @testing.gen_test
-    def test_find_one(self):
-        user = yield self.db.pods.find_one({'name': 'test1'})
-        self.assertEqual(user, self.test1)
-        self.db.pods.remove()
-
-    @testing.gen_test
-    def test_find(self):
-        cursor = self.db.pods.find()
-        names = []
-        while (yield cursor.fetch_next):
-            ob = cursor.next_object()
-            names.append(ob.get('name'))
-        self.assertItemsEqual(names, ['test1', 'test2'])
-
-    @testing.gen_test
-    def test_update(self):
-        yield self.db.pods.update({'_id': '1'}, {'name': 'new_test1'})
-        user = yield self.db.pods.find_one({'_id': '1'})
-        self.assertEqual(user.get('name', None), 'new_test1')
-
-    def test_update_dot_error(self):
-        self._update_assert({'_id': '1', 'name': {'1. name': 'test1'}},
-                            'key 1. name must not contain .')
-
-    def test_update_dot_no_error(self):
-        self._update_assert({'_id': '1', 'name': {'1. name': 'test1'}},
-                            None,
-                            check_keys=False)
-
-    def test_update_dollar_error(self):
-        self._update_assert({'_id': '1', 'name': {'$name': 'test1'}},
-                            'key $name must not start with $')
-
-    def test_update_dollar_no_error(self):
-        self._update_assert({'_id': '1', 'name': {'$name': 'test1'}},
-                            None,
-                            check_keys=False)
-
-    @testing.gen_test
-    def test_remove(self):
-        yield self.db.pods.remove({'_id': '1'})
-        user = yield self.db.pods.find_one({'_id': '1'})
-        self.assertIsNone(user)
-
-    def test_insert_dot_error(self):
-        self._insert_assert({'_id': '1', '2. name': 'test1'},
-                            'key 2. name must not contain .')
-
-    def test_insert_dot_no_error(self):
-        self._insert_assert({'_id': '1', '2. name': 'test1'},
-                            None,
-                            check_keys=False)
-
-    def test_insert_dollar_error(self):
-        self._insert_assert({'_id': '1', '$name': 'test1'},
-                            'key $name must not start with $')
-
-    def test_insert_dollar_no_error(self):
-        self._insert_assert({'_id': '1', '$name': 'test1'},
-                            None,
-                            check_keys=False)
-
-    def _clear(self):
-        self.db.pods.clear()
-
-    def _update_assert(self, docs, error=None, **kwargs):
-        self._db_assert('update', error, {'_id': '1'}, docs, **kwargs)
-
-    def _insert_assert(self, docs, error=None, **kwargs):
-        self._db_assert('insert', error, docs, **kwargs)
-
-    @testing.gen_test
-    def _db_assert(self, method, error, *args, **kwargs):
-        name_error = None
-        try:
-            yield self._eval_pods_db(method, *args, **kwargs)
-        except NameError as err:
-            name_error = err.args[0]
-        finally:
-            self.assertEqual(name_error, error)
-
-    def _eval_pods_db(self, method, *args, **kwargs):
-        table_obj = vars(self.db)['pods']
-        return table_obj.__getattribute__(method)(*args, **kwargs)
-
-
-if __name__ == '__main__':
-    unittest.main()
index e39a9f6..a04de07 100644 (file)
@@ -26,7 +26,7 @@ def swagger_handlers():
             settings.docs_settings,
             name=settings.API_DOCS_NAME),
         tornado.web.URLSpec(
-            _path(r'resources.json$'),
+            _path(r'models.json$'),
             views.SwaggerResourcesHandler,
             settings.docs_settings,
             name=settings.RESOURCE_LISTING_NAME),
diff --git a/utils/test/testapi/opnfv_testapi/ui/auth/__init__.py b/utils/test/testapi/opnfv_testapi/ui/auth/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
index 23341e4..b3394d4 100644 (file)
@@ -1,8 +1,6 @@
 [metadata]
 name = opnfv_testapi
 summary = Test Result Collector
-description-file = 
-    README.rst
 author = SerenaFeng
 author-email = feng.xiaowei@zte.com.cn
 #home-page = http://www.opnfv.org/
@@ -28,6 +26,7 @@ packages =
 data_files =
     /etc/opnfv_testapi = etc/config.ini
     /usr/local/share/opnfv_testapi = 3rd_party/static/*
+    /usr/local/share/opnfv_testapi/testapi-ui/components = opnfv_testapi/ui/*
 
 [entry_points]
 console_scripts =
index d300f1a..13b197c 100644 (file)
@@ -25,6 +25,10 @@ setenv=
   HOME = {envtmpdir}
   PYTHONPATH = {toxinidir}
 
+[testenv:docs]
+basepython=python2.7
+commands = sphinx-build -W -b html docs/ docs/_build
+
 [testenv:pep8]
 deps = flake8
 commands = flake8 {toxinidir}