diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 61902c7..0000000 --- a/.coveragerc +++ /dev/null @@ -1,6 +0,0 @@ -[run] -branch = True -source = monasca_tempest_plugin - -[report] -ignore_errors = True diff --git a/.mailmap b/.mailmap deleted file mode 100644 index 516ae6f..0000000 --- a/.mailmap +++ /dev/null @@ -1,3 +0,0 @@ -# Format is: -# -# diff --git a/.stestr.conf b/.stestr.conf deleted file mode 100644 index 67823ad..0000000 --- a/.stestr.conf +++ /dev/null @@ -1,3 +0,0 @@ -[DEFAULT] -test_path=./monasca_tempest_plugin/tests -top_dir=./ diff --git a/.zuul.yaml b/.zuul.yaml deleted file mode 100644 index 2560da6..0000000 --- a/.zuul.yaml +++ /dev/null @@ -1,69 +0,0 @@ - -- project: - queue: monasca - templates: - - check-requirements - - tempest-plugin-jobs - - publish-openstack-docs-pti - check: - jobs: - - monasca-tempest-python3-influxdb: - voting: false - - monasca-tempest-python3-cassandra: - voting: false - - monasca-tempest-log-python3-influxdb: - voting: false - - build-monasca-docker-image: - voting: false - gate: - jobs: - - monasca-tempest-python3-influxdb: - voting: false - - monasca-tempest-log-python3-influxdb: - voting: false - post: - jobs: - - publish-monasca-tempest-plugin-docker-image - periodic: - jobs: - - publish-monasca-tempest-plugin-docker-image - release: - jobs: - - publish-monasca-tempest-plugin-docker-image - -- job: - name: publish-monasca-tempest-plugin-docker-image - parent: build-monasca-docker-image - post-run: playbooks/docker-publish.yml - required-projects: - - openstack/monasca-common - vars: - publisher: true - secrets: - - doker_hub_login_tempest - -- secret: - name: doker_hub_login_tempest - data: - user: !encrypted/pkcs1-oaep - - TB40TL1BT0pn4kcfHVZqtu+7cuRXM2OJYmHUDdpAVjdwiZvhTu6W0e2jWGv5knNXsPI+n - cz0LB/oYxg5TGl5WHpz9If66dW1lW9HwjlAYOyizzTmz+AfwNShUDR6W39rfxhjxY5bxu - 20FBJnhmcAZvR6iQas7nuD+8PhoFlNAGhk0y9r7qCzVzgM4A2icVHor9xk7UGAyC3HgLN - u5QFhaUmZ32r0pNOnVQF1NgHIBWMk+De6NTr/hw9jXrGOQJYysG6GPKRRqNgXAvUpmykz - Tu7hP17EwgRVxWqwheqEAzIPOGSpWlF32nKJ63yIiMRlkxp3guZMu3/oVDNODoy05WaLc - fO/WeF/pCj+lAJWrC/1diDMnuA4vRgC1ME/f4DANFHjIO3ir0M38IafZW5HbCC0LzFNaE - yJH/0AWwU8O0XAU62Rpr7n57BFib80ViPGkJZ4FOQE0DByEk/BgV0diex4CBlk+AOhOVo - K3Jh238mYdNVFxDqiYCsZNgIkIkSH5hBS2CU2bTcE5856Ep2c7syzTQVwszl34DJk6+ws - pzbGQaFxFpO5B1gnZC4GMMT/uFjAaQGMpSN3sGY1R/Jqs0E/moP227y/WS47YdcXA+t2n - OxuUsTT8qqZ6gmGtRiqgBUqSxNKBdemfXMmiI2nGmHMii/LG5Sw+x5ma2zPyzs= - password: !encrypted/pkcs1-oaep - - L3MF9SSBol2o85/7AUWkkaJQtNo6hFKTruK1JaCpiTojAcNVWIYatny7hFoftWiTkMJfC - VncmLDg6rBZCyB+lhq77CmrvP9Z4HHGlqmUC9HzTx13fTQKUKQsY3fz2reTiO79XlvI2k - z7NzubH8IPj1461kMXL1tSbE/ESwzp7aIqmALJ4pf73sC+YIx7LbW3zwqEWNf61w+/OHt - 03hTCidO98KgZQHV25r0EeCx9ts8BSUamLppsWkq4XzkN7gmUs0BvPdCP+bFltnAbyhwQ - m7r7ga1bZ7cWVxdH4bezync+jWHO1IUxO90erFf7WuvfAYEA85SfDAuqNVF7HJvL+gKDt - wSIybJtHiAUOj9a0/ZoHMBHf7GW1/PDkdJ/HYP5RRRwYp+8YQkb1DYE2USUGhPWr0Vx/U - /LTsBmMfV0GHbGTlNNVRoM2axgreyjX8Ioj+08CXsKnyY1x6V2giRvONaKqt4b+kSGgRj - 2j6CpWYUysJAjwVMYviI/cj1/4kyrdIajQQh7QuC+ESPd/8f6ijmyF9pBlbeBJSHnLMDv - ZCufss2XmedqxiyPgjq9HbNN7TNOYAWYI8u9FoojR6UTjNfGx9fZ7jmBas5KFC2BAkZo1 - HkFvJgA8USrM7U9LRAQnuRTSxFcqPyUKyyixXVpA7S56TO9GiHPhcAngEUtMSA= diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index 8047329..0000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,17 +0,0 @@ -If you would like to contribute to the development of OpenStack, you must -follow the steps in this page: - - https://docs.openstack.org/infra/manual/developers.html - -If you already have a good understanding of how the system works and your -OpenStack accounts are set up, you can skip to the development workflow -section of this documentation to learn how changes to OpenStack should be -submitted for review via the Gerrit tool: - - https://docs.openstack.org/infra/manual/developers.html#development-workflow - -Pull requests submitted through GitHub will be ignored. - -Bugs should be filed on StoryBoard, not GitHub: - - https://storyboard.openstack.org/#!/project/919 diff --git a/HACKING.rst b/HACKING.rst deleted file mode 100644 index 3392185..0000000 --- a/HACKING.rst +++ /dev/null @@ -1,4 +0,0 @@ -openstack Style Commandments -============================ - -Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/ diff --git a/README.rst b/README.rst index f167ca9..d4129d3 100644 --- a/README.rst +++ b/README.rst @@ -1,13 +1,9 @@ -====================== -Monasca Tempest Plugin -====================== +This project is no longer maintained. -Tempest plugin for Monasca API and Log API Project +The contents of this repository are still available in the Git +source code management system. To see the contents of this +repository before it reached its end of life, please check out the +previous commit with "git checkout HEAD^1". -It contains the tempest plugin for the functional testing of Monasca Project. - -* Free software: Apache license -* Documentation: https://docs.openstack.org/monasca-tempest-plugin/latest/ -* Release notes: https://docs.openstack.org/releasenotes/monasca-api/ -* Source: https://opendev.org/openstack/monasca-tempest-plugin -* Bugs: https://storyboard.openstack.org/#!/project/919 +For any further questions, please email openstack-discuss@lists.openstack.org +or join #openstack-dev on OFTC. diff --git a/babel.cfg b/babel.cfg deleted file mode 100644 index 15cd6cb..0000000 --- a/babel.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[python: **.py] - diff --git a/devstack/README.rst b/devstack/README.rst deleted file mode 100644 index e6848a3..0000000 --- a/devstack/README.rst +++ /dev/null @@ -1,33 +0,0 @@ -==================== -Enabling in Devstack -==================== - -**WARNING**: the stack.sh script must be run in a disposable VM that is not -being created automatically, see the README.md file in the "devstack" -repository. - -1. Download DevStack:: - - git clone https://opendev.org/openstack/devstack.git - cd devstack - -2. Add this repo as an external repository:: - - > cat local.conf - [[local|localrc]] - enable_plugin monasca-tempest-plugin https://opendev.org/openstack/monasca-tempest-plugin - -3. run ``stack.sh`` - -Running Monasca tempest tests -============================= - -1. Listing Monasca tempest tests:: - - tempest list-plugins - -2. Running monasca tempest tests:: - - cd /opt/stack/tempest - tempest run -r monasca_tempest_tests.tests.api - tempest run -r monasca_tempest_tests.tests.log_api diff --git a/devstack/plugin.sh b/devstack/plugin.sh deleted file mode 100644 index 03752eb..0000000 --- a/devstack/plugin.sh +++ /dev/null @@ -1,13 +0,0 @@ -# install_monasca_tempest_plugin -function install_monasca_tempest_plugin { - setup_dev_lib "monasca-tempest-plugin" -} - -if [[ "$1" == "stack" ]]; then - case "$2" in - install) - echo_summary "Installing monasca-tempest-plugin" - install_monasca_tempest_plugin - ;; - esac -fi diff --git a/devstack/settings b/devstack/settings deleted file mode 100644 index 125fbec..0000000 --- a/devstack/settings +++ /dev/null @@ -1,3 +0,0 @@ -GITREPO["monasca-tempest-plugin"]=${MONASCA_TEMPEST_REPO:-${GIT_BASE}/openstack/monasca-tempest-plugin.git} -GITDIR["monasca-tempest-plugin"]=$DEST/monasca-tempest-plugin -GITBRANCH["monasca-tempest-plugin"]=master diff --git a/doc/requirements.txt b/doc/requirements.txt deleted file mode 100644 index 60ba470..0000000 --- a/doc/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -sphinx>=2.0.0,!=2.1.0 # BSD -openstackdocstheme>=2.2.1 # Apache-2.0 -# releasenotes -reno>=3.1.0 # Apache-2.0 diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100755 index 9193066..0000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -sys.path.insert(0, os.path.abspath('../..')) -# -- General configuration ---------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [ - 'sphinx.ext.autodoc', - 'openstackdocstheme', -] - -# autodoc generation is a bit aggressive and a nuisance when doing heavy -# text edit cycles. -# execute "export SPHINX_DEBUG=1" in your terminal to disable - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = 'monasca-tempest-plugin' -copyright = '2017, OpenStack Developers' - -# openstackdocstheme options -openstackdocs_repo_name = 'openstack/monasca-tempest-plugin' -openstackdocs_use_storyboard = True - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'native' - -# -- Options for HTML output -------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -# html_theme_path = ["."] -# html_theme = '_theme' -# html_static_path = ['static'] -html_theme = 'openstackdocs' - -# Output file base name for HTML help builder. -htmlhelp_basename = '%sdoc' % project - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto/manual]). -latex_documents = [ - ('index', - '%s.tex' % project, - u'%s Documentation' % project, - u'OpenStack Developers', 'manual'), -] - -# Example configuration for intersphinx: refer to the Python standard library. -#intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/doc/source/index.rst b/doc/source/index.rst deleted file mode 100644 index 681cc43..0000000 --- a/doc/source/index.rst +++ /dev/null @@ -1,18 +0,0 @@ -====================================================== -Welcome to the documentation of monasca_tempest_plugin -====================================================== - -Contents: - -.. toctree:: - :maxdepth: 2 - - readme - installation - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/doc/source/installation.rst b/doc/source/installation.rst deleted file mode 100644 index 5520fe0..0000000 --- a/doc/source/installation.rst +++ /dev/null @@ -1,13 +0,0 @@ -============ -Installation -============ - -Tempest automatically discovers installed plugins. That's why you just need -to install the Python packages that contains the Monasca Tempest plugin in -the same environment where Tempest is installed. - -At the command line:: - - $ git clone https://opendev.org/openstack/monasca-tempest-plugin - $ cd monasca-tempest-plugin/ - $ pip install monasca-tempest-plugin diff --git a/doc/source/readme.rst b/doc/source/readme.rst deleted file mode 100644 index a6210d3..0000000 --- a/doc/source/readme.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../README.rst diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index 6fd9cad..0000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -ARG DOCKER_IMAGE=monasca/tempest-tests -ARG APP_REPO=https://review.opendev.org/openstack/monasca-tempest-plugin - -# Branch, tag or git hash to build from. -ARG REPO_VERSION=master -ARG CONSTRAINTS_BRANCH=master - -# Extra Python3 dependencies. -ARG EXTRA_DEPS="python-openstackclient python-monascaclient" - -# Always start from `monasca-base` image and use specific tag of it. -ARG BASE_TAG=master -FROM monasca/base:$BASE_TAG - -# Environment variables used for our service or wait scripts. -ENV \ - KEYSTONE_IDENTITY_URI=http://keystone:35357 \ - USE_DYNAMIC_CREDS=True \ - KEYSTONE_ADMIN_USER=mini-mon \ - KEYSTONE_ADMIN_PASSWORD=password \ - KEYSTONE_ADMIN_PROJECT=mini-mon \ - KEYSTONE_ADMIN_DOMAIN=Default \ - OS_AUTH_URL=http://keystone:35357/v3 \ - OS_USERNAME=mini-mon \ - OS_PASSWORD=password \ - OS_TENANT_NAME=mini-mon \ - OS_DOMAIN_NAME=Default \ - MONASCA_WAIT_FOR_API=true \ - MONASCA_API_WAIT_RETRIES=24 \ - MONASCA_API_WAIT_INTERVAL=5 \ - STAY_ALIVE_ON_FAILURE=false - -# Copy all neccessary files to proper locations. -COPY tempest.conf.j2 /etc/tempest/ - -WORKDIR /tempest - -# Run here all additionals steps your service need post installation. -# Stay with only one `RUN` and use `&& \` for next steps to don't create -# unnecessary image layers. Clean at the end to conserve space. -#RUN \ -# echo "Some steps to do after main installation." && \ -# echo "Hello when building." - -# Implement start script in `start.sh` file. -CMD ["/start.sh"] diff --git a/docker/README.rst b/docker/README.rst deleted file mode 100644 index 9e4c04c..0000000 --- a/docker/README.rst +++ /dev/null @@ -1,122 +0,0 @@ -=============================================== -Docker image for Monasca Monasca Temptest tests -=============================================== -This image could be used for running Tempest tests on Monasca installed in any -way. After providing proper environment variables container could be started -and will run tests based on what endpoints it will find in configured Keystone. -Supported endpoints are ``monitoring`` and ``logs`` (``Service Type`` in -``openstack endpoint list`` output). - - -Building monasca-base image -=========================== -See https://github.com/openstack/monasca-common/tree/master/docker/README.rst - - -Building Docker image -===================== - -Example: - $ ./build_image.sh - -Everything after ``./build_image.sh`` is optional and by default configured -to get versions from ``Dockerfile``. ``./build_image.sh`` also contain more -detailed build description. - - -How to start -~~~~~~~~~~~~ - -To run, this container needs to connect to a working Keystone and Monasca API. - -When using running Monasca in Docker you can connect this image to the network -where Monasca is accessible and run all tests. -Find network on machine with Monasca with ``docker network ls``. -For example you can see similar information to: -``e20533f6112c monasca-docker_default bridge local`` - -Using this network run all tempest tests with following command: - -``docker run -it --rm --network=monasca-docker_default monasca/tempest-tests:master`` - -It's important to configure all necessary connection environment variables. -They are listed in the next two sections. - -Example command to run tempest tests with custom variables:: - -``docker run -it --rm --network=monasca-docker_default --env-file=tempest_con.env monasca/tempest-tests:master`` - -In this example you configure all environment variables in ``tempest_con.env`` -file:: - - KEYSTONE_IDENTITY_URI=http://172.17.0.1:35357 - USE_DYNAMIC_CREDS=True - KEYSTONE_ADMIN_USER=mini-mon - KEYSTONE_ADMIN_PASSWORD=password - KEYSTONE_ADMIN_PROJECT=mini-mon - KEYSTONE_ADMIN_DOMAIN=Default - OS_AUTH_URL=http://172.17.0.1:35357/v3 - OS_USERNAME=mini-mon - OS_PASSWORD=password - OS_PROJECT_NAME=mini-mon - OS_DOMAIN_NAME=Default - -In order to run in docker-compose add this section to docker-compose.yaml:: - - tempest-tests: - image: monasca/tempest-tests:master - environment: - KEYSTONE_IDENTITY_URI: "http://keystone:35357" - - -Environment variables -~~~~~~~~~~~~~~~~~~~~~ -========================= ============================== ========================================== -Variable Default Description -========================= ============================== ========================================== -USE_DYNAMIC_CREDS True Create dynamic credentials for tests -KEYSTONE_ADMIN_USER mini-mon OpenStack administrator user name -KEYSTONE_ADMIN_PASSWORD password OpenStack administrator user password -KEYSTONE_ADMIN_PROJECT mini-mon OpenStack administrator tenant name -KEYSTONE_ADMIN_DOMAIN Default OpenStack administrator domain -OS_AUTH_URL http://keystone:35357/v3 Versioned Keystone URL -OS_USERNAME mini-mon Keystone user name -OS_PASSWORD password Keystone user password -OS_PROJECT_NAME mini-mon Keystone user project name -OS_DOMAIN_NAME Default Keystone user domain name -IDENTITY_URI http://keystone:35357/v2.0/ Full URI of the Keystone, v2 -IDENTITY_URI_V3 http://keystone:35357/v3/ Full URI of the Keystone, v3 -LOG_LEVEL INFO Log level for root logging -STAY_ALIVE_ON_FAILURE false If true, container runs 2 hours after service fail -========================= ============================== ========================================== - - -Wait scripts environment variables -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -========================= =========================== ============================================= -Variable Default Description -========================= =========================== ============================================= -KEYSTONE_IDENTITY_URI http://keystone:35357 URI to Keystone admin endpoint -MONASCA_WAIT_FOR_API true If true, ensure Monasca API is available -MONASCA_API_WAIT_RETRIES 24 Retries for Monasca API availability checks -MONASCA_API_WAIT_INTERVAL 5 Sleep time between Monasca API retries -========================= =========================== ============================================= - - -Scripts -~~~~~~~ -start.sh - In this starting script provide all steps that lead to the proper service - start. Including usage of wait scripts and templating of configuration - files. You also could provide the ability to allow running container after - service died for easier debugging. - -health_check.py - This file will be used for checking the status of the application. - - -Links -~~~~~ -https://docs.openstack.org/monasca-api/latest/ - -https://github.com/openstack/monasca-api/blob/master/README.rst diff --git a/docker/build_image.sh b/docker/build_image.sh deleted file mode 100755 index fc0b18b..0000000 --- a/docker/build_image.sh +++ /dev/null @@ -1,150 +0,0 @@ -#!/bin/bash - -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# TODO(Dobroslaw): move this script to monasca-common/docker folder -# and leave here small script to download it and execute using env variables -# to minimize code duplication. - -set -x # Print each script step. -set -eo pipefail # Exit the script if any statement returns error. - -# This script is used for building Docker image with proper labels -# and proper version of monasca-common. -# -# Example usage: -# $ ./build_image.sh -# -# Everything after `./build_image.sh` is optional and by default configured -# to get versions from `Dockerfile`. -# -# To build from master branch (default): -# $ ./build_image.sh -# To build specific version run this script in the following way: -# $ ./build_image.sh stable/queens -# Building from specific commit: -# $ ./build_image.sh cb7f226 -# When building from a tag monasca-common will be used in version available -# in upper constraint file: -# $ ./build_image.sh 2.5.0 -# To build image from Gerrit patch sets that is targeting branch stable/queens: -# $ ./build_image.sh refs/changes/51/558751/1 stable/queens -# -# If you want to build image with custom monasca-common version you need -# to provide it as in the following example: -# $ ./build_image.sh master master refs/changes/19/595719/3 - -# Go to folder with Docker files. -REAL_PATH=$(python3 -c "import os,sys; print(os.path.realpath('$0'))") -cd "$(dirname "$REAL_PATH")/../docker/" - -[ -z "$DOCKER_IMAGE" ] && \ - DOCKER_IMAGE=$(\grep DOCKER_IMAGE Dockerfile | cut -f2 -d"=") - -: "${REPO_VERSION:=$1}" -[ -z "$REPO_VERSION" ] && \ - REPO_VERSION=$(\grep REPO_VERSION Dockerfile | cut -f2 -d"=") -# Let's stick to more readable version and disable SC2001 here. -# shellcheck disable=SC2001 -REPO_VERSION_CLEAN=$(echo "$REPO_VERSION" | sed 's|/|-|g') - -[ -z "$APP_REPO" ] && APP_REPO=$(\grep APP_REPO Dockerfile | cut -f2 -d"=") -GITHUB_REPO=$(echo "$APP_REPO" | sed 's/review.opendev.org/github.com/' | \ - sed 's/ssh:/https:/') - -if [ -z "$CONSTRAINTS_FILE" ]; then - CONSTRAINTS_FILE=$(\grep CONSTRAINTS_FILE Dockerfile | cut -f2 -d"=") || true - : "${CONSTRAINTS_FILE:=https://releases.openstack.org/constraints/upper/master}" -fi - -: "${CONSTRAINTS_BRANCH:=$2}" -[ -z "$CONSTRAINTS_BRANCH" ] && \ - CONSTRAINTS_BRANCH=$(\grep CONSTRAINTS_BRANCH Dockerfile | cut -f2 -d"=") - -# When using stable version of repository use same stable constraints file. -case "$REPO_VERSION" in - *stable*) - CONSTRAINTS_BRANCH_CLEAN="$REPO_VERSION" - CONSTRAINTS_FILE=${CONSTRAINTS_FILE/master/$CONSTRAINTS_BRANCH_CLEAN} - # Get monasca-common version from stable upper constraints file. - CONSTRAINTS_TMP_FILE=$(mktemp) - wget --output-document "$CONSTRAINTS_TMP_FILE" \ - $CONSTRAINTS_FILE - UPPER_COMMON=$(\grep 'monasca-common' "$CONSTRAINTS_TMP_FILE") - # Get only version part from monasca-common. - UPPER_COMMON_VERSION="${UPPER_COMMON##*===}" - rm -rf "$CONSTRAINTS_TMP_FILE" - ;; - *) - CONSTRAINTS_BRANCH_CLEAN="$CONSTRAINTS_BRANCH" - ;; -esac - -# Monasca-common variables. -if [ -z "$COMMON_REPO" ]; then - COMMON_REPO=$(\grep COMMON_REPO Dockerfile | cut -f2 -d"=") || true - : "${COMMON_REPO:=https://review.opendev.org/openstack/monasca-common}" -fi -: "${COMMON_VERSION:=$3}" -if [ -z "$COMMON_VERSION" ]; then - COMMON_VERSION=$(\grep COMMON_VERSION Dockerfile | cut -f2 -d"=") || true - if [ "$UPPER_COMMON_VERSION" ]; then - # Common from upper constraints file. - COMMON_VERSION="$UPPER_COMMON_VERSION" - fi -fi - -# Clone project to temporary directory for getting proper commit number from -# branches and tags. We need this for setting proper image labels. -# Docker does not allow to get any data from inside of system when building -# image. -TMP_DIR=$(mktemp -d) -( - cd "$TMP_DIR" - # This many steps are needed to support gerrit patch sets. - git init - git remote add origin "$APP_REPO" - git fetch origin "$REPO_VERSION" - git reset --hard FETCH_HEAD -) -GIT_COMMIT=$(git -C "$TMP_DIR" rev-parse HEAD) -[ -z "${GIT_COMMIT}" ] && echo "No git commit hash found" && exit 1 -rm -rf "$TMP_DIR" - -# Do the same for monasca-common. -COMMON_TMP_DIR=$(mktemp -d) -( - cd "$COMMON_TMP_DIR" - # This many steps are needed to support gerrit patch sets. - git init - git remote add origin "$COMMON_REPO" - git fetch origin "$COMMON_VERSION" - git reset --hard FETCH_HEAD -) -COMMON_GIT_COMMIT=$(git -C "$COMMON_TMP_DIR" rev-parse HEAD) -[ -z "${COMMON_GIT_COMMIT}" ] && echo "No git commit hash found" && exit 1 -rm -rf "$COMMON_TMP_DIR" - -CREATION_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") - -docker build --no-cache \ - --build-arg CREATION_TIME="$CREATION_TIME" \ - --build-arg GITHUB_REPO="$GITHUB_REPO" \ - --build-arg APP_REPO="$APP_REPO" \ - --build-arg REPO_VERSION="$REPO_VERSION" \ - --build-arg GIT_COMMIT="$GIT_COMMIT" \ - --build-arg CONSTRAINTS_FILE="$CONSTRAINTS_FILE" \ - --build-arg COMMON_REPO="$COMMON_REPO" \ - --build-arg COMMON_VERSION="$COMMON_VERSION" \ - --build-arg COMMON_GIT_COMMIT="$COMMON_GIT_COMMIT" \ - --tag "$DOCKER_IMAGE":"$REPO_VERSION_CLEAN" . diff --git a/docker/health_check.py b/docker/health_check.py deleted file mode 100644 index 38e6ac7..0000000 --- a/docker/health_check.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 - -# (C) Copyright 2018 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Health check will returns 0 when service is working properly.""" - -import logging -import os - - -LOG_LEVEL = logging.getLevelName(os.environ.get('LOG_LEVEL', 'INFO')) -logging.basicConfig(level=LOG_LEVEL) -logger = logging.getLogger(__name__) - - -def main(): - logger.debug('No health check for tempest') - return 0 - - -if __name__ == '__main__': - main() diff --git a/docker/start.sh b/docker/start.sh deleted file mode 100644 index 16e1948..0000000 --- a/docker/start.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/sh - -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# Starting script. -# All checks and configuration templating you need to do before service -# could be safely started should be added in this file. - -set -x - -set -eo pipefail # Exit the script if any statement returns error. - -# Test services we need before starting our service. -echo "Start script: waiting for needed services" -/wait_for.sh "$KEYSTONE_IDENTITY_URI" - -if [ "$MONASCA_WAIT_FOR_API" = "true" ]; then - echo "Waiting for Monasca API to become available..." - success="false" - - for i in $(seq "$MONASCA_API_WAIT_RETRIES"); do - if monasca --os-user-domain-name "${OS_DOMAIN_NAME}" \ - --os-project-name "${OS_TENANT_NAME}" --os-auth-url "${OS_AUTH_URL}" \ - --os-username "${OS_USERNAME}" --os-password "${OS_PASSWORD}" \ - alarm-list --limit 1; then - success="true" - break - else - echo "Monasca API not yet ready (attempt $i of $MONASCA_API_WAIT_RETRIES)" - sleep "$MONASCA_API_WAIT_INTERVAL" - fi - done - - if [ "$success" != "true" ]; then - echo "Monasca API failed to become ready, exiting..." - sleep 1 - exit 1 - fi -fi - -# Template all config files before start, it will use env variables. -# Read usage examples: https://pypi.org/project/Templer/ -echo "Start script: creating config files from templates" -templer -v -f /etc/tempest/tempest.conf.j2 /etc/tempest/tempest.conf - -# Start our service. -echo "Start script: starting tempest" -cd /tempest/ -# Initialize only when folder is empty. -if [ ! "$(ls -A /tempest/)" ]; then - tempest init -fi -tempest list-plugins - -if openstack endpoint list --column "Service Type" -f value | grep -q monitoring -then - tempest run -r monasca_tempest_tests.tests.api -else - true -fi -if openstack endpoint list --column "Service Type" -f value | grep -q logs -then - tempest run -r monasca_tempest_tests.tests.log_api -else - true -fi - -# Allow server to stay alive in case of failure for 2 hours for debugging. -RESULT=$? -if [ $RESULT != 0 ] && [ "$STAY_ALIVE_ON_FAILURE" = "true" ]; then - echo "Service died, waiting 120 min before exiting" - sleep 7200 -fi -exit $RESULT diff --git a/docker/tempest.conf.j2 b/docker/tempest.conf.j2 deleted file mode 100644 index aedc478..0000000 --- a/docker/tempest.conf.j2 +++ /dev/null @@ -1,11 +0,0 @@ -[identity] -auth_version = v3 -uri = {{ AUTH_URI | default(KEYSTONE_IDENTITY_URI + "/v2.0/") }} -uri_v3 = {{ AUTH_URI_V3 | default(KEYSTONE_IDENTITY_URI + "/v3/") }} - -[auth] -use_dynamic_credentials = {{ USE_DYNAMIC_CREDS }} -admin_username = {{ KEYSTONE_ADMIN_USER }} -admin_password = {{ KEYSTONE_ADMIN_PASSWORD }} -admin_project_name = {{ KEYSTONE_ADMIN_PROJECT }} -admin_domain_name = {{ KEYSTONE_ADMIN_DOMAIN }} diff --git a/monasca_tempest_tests/README.md b/monasca_tempest_tests/README.md deleted file mode 100644 index db530ee..0000000 --- a/monasca_tempest_tests/README.md +++ /dev/null @@ -1,186 +0,0 @@ -# Introduction -The Monasca Tempest Tests use the [OpenStack Tempest Plugin Interface](https://docs.openstack.org/tempest/latest/plugin.html). This README describes how to configure and run them using a variety of methods. -Currently the devstack environment is needed to run the tests. Instructions on setting up a devstack environment can be found here: https://github.com/openstack/monasca-api/devstack/README.md. - -# Configuring to run the Monasca Tempest Tests -1. Clone the OpenStack Tempest repo, and cd to it. - - ``` - git clone https://opendev.org/openstack/tempest.git - cd tempest - ``` -2. Create a virtualenv for running the Tempest tests and activate it. For example in the Tempest root dir - - ``` - virtualenv .venv - source .venv/bin/activate - ``` -3. Install the Tempest requirements in the virtualenv. - - ``` - pip install -r requirements.txt -r test-requirements.txt - ``` -4. Create ```etc/tempest.conf``` in the Tempest root dir by running the following command: - - ``` - oslo-config-generator --config-file tempest/cmd/config-generator.tempest.conf --output-file etc/tempest.conf - ``` - - Add the following sections to ```tempest.conf``` for testing using the devstack environment. - - ``` - [identity] - - auth_version = v3 - uri = http://127.0.0.1/identity_admin/v2.0/ - uri_v3 = http://127.0.0.1/identity_admin/v3/ - user_lockout_failure_attempts = 2 - user_locakout_duration = 5 - user_unique_last_password_count = 2 - admin_domain_scope = True - - [auth] - - use_dynamic_credentials = True - admin_project_name = admin - admin_username = admin - admin_password = secretadmin - admin_domain_name = Default - ``` - - Edit the variable values in the identity section to match your particular environment. - -5. Create ```etc/logging.conf``` in the Tempest root dir by making a copying ```logging.conf.sample```. - -6. Clone the monasca-api repo in a directory somewhere outside of the Tempest root dir. - -7. Install the monasca-api in your venv, which will also register - the Monasca Tempest Plugin as, monasca_tests. - - cd into the monasca-api root directory. Making sure that the tempest virtual env is still active, - run the following command. - - ``` - python setup.py install - ``` - -See the [OpenStack Tempest Plugin Interface](https://docs.openstack.org/tempest/latest/plugin.html), for more details on Tempest Plugins and the plugin registration process. - -# Running the Monasca Tempest Tests -The Monasca Tempest Tests can be run using a variety of methods including: -1. [Testr](https://wiki.openstack.org/wiki/Testr) -2. [Os-testr](https://docs.openstack.org/os-testr/latest/) -3. [PyCharm](https://www.jetbrains.com/pycharm/) -4. Tempest Scripts in Devstack - -## Run the tests from the CLI using testr - -[Testr](https://wiki.openstack.org/wiki/Testr) is a test runner that can be used to run the Tempest tests. - -1. Initializing testr is necessary to set up the .testrepository directory before using it for the first time. In the Tempest root dir: - - ``` - testr init - ``` - -2. Create a list of the Monasca Tempest Tests in a file: - - ``` - testr list-tests monasca_tempest_tests > monasca_tempest_tests - ``` - -3. Run the tests using testr: - - ``` - testr run --load-list=monasca_tempest_tests - ``` -You can also use testr to create a list of specific tests for your needs. - -## Run the tests using Tempest Run command - -``tempest run`` is a domain-specific command to be used as the primary -entry point for running Tempest tests. - -1. In the Tempest root dir: - - ``` - tempest run -r monasca_tempest_tests - ``` - -## Run the tests from the CLI using os-testr (no file necessary) -[Os-testr](https://docs.openstack.org/os-testr/latest/) is a test wrapper that can be used to run the Monasca Tempest tests. - -1. In the Tempest root dir: - - ``` - ostestr --serial --regex monasca_tempest_tests - ``` - ```--serial``` option is necessary here. Monasca tempest tests can't be run in parallel (default option in ostestr) because some tests depend on the same data and will randomly fail. - -## Running/Debugging the Monasca Tempest Tests in PyCharm - -You need to install `nose` for running tests from PyCharm: -``` -pip install nose -``` - -Assuming that you have already created a PyCharm project for the ```monasca-api``` do the following: - -1. In PyCharm, Edit Configurations and add a new Python tests configuration by selecting Python tests->Nosetests. -2. Name the test. For example TestVersions. -3. Set the path to the script with the tests to run. For example, ~/repos/monasca-api/monasca_tempest_tests/api/test_versions.py -4. Set the name of the Class to test. For example TestVersions. -5. Set the working directory to your local root Tempest repo. For example, ~/repos/tempest. -6. Select the Python interpreter for your project to be the same as the one virtualenv created above. For example, ~/repos/tempest/.venv -7. Run the tests. You should also be able to debug them. -8. Step and repeat for other tests. - -## Run the tests from the CLI using tempest scripts in devstack - -1. Create a virtualenv in devstack for running the tempest tests and activate it: - - ``` - cd /opt/stack/tempest - virtualenv .venv - source .venv/bin/activate - ``` -2. Install the tempest requirements in the virtualenv: - - ``` - pip install -r requirements.txt -r test-requirements.txt - ``` -3. If you want to test changes in monasca-api code on your local machine, change directory to monasca-api and install the latest monasca-api code: - - ``` - cd /vagrant_home/ - python setup.py install - ``` - Or if you want to use the current monasca api in devstack: - - ``` - cd /opt/stack/monasca-api - python setup.py install - ``` - -4. Run tempest tests: - - ``` - cd /opt/stack/tempest - testr init - ostestr --serial --regex monasca_tempest_tests - ``` - -# References -This section provides a few additional references that might be useful: -* [Tempest - The OpenStack Integration Test Suite](https://docs.openstack.org/tempest/latest/overview.html#quickstart) -* [Tempest Configuration Guide](https://github.com/openstack/tempest/blob/master/doc/source/configuration.rst#id1) -* [OpenStack Tempest Plugin Interface](https://docs.openstack.org/tempest/latest/plugin.html) - -In addition to the above references, another source of information is the following OpenStack projects: -* [Manila Tempest Tests](https://github.com/openstack/manila/tree/master/manila_tempest_tests) -* [Congress Tempest Tests](https://github.com/openstack/congress/tree/master/congress_tempest_tests). -In particular, the Manila Tempest Tests were used as a reference implementation to develop the Monasca Tempest Tests. There is also a wiki [HOWTO use tempest with manila](https://wiki.openstack.org/wiki/Manila/docs/HOWTO_use_tempest_with_manila) that might be useful for Monasca too. - -# Issues -* Update documentation for testing using Devstack when available. -* Consider changing from monasca_tempest_tests to monasca_api_tempest_tests. diff --git a/monasca_tempest_tests/__init__.py b/monasca_tempest_tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/monasca_tempest_tests/clients/__init__.py b/monasca_tempest_tests/clients/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/monasca_tempest_tests/clients/api.py b/monasca_tempest_tests/clients/api.py deleted file mode 100644 index a68979c..0000000 --- a/monasca_tempest_tests/clients/api.py +++ /dev/null @@ -1,23 +0,0 @@ -# (C) Copyright 2015,2017 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest import clients - -from monasca_tempest_tests.services import monasca_client - - -class Manager(clients.Manager): - def __init__(self, credentials=None): - super(Manager, self).__init__(credentials) - self.monasca_client = monasca_client.MonascaClient(self.auth_provider) diff --git a/monasca_tempest_tests/clients/event_api.py b/monasca_tempest_tests/clients/event_api.py deleted file mode 100644 index c151fc9..0000000 --- a/monasca_tempest_tests/clients/event_api.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2019 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest import clients - -from monasca_tempest_tests.services import elasticsearch_client -from monasca_tempest_tests.services import events_api_client - - -class Manager(clients.Manager): - def __init__(self, credentials=None): - super(Manager, self).__init__(credentials) - - self.events_api_client = events_api_client.EventApiClient( - self.auth_provider, - 'events', - None - ) - - self.events_search_client = elasticsearch_client.ElasticsearchClient( - self.auth_provider, - 'events-search', - None - ) diff --git a/monasca_tempest_tests/clients/log_api.py b/monasca_tempest_tests/clients/log_api.py deleted file mode 100644 index 0940ad3..0000000 --- a/monasca_tempest_tests/clients/log_api.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2015-2016 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest import clients -from tempest import config - -from monasca_tempest_tests.services import elasticsearch_client -from monasca_tempest_tests.services import log_api_v3_client - -CONF = config.CONF - - -class Manager(clients.Manager): - def __init__(self, credentials=None): - super(Manager, self).__init__(credentials) - - self.log_api_client = log_api_v3_client.LogApiV3Client( - self.auth_provider, - CONF.monitoring.catalog_type_logs, - None - ) - - self.log_search_client = elasticsearch_client.ElasticsearchClient( - self.auth_provider, - CONF.monitoring.catalog_type_log_query, - None - ) diff --git a/monasca_tempest_tests/config.py b/monasca_tempest_tests/config.py deleted file mode 100644 index 70f00f8..0000000 --- a/monasca_tempest_tests/config.py +++ /dev/null @@ -1,79 +0,0 @@ -# (C) Copyright 2015 Hewlett Packard Enterprise Development Company LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config import cfg - - -service_available_group = cfg.OptGroup(name='service_available', - title='Available OpenStack Services') -ServiceAvailableGroup = [ - cfg.BoolOpt('logs', - default=True, - help=('Whether or not Monasca-Log-Api ' - 'is expected to be available')), - cfg.BoolOpt('logs-search', - default=True, - help=('Whether or not Monasca-Log-Api search engine ' - '(ElasticSearch) is expected to be available')), - cfg.BoolOpt("monasca", - default=True, - help="Whether or not Monasca is expected to be " - "available")] - -monitoring_group = cfg.OptGroup(name="monitoring", - title="Monitoring Service Options") - -MonitoringGroup = [ - cfg.StrOpt("region", - default="", - help="The monitoring region name to use. If empty, the value " - "of identity.region is used instead. If no such region " - "is found in the service catalog, the first found one is " - "used."), - cfg.StrOpt("catalog_type", - default="monitoring", - help="Keystone catalog service type of the monitoring service."), - cfg.StrOpt('catalog_type_logs', - default='logs', - help='Keystone catalog service type of the logging service.'), - cfg.StrOpt('catalog_type_log_query', - default='logs-search', - help='Keystone catalog service type of the log query service.'), - cfg.StrOpt('log_query_message_field', - default='message', - help='The field under which the log message is stored.'), - cfg.StrOpt('log_uri_path', - default='/logs', - help='Path used to form Log API URI.'), - cfg.ListOpt('log_project_id_path', - default=['_source', 'tenant'], - help='Series of keys to access the Project ID field in a persisted' - 'log file.'), - cfg.StrOpt('endpoint_type', - default='publicURL', - choices=['public', 'admin', 'internal', - 'publicURL', 'adminURL', 'internalURL'], - help="The endpoint type to use for the monitoring service."), - cfg.StrOpt('api_version', - default='v2.0', - help='monasca-log-api API version'), - cfg.StrOpt('kibana_version', - default='7.3.0', - help='Kibana version'), - cfg.IntOpt('log_api_max_log_size', - default=1024 * 1024, - help=('Refers to payload/envelope size. This should be set ' - 'to the same value as "[service]max_log_size" in the ' - 'monasca-log-api configuration')) -] diff --git a/monasca_tempest_tests/contrib/gate_hook.sh b/monasca_tempest_tests/contrib/gate_hook.sh deleted file mode 100755 index e69de29..0000000 diff --git a/monasca_tempest_tests/contrib/post_test_hook.sh b/monasca_tempest_tests/contrib/post_test_hook.sh deleted file mode 100755 index 533df93..0000000 --- a/monasca_tempest_tests/contrib/post_test_hook.sh +++ /dev/null @@ -1,102 +0,0 @@ -# -# (C) Copyright 2015 Hewlett Packard Enterprise Development Company LP -# (C) Copyright 2017 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -#    http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -sleep 6 - -function load_devstack_utilities { - source $BASE/new/devstack/stackrc - source $BASE/new/devstack/functions - source $BASE/new/devstack/openrc admin admin -} - -function setup_monasca_api { - - local constraints="-c /opt/stack/new/requirements/upper-constraints.txt" - - pushd $TEMPEST_DIR - sudo -EH pip install $constraints -r requirements.txt -r test-requirements.txt - popd; - - pushd $MONASCA_API_DIR - sudo -EH pip install $constraints -r requirements.txt -r test-requirements.txt - sudo -EH python setup.py install - popd; -} - -function set_tempest_conf { - - local conf_file=$TEMPEST_DIR/etc/tempest.conf - pushd $TEMPEST_DIR - oslo-config-generator \ - --config-file tempest/cmd/config-generator.tempest.conf \ - --output-file $conf_file - popd - - cp -f $DEST/tempest/etc/logging.conf.sample $DEST/tempest/etc/logging.conf - - # set identity section - iniset $conf_file identity admin_domain_scope True - iniset $conf_file identity user_unique_last_password_count 2 - iniset $conf_file identity user_locakout_duration 5 - iniset $conf_file identity user_lockout_failure_attempts 2 - iniset $conf_file identity uri $OS_AUTH_URL/v2.0 - iniset $conf_file identity uri_v3 $OS_AUTH_URL/v3 - iniset $conf_file identity auth_version v$OS_IDENTITY_API_VERSION - # set auth section - iniset $conf_file auth use_dynamic_credentials True - iniset $conf_file auth admin_username $OS_USERNAME - iniset $conf_file auth admin_password $OS_PASSWORD - iniset $conf_file auth admin_domain_name $OS_PROJECT_DOMAIN_ID - iniset $conf_file auth admin_project_name $OS_PROJECT_NAME - -} - -function function_exists { - declare -f -F $1 > /dev/null -} - -if ! function_exists echo_summary; then - function echo_summary { - echo $@ - } -fi - -XTRACE=$(set +o | grep xtrace) -set -o xtrace - -echo_summary "monasca's post_test_hook.sh was called..." -(set -o posix; set) - -# save ref to monasca-api dir -export MONASCA_API_DIR="$BASE/new/monasca-api" -export TEMPEST_DIR="$BASE/new/tempest" - -sudo chown -R $USER:stack $MONASCA_API_DIR -sudo chown -R $USER:stack $TEMPEST_DIR - -load_devstack_utilities -setup_monasca_api -set_tempest_conf - -(cd $TEMPEST_DIR; testr init) -(cd $TEMPEST_DIR; testr list-tests monasca_tempest_tests > monasca_tempest_tests) -(cd $TEMPEST_DIR; cat monasca_tempest_tests) -(cd $TEMPEST_DIR; cat monasca_tempest_tests | grep gate > monasca_tempest_tests_gate) -(cd $TEMPEST_DIR; testr run --subunit --load-list=monasca_tempest_tests_gate | subunit-trace --fails) - - diff --git a/monasca_tempest_tests/plugin.py b/monasca_tempest_tests/plugin.py deleted file mode 100644 index d911393..0000000 --- a/monasca_tempest_tests/plugin.py +++ /dev/null @@ -1,43 +0,0 @@ -# (C) Copyright 2015 Hewlett Packard Enterprise Development Company LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os - -from tempest import config -from tempest.test_discover import plugins - -from monasca_tempest_tests import config as config_monitoring - - -class MonascaTempestPlugin(plugins.TempestPlugin): - def load_tests(self): - base_path = os.path.split(os.path.dirname( - os.path.abspath(__file__)))[0] - test_dir = "monasca_tempest_tests/tests" - full_test_dir = os.path.join(base_path, test_dir) - return full_test_dir, base_path - - def register_opts(self, conf): - config.register_opt_group( - conf, - config_monitoring.service_available_group, - config_monitoring.ServiceAvailableGroup - ) - config.register_opt_group(conf, - config_monitoring.monitoring_group, - config_monitoring.MonitoringGroup) - - def get_opt_lists(self): - return [(config_monitoring.monitoring_group.name, - config_monitoring.MonitoringGroup)] diff --git a/monasca_tempest_tests/services/__init__.py b/monasca_tempest_tests/services/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/monasca_tempest_tests/services/elasticsearch_client.py b/monasca_tempest_tests/services/elasticsearch_client.py deleted file mode 100644 index f4b208d..0000000 --- a/monasca_tempest_tests/services/elasticsearch_client.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright 2015 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config import cfg -from oslo_serialization import jsonutils as json -from tempest.lib.common import rest_client - -CONF = cfg.CONF - - -header = {'kbn-version': CONF.monitoring.kibana_version, 'kbn-xsrf': 'kibana'} - - -class ElasticsearchClient(rest_client.RestClient): - uri_prefix = "/elasticsearch" - - def __init__(self, auth_provider, service, region): - super(ElasticsearchClient, self).__init__( - auth_provider, - service, - region, - ) - - @staticmethod - def deserialize(body): - body = body.decode('utf-8') - return json.loads(body.replace("\n", "")) - - @staticmethod - def serialize(body): - return json.dumps(body) - - def get_metadata(self): - uri = "/" - - response, body = self.get(self._uri(uri)) - self.expected_success(200, response.status) - - if body: - body = self.deserialize(body) - return response, body - - def count_search_messages(self, message, headers): - return len(self.search_messages(message, headers)) - - def search_messages(self, message, headers=None): - uri = '_msearch' - field = CONF.monitoring.log_query_message_field - body = ('\n' - '{"index" : "*", "search_type" : "dfs_query_then_fetch"}\n' - '{"query" : {"match" : {"' + field + '":"' + message + '"}}}' - '\n') - response, body = self.post(self._uri(uri), body, headers) - self.expected_success(200, response.status) - body = self.deserialize(body) - return body['responses'][0].get('hits', {}).get('hits', []) - - def search_event_by_event_type(self, event_type): - uri = '_msearch' - body = u""" - {"index" : "*", "search_type" : "dfs_query_then_fetch"} - {"query" : {"match" : {"event_type":" """ + event_type + """ "}}}\n""" - response, body = self.post(self._uri(uri), body, header) - self.expected_success(200, response.status) - body = self.deserialize(body) - return body['responses'][0].get('hits', {}).get('hits', []) - - def search_event(self, event): - uri = '_msearch' - event = json.dumps(event) - body = u""" - {"index" : "*", "search_type" : "dfs_query_then_fetch"} - {"query" : {"match" : {"event":" """ + event + """ "}}}\n""" - response, body = self.post(self._uri(uri), body, header) - self.expected_success(200, response.status) - body = self.deserialize(body) - return body['responses'][0].get('hits', {}).get('hits', []) - - def _uri(self, url): - return '{}/{}'.format(self.uri_prefix, url) diff --git a/monasca_tempest_tests/services/events_api_client.py b/monasca_tempest_tests/services/events_api_client.py deleted file mode 100644 index cd9ce2d..0000000 --- a/monasca_tempest_tests/services/events_api_client.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2019 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json - -from tempest.lib.common import rest_client - - -class EventApiClient(rest_client.RestClient): - - _uri = '/v1.0/events' - - def __init__(self, auth_provider, service, region): - super(EventApiClient, self).__init__( - auth_provider, - service, - region - ) - - def send_events(self, events, headers=None): - msg = json.dumps(events) - resp, body = self.post(self._uri, body=msg, headers=headers) - return resp, body diff --git a/monasca_tempest_tests/services/log_api_v3_client.py b/monasca_tempest_tests/services/log_api_v3_client.py deleted file mode 100644 index 234b88a..0000000 --- a/monasca_tempest_tests/services/log_api_v3_client.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2015 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from urllib.parse import urlencode - -from oslo_serialization import jsonutils as json -from tempest import config -from tempest.lib.common import rest_client - -CONF = config.CONF - - -class LogApiV3Client(rest_client.RestClient): - - def __init__(self, auth_provider, service, region): - super(LogApiV3Client, self).__init__( - auth_provider, - service, - region - ) - - def get_version(self): - resp, response_body = self.send_request('GET', '/') - return resp, response_body - - def send_single_log(self, log, headers=None, fields=None): - default_headers = { - 'X-Tenant-Id': 'b4265b0a48ae4fd3bdcee0ad8c2b6012', - 'X-Roles': 'admin', - } - default_headers.update(headers) - msg = json.dumps(log) - uri = CONF.monitoring.log_uri_path - - if fields: - uri += '?' + urlencode(fields) - - resp, body = self.post(uri, msg, default_headers) - - return resp, body - - def custom_request(self, method, headers=None, body=None): - self.request(method=method, url=CONF.monitoring.log_uri_path, headers=headers, body=body) diff --git a/monasca_tempest_tests/services/monasca_client.py b/monasca_tempest_tests/services/monasca_client.py deleted file mode 100644 index 366f5cb..0000000 --- a/monasca_tempest_tests/services/monasca_client.py +++ /dev/null @@ -1,346 +0,0 @@ -# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -from oslo_serialization import jsonutils as json - -from tempest import config -from tempest.lib.common import rest_client - -CONF = config.CONF - - -class MonascaClient(rest_client.RestClient): - - def __init__(self, auth_provider): - super(MonascaClient, self).__init__( - auth_provider, - CONF.monitoring.catalog_type, - CONF.monitoring.region or CONF.identity.region, - endpoint_type=CONF.monitoring.endpoint_type) - - def get_version(self): - resp, response_body = self.get('') - return resp, response_body - - def create_metrics(self, metrics, tenant_id=None): - uri = 'metrics' - if tenant_id: - uri = uri + '?tenant_id=%s' % tenant_id - request_body = json.dumps(metrics) - resp, response_body = self.post(uri, request_body) - return resp, response_body - - def list_metrics(self, query_params=None): - uri = 'metrics' - if query_params is not None: - uri = uri + query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def list_metrics_names(self, query_params=None): - uri = 'metrics/names' - if query_params is not None: - uri = uri + query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def list_dimension_names(self, query_params=None): - uri = 'metrics/dimensions/names' - if query_params is not None: - uri = uri + query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def list_dimension_values(self, query_params=None): - uri = 'metrics/dimensions/names/values' - if query_params is not None: - uri = uri + query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def list_measurements(self, query_params=None): - uri = 'metrics/measurements' - if query_params is not None: - uri = uri + query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def list_statistics(self, query_params=None): - uri = 'metrics/statistics' - if query_params is not None: - uri = uri + query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def create_notifications(self, notification): - uri = 'notification-methods' - request_body = json.dumps(notification) - resp, response_body = self.post(uri, request_body) - return resp, json.loads(response_body) - - def create_notification_method(self, - name=None, - type=None, - address=None, - period=None): - uri = 'notification-methods' - request_body = {} - if name is not None: - request_body['name'] = name - if type is not None: - request_body['type'] = type - if address is not None: - request_body['address'] = address - if period is not None: - request_body['period'] = period - resp, response_body = self.post(uri, json.dumps(request_body)) - return resp, json.loads(response_body) - - def delete_notification_method(self, id): - uri = 'notification-methods/' + id - resp, response_body = self.delete(uri) - return resp, response_body - - def get_notification_method(self, id): - uri = 'notification-methods/' + id - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def list_notification_methods(self, query_params=None): - uri = 'notification-methods' - if query_params is not None: - uri = uri + query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def update_notification_method(self, id, name, type, address, period=None): - uri = 'notification-methods/' + id - request_body = {} - request_body['name'] = name - request_body['type'] = type - request_body['address'] = address - if period is not None: - request_body['period'] = period - resp, response_body = self.put(uri, json.dumps(request_body)) - return resp, json.loads(response_body) - - def patch_notification_method(self, id, - name=None, type=None, - address=None, period=None): - uri = 'notification-methods/' + id - request_body = {} - if name is not None: - request_body['name'] = name - if type is not None: - request_body['type'] = type - if address is not None: - request_body['address'] = address - if period is not None: - request_body['period'] = period - resp, response_body = self.patch(uri, json.dumps(request_body)) - return resp, json.loads(response_body) - - def list_notification_method_types(self, query_params=None): - uri = 'notification-methods/types' - if query_params is not None: - uri = uri + query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def create_alarm_definitions(self, alarm_definitions): - uri = 'alarm-definitions' - request_body = json.dumps(alarm_definitions) - resp, response_body = self.post(uri, request_body) - return resp, json.loads(response_body) - - def list_alarm_definitions(self, query_params=None): - uri = 'alarm-definitions' - if query_params is not None: - uri = uri + query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def get_alarm_definition(self, id): - uri = 'alarm-definitions/' + id - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def delete_alarm_definition(self, id): - uri = 'alarm-definitions/' + id - resp, response_body = self.delete(uri) - return resp, response_body - - def update_alarm_definition(self, id, name, expression, description, - actions_enabled, match_by, - severity, alarm_actions, - ok_actions, undetermined_actions, - **kwargs): - uri = 'alarm-definitions/' + id - request_body = {} - request_body['name'] = name - request_body['expression'] = expression - request_body['description'] = description - request_body['actions_enabled'] = actions_enabled - request_body['match_by'] = match_by - request_body['severity'] = severity - request_body['alarm_actions'] = alarm_actions - request_body['ok_actions'] = ok_actions - request_body['undetermined_actions'] = undetermined_actions - - for key, value in kwargs.items(): - request_body[key] = value - - resp, response_body = self.put(uri, json.dumps(request_body)) - return resp, json.loads(response_body) - - def patch_alarm_definition(self, - id, - name=None, - description=None, - expression=None, - actions_enabled=None, - match_by=None, - severity=None, - alarm_actions=None, - ok_actions=None, - undetermined_actions=None, - **kwargs): - uri = 'alarm-definitions/' + id - request_body = {} - if name is not None: - request_body['name'] = name - if description is not None: - request_body['description'] = description - if expression is not None: - request_body['expression'] = expression - if actions_enabled is not None: - request_body['actions_enabled'] = actions_enabled - if match_by is not None: - request_body['match_by'] = match_by - if severity is not None: - request_body['severity'] = severity - if alarm_actions is not None: - request_body['alarm_actions'] = alarm_actions - if ok_actions is not None: - request_body['ok_actions'] = ok_actions - if undetermined_actions is not None: - request_body['undetermined_actions'] = undetermined_actions - - for key, value in kwargs.items(): - request_body[key] = value - - resp, response_body = self.patch(uri, json.dumps(request_body)) - return resp, json.loads(response_body) - - def list_alarms(self, query_params=None): - uri = 'alarms' - if query_params is not None: - uri = uri + query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def get_alarm(self, id): - uri = 'alarms/' + id - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def delete_alarm(self, id): - uri = 'alarms/' + id - resp, response_body = self.delete(uri) - return resp, response_body - - def update_alarm(self, id, state, lifecycle_state, link, **kwargs): - uri = 'alarms/' + id - request_body = {} - request_body['state'] = state - request_body['lifecycle_state'] = lifecycle_state - request_body['link'] = link - - for key, value in kwargs.items(): - request_body[key] = value - - resp, response_body = self.put(uri, json.dumps(request_body)) - return resp, json.loads(response_body) - - def patch_alarm(self, id, state=None, lifecycle_state=None, link=None, - **kwargs): - uri = 'alarms/' + id - request_body = {} - if state is not None: - request_body['state'] = state - if lifecycle_state is not None: - request_body['lifecycle_state'] = lifecycle_state - if link is not None: - request_body['link'] = link - - for key, value in kwargs.items(): - request_body[key] = value - - resp, response_body = self.patch(uri, json.dumps(request_body)) - return resp, json.loads(response_body) - - def count_alarms(self, query_params=None): - uri = 'alarms/count' - if query_params is not None: - uri += query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def list_alarms_state_history(self, query_params=None): - uri = 'alarms/state-history' - if query_params is not None: - uri = uri + query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - def list_alarm_state_history(self, id, query_params=None): - uri = 'alarms/' + id + '/state-history' - if query_params is not None: - uri = uri + query_params - resp, response_body = self.get(uri) - return resp, json.loads(response_body) - - # For Negative Tests - def update_alarm_definition_with_no_ok_actions(self, id, name, - expression, description, - actions_enabled, match_by, - severity, alarm_actions, - undetermined_actions, - **kwargs): - uri = 'alarm-definitions/' + id - request_body = {} - request_body['name'] = name - request_body['expression'] = expression - request_body['description'] = description - request_body['actions_enabled'] = actions_enabled - request_body['match_by'] = match_by - request_body['severity'] = severity - request_body['alarm_actions'] = alarm_actions - request_body['undetermined_actions'] = undetermined_actions - - for key, value in kwargs.items(): - request_body[key] = value - - resp, response_body = self.put(uri, json.dumps(request_body)) - return resp, json.loads(response_body) - - def update_notification_method_with_no_address(self, id, name, type, - period=None): - uri = 'notification-methods/' + id - request_body = {} - request_body['name'] = name - request_body['type'] = type - if period is not None: - request_body['period'] = period - resp, response_body = self.put(uri, json.dumps(request_body)) - return resp, json.loads(response_body) diff --git a/monasca_tempest_tests/tests/__init__.py b/monasca_tempest_tests/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/monasca_tempest_tests/tests/api/__init__.py b/monasca_tempest_tests/tests/api/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/monasca_tempest_tests/tests/api/base.py b/monasca_tempest_tests/tests/api/base.py deleted file mode 100644 index 362d141..0000000 --- a/monasca_tempest_tests/tests/api/base.py +++ /dev/null @@ -1,100 +0,0 @@ -# (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import urllib.parse as urlparse - -from tempest.common import credentials_factory -from tempest import config -from tempest.lib import exceptions -import tempest.test - -from monasca_tempest_tests.clients import api as clients - -CONF = config.CONF - - -class BaseMonascaTest(tempest.test.BaseTestCase): - """Base test case class for all Monasca API tests.""" - - @classmethod - def skip_checks(cls): - super(BaseMonascaTest, cls).skip_checks() - if not CONF.service_available.monasca: - raise cls.skipException("Monasca support is required") - - @classmethod - def resource_setup(cls): - super(BaseMonascaTest, cls).resource_setup() - auth_version = CONF.identity.auth_version - cls.cred_provider = credentials_factory.get_credentials_provider( - cls.__name__, - force_tenant_isolation=True, - identity_version=auth_version) - credentials = cls.cred_provider.get_creds_by_roles( - ['monasca-user', 'monasca-read-only-user', 'admin']).credentials - cls.os = clients.Manager(credentials=credentials) - cls.monasca_client = cls.os.monasca_client - cls.projects_client = cls.os.projects_client - - @staticmethod - def cleanup_resources(method, list_of_ids): - for resource_id in list_of_ids: - try: - method(resource_id) - except exceptions.NotFound: - pass - - @classmethod - def resource_cleanup(cls): - super(BaseMonascaTest, cls).resource_cleanup() - resp, response_body = cls.monasca_client.list_alarm_definitions() - if resp.status == 200: - if 'elements' in response_body: - elements = response_body['elements'] - for element in elements: - id = element['id'] - cls.monasca_client.delete_alarm_definition(id) - - resp, response_body = cls.monasca_client.list_notification_methods() - if resp.status == 200: - if 'elements' in response_body: - elements = response_body['elements'] - for element in elements: - id = element['id'] - cls.monasca_client.delete_notification_method(id) - - resp, response_body = cls.monasca_client.list_alarms() - if resp.status == 200: - if 'elements' in response_body: - elements = response_body['elements'] - for element in elements: - id = element['id'] - cls.monasca_client.delete_alarm(id) - cls.cred_provider.clear_creds() - - def _get_offset(self, response_body): - next_link = None - self_link = None - for link in response_body['links']: - if link['rel'] == 'next': - next_link = link['href'] - if link['rel'] == 'self': - self_link = link['href'] - if not next_link: - query_parms = urlparse.parse_qs(urlparse.urlparse(self_link).query) - self.fail("No next link returned with query parameters: {}".format(query_parms)) - query_params = urlparse.parse_qs(urlparse.urlparse(next_link).query) - if 'offset' not in query_params: - self.fail("No offset in next link: {}".format(next_link)) - return query_params['offset'][0] diff --git a/monasca_tempest_tests/tests/api/constants.py b/monasca_tempest_tests/tests/api/constants.py deleted file mode 100644 index 9146d78..0000000 --- a/monasca_tempest_tests/tests/api/constants.py +++ /dev/null @@ -1,47 +0,0 @@ -# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development Company LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -MAX_RETRIES = 60 -RETRY_WAIT_SECS = 1 -ONE_MINUTE_TIME_OUT = 60 - -ALARM_DEFINITION_CREATION_WAIT = 3 - -MAX_METRIC_NAME_LENGTH = 255 -MAX_DIMENSION_KEY_LENGTH = 255 -MAX_DIMENSION_VALUE_LENGTH = 255 -INVALID_DIMENSION_CHARS = "<>={},\"\\;&" -INVALID_NAME_CHARS = INVALID_DIMENSION_CHARS + "()" - -MAX_ALARM_DEFINITION_NAME_LENGTH = 255 -MAX_ALARM_DEFINITION_DESCRIPTION_LENGTH = 255 -MAX_ALARM_DEFINITION_ACTIONS_LENGTH = 50 - -MAX_NOTIFICATION_METHOD_NAME_LENGTH = 250 -MAX_NOTIFICATION_METHOD_TYPE_LENGTH = 100 -MAX_NOTIFICATION_METHOD_ADDRESS_LENGTH = 512 -INVALID_CHARS_NOTIFICATION = "<>={}(),\"\\;&" - -MAX_LIST_MEASUREMENTS_NAME_LENGTH = 255 - -MAX_LIST_STATISTICS_NAME_LENGTH = 255 - -MAX_ALARM_LIFECYCLE_STATE_LENGTH = 50 -MAX_ALARM_METRIC_NAME_LENGTH = 255 -MAX_ALARM_METRIC_DIMENSIONS_KEY_LENGTH = 255 -MAX_ALARM_METRIC_DIMENSIONS_VALUE_LENGTH = 255 -MAX_ALARM_LINK_LENGTH = 512 - -MAX_VALUE_META_NAME_LENGTH = 255 -MAX_VALUE_META_TOTAL_LENGTH = 2048 diff --git a/monasca_tempest_tests/tests/api/helpers.py b/monasca_tempest_tests/tests/api/helpers.py deleted file mode 100644 index f4f8966..0000000 --- a/monasca_tempest_tests/tests/api/helpers.py +++ /dev/null @@ -1,179 +0,0 @@ -# (C) Copyright 2015 Hewlett Packard Enterprise Development Company LP -# (C) Copyright 2017 SUSE LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -import datetime -import time -import urllib.parse as urlparse - -from tempest.lib.common.utils import data_utils - -NUM_ALARM_DEFINITIONS = 2 -NUM_MEASUREMENTS = 100 - - -def create_metric(name='name-1', - dimensions={ - 'key-1': 'value-1', - 'key-2': 'value-2' - }, - timestamp=None, - value=0.0, - value_meta={ - 'key-1': 'value-1', - 'key-2': 'value-2' - }, - ): - metric = {} - if name is not None: - metric['name'] = name - if dimensions is not None: - metric['dimensions'] = dimensions - if timestamp is not None: - metric['timestamp'] = timestamp - else: - metric['timestamp'] = int(time.time() * 1000) - if value is not None: - metric['value'] = value - if value_meta is not None: - metric['value_meta'] = value_meta - return metric - - -def create_notification(name=data_utils.rand_name('notification-'), - type='EMAIL', - address='john.doe@domain.com', - period=0): - notification = {} - if name is not None: - notification['name'] = name - if type is not None: - notification['type'] = type - if address is not None: - notification['address'] = address - if period is not None: - notification['period'] = period - return notification - - -def create_alarm_definition(name=None, - description=None, - expression=None, - match_by=None, - severity=None, - alarm_actions=None, - ok_actions=None, - undetermined_actions=None): - alarm_definition = {} - if name is not None: - alarm_definition['name'] = name - if description is not None: - alarm_definition['description'] = description - if expression is not None: - alarm_definition['expression'] = expression - if match_by is not None: - alarm_definition['match_by'] = match_by - if severity is not None: - alarm_definition['severity'] = severity - if alarm_actions is not None: - alarm_definition['alarm_actions'] = alarm_actions - if ok_actions is not None: - alarm_definition['ok_actions'] = ok_actions - if undetermined_actions is not None: - alarm_definition['undetermined_actions'] = undetermined_actions - return alarm_definition - - -def delete_alarm_definitions(monasca_client): - # Delete alarm definitions - resp, response_body = monasca_client.list_alarm_definitions() - elements = response_body['elements'] - if elements: - for element in elements: - alarm_def_id = element['id'] - monasca_client.delete_alarm_definition(alarm_def_id) - - -def timestamp_to_iso(timestamp): - time_utc = datetime.datetime.utcfromtimestamp(timestamp / 1000.0) - time_iso_base = time_utc.strftime("%Y-%m-%dT%H:%M:%S") - time_iso_base += 'Z' - return time_iso_base - - -def timestamp_to_iso_millis(timestamp): - time_utc = datetime.datetime.utcfromtimestamp(timestamp / 1000.0) - time_iso_base = time_utc.strftime("%Y-%m-%dT%H:%M:%S") - time_iso_microsecond = time_utc.strftime(".%f") - time_iso_millisecond = time_iso_base + time_iso_microsecond[0:4] + 'Z' - return time_iso_millisecond - - -def get_query_param(uri, query_param_name): - query_param_val = None - parsed_uri = urlparse.urlparse(uri) - for query_param in parsed_uri.query.split('&'): - parsed_query_name, parsed_query_val = query_param.split('=', 1) - if query_param_name == parsed_query_name: - query_param_val = parsed_query_val - return query_param_val - - -def get_expected_elements_inner_offset_limit(all_elements, offset, limit, inner_key): - expected_elements = [] - total_statistics = 0 - - if offset is None: - offset_id = None - offset_time = "" - passed_offset = True - else: - offset_tuple = offset.split('_') - offset_id = offset_tuple[0] if len(offset_tuple) > 1 else u'0' - offset_time = offset_tuple[1] if len(offset_tuple) > 1 else offset_tuple[0] - passed_offset = False - - for element in all_elements: - element_id = element['id'] - if (not passed_offset) and element_id != offset_id: - continue - next_element = None - - for value in element[inner_key]: - if passed_offset or (element_id == offset_id and value[0] > offset_time): - if not passed_offset: - passed_offset = True - if not next_element: - next_element = element.copy() - next_element[inner_key] = [value] - else: - next_element[inner_key].append(value) - total_statistics += 1 - if total_statistics >= limit: - break - - if next_element: - expected_elements.append(next_element) - - if total_statistics >= limit: - break - - if element_id == offset_id: - passed_offset = True - - # if index is used in the element id, reset to start at zero - if expected_elements and expected_elements[0]['id'].isdigit(): - for i in range(len(expected_elements)): - expected_elements[i]['id'] = str(i) - - return expected_elements diff --git a/monasca_tempest_tests/tests/api/test_alarm_definitions.py b/monasca_tempest_tests/tests/api/test_alarm_definitions.py deleted file mode 100644 index f5d03ff..0000000 --- a/monasca_tempest_tests/tests/api/test_alarm_definitions.py +++ /dev/null @@ -1,1128 +0,0 @@ -# -*- coding: utf-8 -*- -# (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time -import urllib.parse as urlparse - -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators -from tempest.lib import exceptions - -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import constants -from monasca_tempest_tests.tests.api import helpers - - -NUM_ALARM_DEFINITIONS = 2 - - -class TestAlarmDefinitions(base.BaseMonascaTest): - - @decorators.attr(type=["gate", "smoke"]) - def test_create_alarm_definition(self): - # Create an alarm definition - name = data_utils.rand_name('alarm_definition') - expression = "max(cpu.system_perc) > 0" - alarm_definition = helpers.create_alarm_definition( - name=name, description="description", expression=expression, - match_by=['hostname'], severity="MEDIUM") - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition) - self._verify_create_alarm_definitions(resp, response_body, - alarm_definition) - - @decorators.attr(type="gate") - def test_create_alarm_definition_with_notification(self): - notification_name = data_utils.rand_name('notification-') - notification_type = 'EMAIL' - notification_address = 'root@localhost' - resp, response_body = self.monasca_client.create_notification_method( - name=notification_name, type=notification_type, - address=notification_address) - notification_id = self._verify_create_notification_method( - resp, response_body, notification_name, notification_type, - notification_address) - - # Create an alarm definition - alarm_def_name = data_utils.rand_name('monitoring_alarm_definition') - expression = "mem_total_mb > 0" - alarm_definition = helpers.create_alarm_definition( - name=alarm_def_name, - expression=expression, - alarm_actions=[notification_id], - ok_actions=[notification_id], - undetermined_actions=[notification_id], - severity="LOW") - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition) - self._verify_create_alarm_definitions(resp, response_body, - alarm_definition) - self.assertEqual(notification_id, response_body['ok_actions'][0]) - self.assertEqual(notification_id, response_body['alarm_actions'][0]) - self.assertEqual(notification_id, - response_body['undetermined_actions'][0]) - - self._delete_notification(notification_id) - - @decorators.attr(type="gate") - def test_create_alarm_definition_with_multiple_notifications(self): - notification_name1 = data_utils.rand_name('notification-') - notification_type1 = 'EMAIL' - address1 = 'root@localhost' - - notification_name2 = data_utils.rand_name('notification-') - notification_type2 = 'PAGERDUTY' - address2 = 'http://localhost.com' - - resp, response_body = self.monasca_client.create_notification_method( - notification_name1, type=notification_type1, address=address1) - notification_id1 = self._verify_create_notification_method( - resp, response_body, notification_name1, notification_type1, - address1) - - resp, response_body = self.monasca_client.create_notification_method( - notification_name2, type=notification_type2, address=address2) - notification_id2 = self._verify_create_notification_method( - resp, response_body, notification_name2, notification_type2, - address2) - - # Create an alarm definition - alarm_def_name = data_utils.rand_name('monitoring_alarm_definition') - alarm_definition = helpers.create_alarm_definition( - name=alarm_def_name, - expression="mem_total_mb > 0", - alarm_actions=[notification_id1, notification_id2], - ok_actions=[notification_id1, notification_id2], - undetermined_actions=[notification_id1, notification_id2], - severity="LOW") - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition) - self._verify_create_alarm_definitions(resp, response_body, - alarm_definition) - - self._delete_notification(notification_id1) - self._delete_notification(notification_id2) - - @decorators.attr(type="gate") - def test_create_alarm_definition_with_url_in_expression(self): - notification_name = data_utils.rand_name('notification-') - notification_type = 'EMAIL' - address = 'root@localhost' - resp, response_body = self.monasca_client.create_notification_method( - notification_name, type=notification_type, address=address) - notification_id = self._verify_create_notification_method( - resp, response_body, notification_name, notification_type, address) - - # Create an alarm definition - alarm_def_name = data_utils.rand_name('monitoring_alarm_definition') - alarm_definition = helpers.create_alarm_definition( - name=alarm_def_name, - expression="avg(mem_total_mb{url=https://www.google.com}) gt 0", - alarm_actions=[notification_id], - ok_actions=[notification_id], - undetermined_actions=[notification_id], - severity="LOW") - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition) - self._verify_create_alarm_definitions(resp, response_body, - alarm_definition) - self._delete_notification(notification_id) - - @decorators.attr(type='gate') - def test_create_deterministic_alarm_definition(self): - name = data_utils.rand_name('log.error') - expression = "count(log.error{},deterministic) > 0" - - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression, - match_by=['hostname'], - severity="MEDIUM" - ) - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition - ) - self._verify_create_alarm_definitions(resp, - response_body, - alarm_definition, - deterministic=True) - - @decorators.attr(type='gate') - def test_create_non_deterministic_alarm_definition_compound_mixed_expr(self): - name = data_utils.rand_name('log.error.and.disk.used_perc') - expression = ('max(disk.used_perc{hostname=node_1}) > 99.0 AND ' - 'count(log.error{hostname=node_1},deterministic) > 0') - - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression, - match_by=['hostname'], - severity="MEDIUM" - ) - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition - ) - self._verify_create_alarm_definitions(resp, - response_body, - alarm_definition, - deterministic=False) - - @decorators.attr(type='gate') - def test_create_deterministic_alarm_definition_compound_expr(self): - name = data_utils.rand_name('log.error.nodes_1_2') - expression = ('count(log.error{hostname=node_2},deterministic) > 0 ' - 'AND ' - 'count(log.error{hostname=node_1},deterministic) > 0') - - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression, - match_by=['hostname'], - severity="MEDIUM" - ) - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition - ) - self._verify_create_alarm_definitions(resp, - response_body, - alarm_definition, - deterministic=True) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_alarm_definition_with_special_chars_in_expression(self): - notification_name = data_utils.rand_name('notification-') - notification_type = 'EMAIL' - address = 'root@localhost' - - resp, response_body = self.monasca_client.create_notification_method( - notification_name, type=notification_type, address=address) - notification_id = self._verify_create_notification_method( - resp, response_body, notification_name, notification_type, address) - - # Create an alarm definition - alarm_def_name = data_utils.rand_name('monitoring_alarm') - alarm_definition = helpers.create_alarm_definition( - name=alarm_def_name, - expression="avg(mem_total_mb{dev=\\usr\local\bin}) gt 0", # noqa - alarm_actions=[notification_id], - ok_actions=[notification_id], - undetermined_actions=[notification_id], - severity="LOW") - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_alarm_definitions, - alarm_definition) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_alarm_definition_with_name_exceeds_max_length(self): - long_name = "x" * (constants.MAX_ALARM_DEFINITION_NAME_LENGTH + 1) - expression = "max(cpu.system_perc) > 0" - alarm_definition = helpers.create_alarm_definition( - name=long_name, description="description", expression=expression) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_alarm_definitions, - alarm_definition) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_alarm_definition_with_description_exceeds_max_length(self): - name = data_utils.rand_name('alarm_definition') - long_description = "x" * (constants. - MAX_ALARM_DEFINITION_DESCRIPTION_LENGTH + 1) - expression = "max(cpu.system_perc) > 0" - alarm_definition = helpers.create_alarm_definition( - name=name, description=long_description, expression=expression) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_alarm_definitions, - alarm_definition) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_alarm_definition_with_invalid_severity(self): - invalid_severity = "INVALID" - name = data_utils.rand_name('alarm_definition') - expression = "max(cpu.system_perc) > 0" - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression, - severity=invalid_severity) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_alarm_definitions, - alarm_definition) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_alarm_definition_with_alarm_actions_exceeds_max_length( - self): - name = data_utils.rand_name('alarm_definition') - expression = "max(cpu.system_perc) > 0" - alarm_actions = ["x" * ( - constants.MAX_ALARM_DEFINITION_ACTIONS_LENGTH + 1)] - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression, - alarm_actions=alarm_actions) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_alarm_definitions, - alarm_definition) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_alarm_definition_with_ok_actions_exceeds_max_length(self): - name = data_utils.rand_name('alarm_definition') - expression = "max(cpu.system_perc) > 0" - ok_actions = ["x" * (constants.MAX_ALARM_DEFINITION_ACTIONS_LENGTH + - 1)] - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression, - ok_actions=ok_actions) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_alarm_definitions, - alarm_definition) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_alarm_definition_with_undeterm_actions_exceeds_max_length( - self): - name = data_utils.rand_name('alarm_definition') - expression = "max(cpu.system_perc) > 0" - undetermined_actions = ["x" * (constants. - MAX_ALARM_DEFINITION_ACTIONS_LENGTH + - 1)] - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression, - undetermined_actions=undetermined_actions) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_alarm_definitions, - alarm_definition) - - # List - - @decorators.attr(type=["gate", "smoke"]) - def test_list_alarm_definitions(self): - expression = "avg(cpu_utilization{service=compute}) >= 1234" - response_body_list = self._create_alarm_definitions( - expression=expression, number_of_definitions=1) - query_param = '?name=' + str(response_body_list[0]['name']) - resp, response_body = self.monasca_client.list_alarm_definitions( - query_param) - self._verify_list_alarm_definitions_response_body(resp, response_body) - - # Test list alarm definition response body - elements = response_body['elements'] - self._verify_alarm_definitions_list(elements, response_body_list) - links = response_body['links'] - self._verify_list_alarm_definitions_links(links) - - @decorators.attr(type="gate") - def test_list_alarm_definitions_with_multibyte_character(self): - rand_name = data_utils.rand_name('alarm_definition') - name = rand_name - description = 'description' - - response_body_list = self._create_alarm_definitions( - name=name, - description=description, - number_of_definitions=1 - ) - alarm_definition = response_body_list[0] - - query_param = '?name=' + urlparse.quote(name.encode('utf8')) - resp, response_body = self.monasca_client.list_alarm_definitions( - query_param) - - self._verify_list_alarm_definitions_response_body(resp, response_body) - - # Test list alarm definition response body - elements = response_body['elements'] - self._verify_alarm_definitions_list(elements, [alarm_definition]) - links = response_body['links'] - self._verify_list_alarm_definitions_links(links) - - @decorators.attr(type="gate") - def test_list_alarm_definitions_with_name(self): - name = data_utils.rand_name('alarm_definition') - alarm_definition = helpers.create_alarm_definition( - name=name, - description=data_utils.rand_name('description'), - expression="max(cpu.system_perc) > 0") - resp, res_body_create_alarm_def = self.monasca_client.\ - create_alarm_definitions(alarm_definition) - self.assertEqual(201, resp.status) - - query_parms = "?name=" + str(name) - resp, response_body = self.monasca_client.list_alarm_definitions( - query_parms) - self._verify_list_alarm_definitions_response_body(resp, response_body) - elements = response_body['elements'] - self._verify_alarm_definitions_list( - elements, [res_body_create_alarm_def]) - links = response_body['links'] - self._verify_list_alarm_definitions_links(links) - - @decorators.attr(type="gate") - def test_list_alarm_definitions_with_dimensions(self): - # Create an alarm definition with random dimensions - name = data_utils.rand_name('alarm_definition') - key = data_utils.rand_name('key') - value = data_utils.rand_name('value') - expression = 'avg(cpu_utilization{' + str(key) + '=' + str(value) + \ - '}) >= 1000' - alarm_definition = helpers.create_alarm_definition( - name=name, description="description", expression=expression) - resp, res_body_create_alarm_def = self.monasca_client.\ - create_alarm_definitions(alarm_definition) - self.assertEqual(201, resp.status) - - # List alarms - query_parms = '?dimensions=' + str(key) + ':' + str(value) - resp, response_body = self.monasca_client.\ - list_alarm_definitions(query_parms) - self._verify_list_alarm_definitions_response_body(resp, response_body) - elements = response_body['elements'] - self._verify_alarm_definitions_list(elements, [res_body_create_alarm_def]) - links = response_body['links'] - self._verify_list_alarm_definitions_links(links) - - @decorators.attr(type="gate") - def test_list_alarm_definitions_with_multiple_dimensions(self): - # Create an alarm definition with random dimensions - name = data_utils.rand_name('alarm_definition') - dimensions = {data_utils.rand_name('key-1'): data_utils.rand_name('value-1'), - data_utils.rand_name('key-2'): data_utils.rand_name('value-2')} - dimension_strings = [key + '=' + value for key, value in dimensions.items()] - expression = 'avg(cpu_utilization{' + ','.join(dimension_strings) + '}) >= 1000' - - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression) - resp, res_body_create_alarm_def = self.monasca_client. \ - create_alarm_definitions(alarm_definition) - self.assertEqual(201, resp.status) - - # List alarms - query_dimensions = [key + ':' + value for key, value in dimensions.items()] - query_parms = '?dimensions=' + ','.join(query_dimensions) - resp, response_body = self.monasca_client.list_alarm_definitions(query_parms) - self._verify_list_alarm_definitions_response_body(resp, response_body) - - elements = response_body['elements'] - self._verify_alarm_definitions_list(elements, [res_body_create_alarm_def]) - - links = response_body['links'] - self._verify_list_alarm_definitions_links(links) - - @decorators.attr(type="gate") - def test_list_alarm_definitions_with_severity(self): - name = data_utils.rand_name('alarm_definition') - expression = 'avg(cpu_utilization) >= 1000' - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression, - severity="LOW") - resp, res_body_create_alarm_def = self.monasca_client.\ - create_alarm_definitions(alarm_definition) - self.assertEqual(201, resp.status) - - name = data_utils.rand_name('alarm_definition') - expression = 'avg(cpu_utilization) >= 1000' - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression, - severity="MEDIUM") - resp, res_body_create_alarm_def = self.monasca_client.\ - create_alarm_definitions(alarm_definition) - self.assertEqual(201, resp.status) - - query_param = '?severity=MEDIUM' - resp, response_body = self.monasca_client.\ - list_alarm_definitions(query_param) - self._verify_list_alarm_definitions_response_body(resp, response_body) - elements = response_body['elements'] - self._verify_alarm_definitions_list(elements, [res_body_create_alarm_def]) - links = response_body['links'] - self._verify_list_alarm_definitions_links(links) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_alarm_definitions_by_severity_invalid_severity(self): - query_parms = '?severity=false_severity' - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_alarm_definitions, query_parms) - - @decorators.attr(type="gate") - def test_list_alarm_definitions_with_multiple_severity(self): - name = data_utils.rand_name('alarm_definition') - expression = 'avg(cpu_utilization{alarm=severity}) >= 1000' - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression, - severity="LOW") - resp, res_body_create_alarm_def_low = self.monasca_client.\ - create_alarm_definitions(alarm_definition) - self.assertEqual(201, resp.status) - - name = data_utils.rand_name('alarm_definition') - expression = 'avg(cpu_utilization{alarm=severity}) >= 1000' - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression, - severity="MEDIUM") - resp, res_body_create_alarm_def_medium = self.monasca_client.\ - create_alarm_definitions(alarm_definition) - self.assertEqual(201, resp.status) - - name = data_utils.rand_name('alarm_definition') - expression = 'avg(cpu_utilization{alarm=severity}) >= 1000' - alarm_definition = helpers.create_alarm_definition( - name=name, - description="description", - expression=expression, - severity="HIGH") - resp, res_body_create_alarm_def = self.monasca_client.\ - create_alarm_definitions(alarm_definition) - self.assertEqual(201, resp.status) - - query_param = ('?severity=MEDIUM|LOW&dimensions=alarm:severity' - '&sort_by=severity') - resp, response_body = (self.monasca_client - .list_alarm_definitions(query_param)) - self._verify_list_alarm_definitions_response_body(resp, response_body) - elements = response_body['elements'] - self._verify_alarm_definitions_list(elements, [res_body_create_alarm_def_low, - res_body_create_alarm_def_medium]) - links = response_body['links'] - self._verify_list_alarm_definitions_links(links) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_alarm_definitions_by_severity_multiple_values_invalid_severity(self): - query_parms = '?severity=false_severity|MEDIUM' - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_alarm_definitions, query_parms) - - query_parms = '?severity=MEDIUM|false_severity' - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_alarm_definitions, query_parms) - - query_parms = '?severity=LOW|false_severity|HIGH' - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_alarm_definitions, query_parms) - - @decorators.attr(type='gate') - def test_list_alarm_definitions_sort_by(self): - key = data_utils.rand_name('key') - value = data_utils.rand_name('value') - expression = 'avg(cpu_utilization{' + str(key) + '=' + str(value) + \ - '}) >= 1000' - - alarm_definitions = [helpers.create_alarm_definition( - name='alarm def sort by 01', - expression=expression, - severity='HIGH' - ), helpers.create_alarm_definition( - name='alarm def sort by 04', - expression=expression, - severity='LOW' - ), helpers.create_alarm_definition( - name='alarm def sort by 02', - expression=expression, - severity='CRITICAL' - ), helpers.create_alarm_definition( - name='alarm def sort by 03', - expression=expression, - severity='MEDIUM' - )] - for definition in alarm_definitions: - resp, response_body = self.monasca_client.create_alarm_definitions(definition) - definition['id'] = response_body['id'] - time.sleep(1) - - sort_params1 = ['id', 'name', 'severity'] - for sort_by in sort_params1: - alarmdefs_sort_by = sorted(alarm_definitions, - key=lambda d: d[sort_by]) - - resp, response_body = self.monasca_client.list_alarm_definitions( - '?dimensions=' + str(key) + ':' + str(value) + - '&sort_by=' + sort_by) - self.assertEqual(200, resp.status) - for i, element in enumerate(response_body['elements']): - self.assertEqual(alarmdefs_sort_by[i][sort_by], element[sort_by]) - - resp, response_body = self.monasca_client.list_alarm_definitions( - '?dimensions=' + str(key) + ':' + str(value) + - '&sort_by=' + sort_by + urlparse.quote(' asc')) - self.assertEqual(200, resp.status) - for i, element in enumerate(response_body['elements']): - self.assertEqual(alarmdefs_sort_by[i][sort_by], element[sort_by]) - - alarmdefs_sort_by_reverse = sorted(alarm_definitions, - key=lambda d: d[sort_by], - reverse=True) - - resp, response_body = self.monasca_client.list_alarm_definitions( - '?dimensions=' + str(key) + ':' + str(value) + - '&sort_by=' + sort_by + urlparse.quote(' desc')) - self.assertEqual(200, resp.status) - for i, element in enumerate(response_body['elements']): - self.assertEqual(alarmdefs_sort_by_reverse[i][sort_by], element[sort_by]) - - sort_params2 = ['created_at', 'updated_at'] - for sort_by in sort_params2: - resp, response_body = self.monasca_client.list_alarm_definitions( - '?dimensions=' + str(key) + ':' + str(value) + - '&sort_by=' + sort_by) - self.assertEqual(200, resp.status) - for i, element in enumerate(response_body['elements']): - self.assertEqual(alarm_definitions[i]['id'], element['id']) - - resp, response_body = self.monasca_client.list_alarm_definitions( - '?dimensions=' + str(key) + ':' + str(value) + - '&sort_by=' + sort_by + urlparse.quote(' asc')) - self.assertEqual(200, resp.status) - for i, element in enumerate(response_body['elements']): - self.assertEqual(alarm_definitions[i]['id'], element['id']) - - resp, response_body = self.monasca_client.list_alarm_definitions( - '?dimensions=' + str(key) + ':' + str(value) + - '&sort_by=' + sort_by + urlparse.quote(' desc')) - self.assertEqual(200, resp.status) - for i, element in enumerate(response_body['elements']): - self.assertEqual(alarm_definitions[-i - 1]['id'], element['id']) - - @decorators.attr(type='gate') - def test_list_alarm_definitions_multiple_sort_by(self): - key = data_utils.rand_name('key') - value = data_utils.rand_name('value') - expression = 'avg(cpu_utilization{' + str(key) + '=' + str(value) + \ - '}) >= 1000' - - alarm_definitions = [helpers.create_alarm_definition( - name='alarm def sort by 11', - expression=expression, - severity='MEDIUM' - ), helpers.create_alarm_definition( - name='alarm def sort by 14', - expression=expression, - severity='MEDIUM' - ), helpers.create_alarm_definition( - name='alarm def sort by 12', - expression=expression, - severity='LOW' - ), helpers.create_alarm_definition( - name='alarm def sort by 13', - expression=expression, - severity='MEDIUM' - )] - for definition in alarm_definitions: - resp, response_body = self.monasca_client.create_alarm_definitions(definition) - definition['id'] = response_body['id'] - - resp, response_body = self.monasca_client.list_alarm_definitions( - '?dimensions=' + str(key) + ':' + str(value) + - '&sort_by=' + urlparse.quote('severity asc,name desc,id')) - self.assertEqual(200, resp.status) - - expected_order = [2, 1, 3, 0] - - for i, element in enumerate(response_body['elements']): - self.assertEqual(alarm_definitions[expected_order[i]]['id'], element['id']) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_list_alarm_definitions_invalid_sort_by(self): - query_parms = '?sort_by=random' - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_alarm_definitions, query_parms) - - @decorators.attr(type="gate") - def test_list_alarm_definitions_with_offset_limit(self): - helpers.delete_alarm_definitions(self.monasca_client) - expression = "max(cpu.system_perc) > 0" - self._create_alarm_definitions( - expression=expression, number_of_definitions=NUM_ALARM_DEFINITIONS) - resp, response_body = self.monasca_client.list_alarm_definitions() - self._verify_list_alarm_definitions_response_body(resp, response_body) - first_element = response_body['elements'][0] - last_element = response_body['elements'][1] - - query_parms = '?limit=2' - resp, response_body = self.monasca_client.list_alarm_definitions( - query_parms) - self.assertEqual(200, resp.status) - - elements = response_body['elements'] - self.assertEqual(2, len(elements)) - self.assertEqual(first_element, elements[0]) - self.assertEqual(last_element, elements[1]) - - for offset in range(0, 2): - for limit in range(1, 3 - offset): - query_parms = '?offset=' + str(offset) + '&limit=' + str(limit) - resp, response_body = self.monasca_client.list_alarm_definitions(query_parms) - self.assertEqual(200, resp.status) - new_elements = response_body['elements'] - self.assertEqual(limit, len(new_elements)) - self.assertEqual(elements[offset], new_elements[0]) - self.assertEqual(elements[offset + limit - 1], - new_elements[-1]) - links = response_body['links'] - for link in links: - if link['rel'] == 'next': - next_offset = helpers.get_query_param(link['href'], 'offset') - next_limit = helpers.get_query_param(link['href'], 'limit') - self.assertEqual(str(offset + limit), next_offset) - self.assertEqual(str(limit), next_limit) - - # Get - - @decorators.attr(type="gate") - def test_get_alarm_definition(self): - response_body_list = self._create_alarm_definitions( - expression=None, number_of_definitions=1) - resp, response_body = self.monasca_client.get_alarm_definition( - response_body_list[0]['id']) - self.assertEqual(200, resp.status) - self._verify_element_set(response_body) - self._verify_alarm_definitions_element(response_body, - response_body_list[0]) - links = response_body['links'] - self._verify_list_alarm_definitions_links(links) - - @decorators.attr(type="gate") - def test_get_alarm_definition_with_multibyte_character(self): - # Create an alarm definition - rand_name = data_utils.rand_name('alarm_definition') - name = rand_name - description = 'description' - response_body_list = self._create_alarm_definitions( - name=name, - description=description, - number_of_definitions=1 - ) - alarm_definition = response_body_list[0] - - resp, response_body = self.monasca_client.get_alarm_definition( - alarm_definition['id']) - - self.assertEqual(200, resp.status) - self._verify_element_set(response_body) - self._verify_alarm_definitions_element(response_body, - alarm_definition) - links = response_body['links'] - self._verify_list_alarm_definitions_links(links) - - # Update - - @decorators.attr(type="gate") - def test_update_alarm_definition(self): - notification_name = data_utils.rand_name('notification-') - notification_type = 'EMAIL' - address = 'root@localhost' - - resp, response_body = self.monasca_client.create_notification_method( - notification_name, type=notification_type, address=address) - notification_id = self._verify_create_notification_method( - resp, response_body, notification_name, notification_type, address) - - response_body_list = self._create_alarm_definitions( - expression=None, number_of_definitions=1) - # Update alarm definition - updated_name = data_utils.rand_name('updated_name') - updated_description = 'updated description' - updated_expression = "max(cpu.system_perc) < 0" - - resp, response_body = self.monasca_client.update_alarm_definition( - str(response_body_list[0]['id']), updated_name, updated_expression, - updated_description, True, response_body_list[0]['match_by'], - 'LOW', [notification_id], [notification_id], [notification_id]) - self.assertEqual(200, resp.status) - self._verify_update_patch_alarm_definition(response_body, updated_name, - updated_expression, - updated_description, None) - # Validate fields updated - resp, response_body = self.monasca_client.get_alarm_definition( - response_body_list[0]['id']) - self._verify_update_patch_alarm_definition(response_body, updated_name, - updated_expression, - updated_description, None) - links = response_body['links'] - self._verify_list_alarm_definitions_links(links) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_update_alarm_definition_with_a_different_match_by(self): - response_body_list = self._create_alarm_definitions( - expression=None, number_of_definitions=1) - name = response_body_list[0]['name'] - expression = response_body_list[0]['expression'] - description = response_body_list[0]['description'] - updated_match_by = ['hostname'] - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.update_alarm_definition, - response_body_list[0]['id'], name, expression, - description, 'true', updated_match_by, 'LOW', None, - None, None) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_update_alarm_definition_with_no_ok_actions(self): - response_body_list = self._create_alarm_definitions( - expression=None, number_of_definitions=1) - name = response_body_list[0]['name'] - expression = response_body_list[0]['expression'] - description = response_body_list[0]['description'] - updated_match_by = ['hostname'] - self.assertRaises( - exceptions.UnprocessableEntity, - self.monasca_client.update_alarm_definition_with_no_ok_actions, - response_body_list[0]['id'], name, expression, description, - 'true', updated_match_by, 'LOW', None, None) - - @decorators.attr(type="gate") - def test_update_notification_in_alarm_definition(self): - notification_name = data_utils.rand_name('notification-') - notification_type = 'EMAIL' - address = 'root@localhost' - - resp, response_body = self.monasca_client.create_notification_method( - notification_name, type=notification_type, address=address) - notification_id = self._verify_create_notification_method( - resp, response_body, notification_name, notification_type, address) - - # Create an alarm definition - response_body_list = self._create_alarm_definitions( - expression=None, number_of_definitions=1) - expression = response_body_list[0]['expression'] - - # Update alarm definition - update_alarm_def_name = data_utils.rand_name('monitoring_alarm_update') - resp, response_body = self.monasca_client.update_alarm_definition( - response_body_list[0]['id'], update_alarm_def_name, expression, - 'description', True, response_body_list[0]['match_by'], 'LOW', - [notification_id], [notification_id], [notification_id]) - self.assertEqual(200, resp.status) - self._verify_update_patch_alarm_definition(response_body, - update_alarm_def_name, - None, None, notification_id) - # Get and verify details of an alarm after update - resp, response_body = self.monasca_client.get_alarm_definition( - response_body_list[0]['id']) - self._verify_update_patch_alarm_definition(response_body, - update_alarm_def_name, - None, None, notification_id) - self._delete_notification(notification_id) - - # Patch - - @decorators.attr(type="gate") - def test_patch_alarm_definition(self): - response_body_list = self._create_alarm_definitions( - expression=None, number_of_definitions=1) - # Patch alarm definition - patched_name = data_utils.rand_name('patched_name') - resp, response_body = self.monasca_client.patch_alarm_definition( - id=response_body_list[0]['id'], - name=patched_name - ) - self.assertEqual(200, resp.status) - self._verify_update_patch_alarm_definition(response_body, patched_name, - None, None, None) - # Validate fields updated - resp, response_body = self.monasca_client.get_alarm_definition( - response_body_list[0]['id']) - self._verify_update_patch_alarm_definition(response_body, patched_name, - None, None, None) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_patch_alarm_definition_with_a_different_match_by(self): - response_body_list = self._create_alarm_definitions( - expression=None, number_of_definitions=1) - # Patch alarm definition - patched_match_by = ['hostname'] - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.patch_alarm_definition, - id=response_body_list[0]['id'], - match_by=patched_match_by) - - @decorators.attr(type="gate") - def test_patch_actions_in_alarm_definition(self): - notification_name = data_utils.rand_name('notification-') - notification_type = 'EMAIL' - address = 'root@localhost' - - resp, response_body = self.monasca_client.create_notification_method( - notification_name, type=notification_type, address=address) - notification_id = self._verify_create_notification_method( - resp, response_body, notification_name, notification_type, address) - - # Create an alarm definition - response_body_list = self._create_alarm_definitions( - expression=None, number_of_definitions=1) - # Patch alarm definition - patch_alarm_def_name = data_utils.rand_name('monitoring_alarm_update') - resp, body = self.monasca_client.patch_alarm_definition( - response_body_list[0]['id'], - name=patch_alarm_def_name, - expression=response_body_list[0]['expression'], - actions_enabled='true', - alarm_actions=[notification_id], - ok_actions=[notification_id], - undetermined_actions=[notification_id] - ) - self.assertEqual(200, resp.status) - self._verify_update_patch_alarm_definition(body, patch_alarm_def_name, - None, None, notification_id) - # Get and verify details of an alarm after update - resp, response_body = self.monasca_client.get_alarm_definition( - response_body_list[0]['id']) - self._verify_update_patch_alarm_definition(response_body, - patch_alarm_def_name, None, - None, notification_id) - self._delete_notification(notification_id) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_patch_alarm_definition_with_invalid_actions(self): - response_body_list = self._create_alarm_definitions( - expression=None, number_of_definitions=1) - # Patch alarm definition - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.patch_alarm_definition, - id=response_body_list[0]['id'], - alarm_actions=['bad_notification_id']) - - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.patch_alarm_definition, - id=response_body_list[0]['id'], - ok_actions=['bad_notification_id']) - - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.patch_alarm_definition, - id=response_body_list[0]['id'], - undetermined_actions=['bad_notification_id']) - - # Delete - - @decorators.attr(type="gate") - def test_create_and_delete_alarm_definition(self): - response_body_list = self._create_alarm_definitions( - expression=None, number_of_definitions=1) - # Delete alarm definitions - resp, response_body = self.monasca_client.list_alarm_definitions() - self._verify_list_alarm_definitions_response_body(resp, response_body) - elements = response_body['elements'] - for element in elements: - if element['id'] == response_body_list[0]['id']: - resp, body = self.monasca_client.delete_alarm_definition( - response_body_list[0]['id']) - self.assertEqual(204, resp.status) - self.assertRaises(exceptions.NotFound, - self.monasca_client.get_alarm_definition, - response_body_list[0]['id']) - return - self.fail("Failed test_create_and_delete_alarm_definition: " - "cannot find the alarm definition just created.") - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_get_alarm_defintion_with_invalid_id(self): - def_id = data_utils.rand_name() - self.assertRaises(exceptions.NotFound, - self.monasca_client.get_alarm_definition, def_id) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_delete_alarm_defintion_with_invalid_id(self): - def_id = data_utils.rand_name() - self.assertRaises(exceptions.NotFound, - self.monasca_client.delete_alarm_definition, def_id) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_patch_alarm_defintion_with_invalid_id(self): - def_id = data_utils.rand_name() - self.assertRaises(exceptions.NotFound, - self.monasca_client.patch_alarm_definition, - id=def_id, name='Test') - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_update_alarm_defintion_with_invalid_id(self): - def_id = data_utils.rand_name() - - updated_name = data_utils.rand_name('updated_name') - updated_description = 'updated description' - updated_expression = "max(cpu.system_perc) < 0" - self.assertRaises(exceptions.NotFound, - self.monasca_client.update_alarm_definition, - def_id, updated_name, updated_expression, - updated_description, True, ['device'], - 'LOW', [], [], - []) - - def _create_alarm_definitions(self, number_of_definitions, **kwargs): - self.rule = {'expression': 'mem_total_mb > 0'} - - expression = kwargs.get('expression', None) - if expression is None: - expression = 'max(cpu.system_perc) > 0' - match_by = kwargs.get('match_by', ['device']) - - response_body_list = [] - for i in range(number_of_definitions): - - name = kwargs.get('name', - data_utils.rand_name('alarm_definition')) - desc = kwargs.get('description', - data_utils.rand_name('description')) - - alarm_definition = helpers.create_alarm_definition( - name=name, - description=desc, - expression=expression, - match_by=match_by - ) - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition) - self.assertEqual(201, resp.status) - response_body_list.append(response_body) - return response_body_list - - def _verify_list_alarm_definitions_response_body(self, resp, - response_body): - self.assertEqual(200, resp.status) - self.assertIsInstance(response_body, dict) - self.assertTrue(set(['links', 'elements']) == set(response_body)) - - def _verify_alarm_definitions_list(self, observed, reference): - self.assertEqual(len(reference), len(observed)) - for i in range(len(reference)): - self._verify_alarm_definitions_element( - reference[i], observed[i]) - - def _verify_alarm_definitions_element(self, response_body, - res_body_create_alarm_def): - self._verify_element_set(response_body) - self.assertEqual(response_body['name'], - res_body_create_alarm_def['name']) - self.assertEqual(response_body['expression'], - res_body_create_alarm_def['expression']) - self.assertEqual(response_body['id'], res_body_create_alarm_def['id']) - self.assertEqual(response_body['description'], - res_body_create_alarm_def['description']) - self.assertEqual(response_body['match_by'], - res_body_create_alarm_def['match_by']) - self.assertEqual(response_body['severity'], - res_body_create_alarm_def['severity']) - self.assertEqual(response_body['deterministic'], - res_body_create_alarm_def['deterministic']) - - def _verify_element_set(self, element): - self.assertTrue(set(['id', - 'links', - 'name', - 'description', - 'expression', - 'deterministic', - 'match_by', - 'severity', - 'actions_enabled', - 'ok_actions', - 'alarm_actions', - 'undetermined_actions']) == - set(element)) - - def _verify_list_alarm_definitions_links(self, links): - self.assertIsInstance(links, list) - link = links[0] - self.assertTrue(set(['rel', 'href']) == set(link)) - self.assertEqual(link['rel'], u'self') - - def _verify_create_alarm_definitions(self, - resp, - response_body, - alarm_definition, - deterministic=False): - self.assertEqual(201, resp.status) - self.assertEqual(alarm_definition['name'], response_body['name']) - - self.assertEqual(alarm_definition['expression'], - str(response_body['expression'])) - self.assertEqual(deterministic, bool(response_body['deterministic'])) - - if 'description' in alarm_definition: - self.assertEqual(alarm_definition['description'], - str(response_body['description'])) - else: - self.assertEqual('', str(response_body['description'])) - if 'match_by' in alarm_definition: - self.assertEqual(alarm_definition['match_by'], - response_body['match_by']) - else: - self.assertEmpty(response_body['match_by']) - if 'severity' in alarm_definition: - self.assertEqual(alarm_definition['severity'], - str(response_body['severity'])) - else: - self.assertEqual('LOW', str(response_body['severity'])) - - def _verify_update_patch_alarm_definition(self, response_body, - updated_name, updated_expression, - updated_description, - notification_id): - if updated_name is not None: - self.assertEqual(updated_name, response_body['name']) - if updated_expression is not None: - self.assertEqual(updated_expression, response_body['expression']) - if updated_description is not None: - self.assertEqual(updated_description, response_body['description']) - if notification_id is not None: - self.assertEqual(notification_id, - response_body['alarm_actions'][0]) - self.assertEqual(notification_id, response_body['ok_actions'][0]) - self.assertEqual(notification_id, - response_body['undetermined_actions'][0]) - - def _delete_notification(self, notification_id): - resp, body = self.monasca_client.delete_notification_method( - notification_id) - self.assertEqual(204, resp.status) - - def _verify_create_notification_method( - self, resp, response_body, test_name, test_type, test_address): - self.assertEqual(201, resp.status) - self.assertEqual(test_name, response_body['name']) - self.assertEqual(test_type, response_body['type']) - self.assertEqual(test_address, response_body['address']) - notification_id = response_body['id'] - return notification_id diff --git a/monasca_tempest_tests/tests/api/test_alarm_state_history_multiple_transitions.py b/monasca_tempest_tests/tests/api/test_alarm_state_history_multiple_transitions.py deleted file mode 100644 index c58976b..0000000 --- a/monasca_tempest_tests/tests/api/test_alarm_state_history_multiple_transitions.py +++ /dev/null @@ -1,141 +0,0 @@ -# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time - -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import constants -from monasca_tempest_tests.tests.api import helpers -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -MIN_HISTORY = 2 - - -class TestAlarmStateHistoryMultipleTransitions(base.BaseMonascaTest): - # For testing list alarm state history with the same alarm ID, two alarm - # transitions are needed. One transit from ALARM state to UNDETERMINED - # state and the other one from UNDETERMINED state to ALARM state. - - @classmethod - def resource_setup(cls): - super(TestAlarmStateHistoryMultipleTransitions, cls).resource_setup() - alarm_definition = helpers.create_alarm_definition( - name=data_utils.rand_name('alarm_state_history'), - expression="min(name-1) < 1.0") - cls.monasca_client.create_alarm_definitions(alarm_definition) - for timer in range(constants.MAX_RETRIES): - # create some metrics to prime the system and create - # MIN_HISTORY alarms - metric = helpers.create_metric( - name="name-1", dimensions={'key1': 'value1'}, value=0.0) - cls.monasca_client.create_metrics(metric) - # sleep 1 second between metrics to make sure timestamps - # are different in the second field. Influxdb has a bug - # where it does not sort properly by milliseconds. .014 - # is sorted as greater than .138 - time.sleep(1.0) - resp, response_body = cls.monasca_client.\ - list_alarms_state_history() - elements = response_body['elements'] - if len(elements) >= 1: - break - time.sleep(constants.RETRY_WAIT_SECS) - - time.sleep(constants.MAX_RETRIES) - - for timer in range(constants.MAX_RETRIES * 2): - metric = helpers.create_metric( - name="name-1", dimensions={'key2': 'value2'}, value=2.0) - cls.monasca_client.create_metrics(metric) - # sleep 0.05 second between metrics to make sure timestamps - # are different - time.sleep(0.05) - resp, response_body = \ - cls.monasca_client.list_alarms_state_history() - elements = response_body['elements'] - if len(elements) >= 2: - return - else: - num_transitions = len(elements) - time.sleep(constants.RETRY_WAIT_SECS) - assert False, "Required {} alarm state transitions, but found {}".\ - format(MIN_HISTORY, num_transitions) - - @classmethod - def resource_cleanup(cls): - super(TestAlarmStateHistoryMultipleTransitions, cls).\ - resource_cleanup() - - @decorators.attr(type="gate") - def test_list_alarm_state_history(self): - # Get the alarm state history for a specific alarm by ID - resp, response_body = self.monasca_client.list_alarms_state_history() - self.assertEqual(200, resp.status) - elements = response_body['elements'] - if elements: - element = elements[0] - alarm_id = element['alarm_id'] - resp, response_body = self.monasca_client.list_alarm_state_history( - alarm_id) - self.assertEqual(200, resp.status) - - # Test Response Body - self.assertTrue(set(['links', 'elements']) == - set(response_body)) - elements = response_body['elements'] - links = response_body['links'] - self.assertIsInstance(links, list) - link = links[0] - self.assertTrue(set(['rel', 'href']) == - set(link)) - self.assertEqual(link['rel'], u'self') - definition = elements[0] - self.assertTrue(set(['id', 'alarm_id', 'metrics', 'new_state', - 'old_state', 'reason', 'reason_data', - 'sub_alarms', 'timestamp']) == - set(definition)) - else: - error_msg = "Failed test_list_alarm_state_history: at least one " \ - "alarm state history is needed." - self.fail(error_msg) - - @decorators.attr(type="gate") - def test_list_alarm_state_history_with_offset_limit(self): - # Get the alarm state history for a specific alarm by ID - resp, response_body = self.monasca_client.list_alarms_state_history() - self.assertEqual(200, resp.status) - elements = response_body['elements'] - if len(elements) >= MIN_HISTORY: - element = elements[0] - second_element = elements[1] - alarm_id = element['alarm_id'] - query_parms = '?limit=1' - resp, response_body = self.monasca_client.\ - list_alarm_state_history(alarm_id, query_parms) - elements = response_body['elements'] - self.assertEqual(200, resp.status) - self.assertEqual(1, len(elements)) - - query_parms = '?offset=' + str(element['timestamp']) - resp, response_body = self.monasca_client.\ - list_alarm_state_history(alarm_id, query_parms) - elements_new = response_body['elements'] - self.assertEqual(200, resp.status) - self.assertEqual(1, len(elements_new)) - self.assertEqual(second_element, elements_new[0]) - else: - error_msg = "Failed test_list_alarm_state_history_with_offset" \ - "_limit: two alarms state history are needed." - self.fail(error_msg) diff --git a/monasca_tempest_tests/tests/api/test_alarm_transitions.py b/monasca_tempest_tests/tests/api/test_alarm_transitions.py deleted file mode 100644 index 0e79699..0000000 --- a/monasca_tempest_tests/tests/api/test_alarm_transitions.py +++ /dev/null @@ -1,212 +0,0 @@ -# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time - -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import constants -from monasca_tempest_tests.tests.api import helpers - -WAIT_SECS = 10 - - -class TestAlarmTransitions(base.BaseMonascaTest): - - @classmethod - def resource_setup(cls): - super(TestAlarmTransitions, cls).resource_setup() - - @classmethod - def resource_cleanup(cls): - super(TestAlarmTransitions, cls).resource_cleanup() - - def _wait_for_alarm_creation(self, definition_id): - for x in range(WAIT_SECS): - time.sleep(1) - resp, resp_body = self.monasca_client.list_alarms( - query_params="?alarm_definition_id=" + definition_id) - - self.assertEqual(200, resp.status) - if len(resp_body['elements']) != 0: - break - self.assertEqual(1, len(resp_body['elements'])) - alarm_id = resp_body['elements'][0]['id'] - initial_state = resp_body['elements'][0]['state'] - return alarm_id, initial_state - - def _wait_for_alarm_transition(self, alarm_id, expected_state): - for x in range(WAIT_SECS): - time.sleep(1) - resp, resp_body = self.monasca_client.get_alarm(alarm_id) - self.assertEqual(200, resp.status) - if resp_body['state'] == expected_state: - break - self.assertEqual(expected_state, resp_body['state']) - - def _send_measurement(self, metric_def, value): - metric = helpers.create_metric(name=metric_def['name'], - dimensions=metric_def['dimensions'], - value=value) - resp, resp_body = self.monasca_client.create_metrics([metric]) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_alarm_max_function(self): - metric_def = { - 'name': data_utils.rand_name("max_test"), - 'dimensions': { - 'dim_to_match': data_utils.rand_name("max_match") - } - } - expression = "max(" + metric_def['name'] + ") > 14" - definition = helpers.create_alarm_definition(name="Test Max Function", - description="", - expression=expression, - match_by=["dim_to_match"]) - resp, resp_body = (self.monasca_client - .create_alarm_definitions(definition)) - self.assertEqual(201, resp.status) - definition_id = resp_body['id'] - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - - self._send_measurement(metric_def, 1) - - alarm_id, initial_state = self._wait_for_alarm_creation(definition_id) - self.assertEqual("UNDETERMINED", initial_state) - - self._send_measurement(metric_def, 20) - - self._wait_for_alarm_transition(alarm_id, "ALARM") - - @decorators.attr(type="gate") - def test_alarm_max_with_deterministic(self): - metric_def = { - 'name': data_utils.rand_name("max_deterministic_test"), - 'dimensions': { - 'dim_to_match': data_utils.rand_name("max_match") - } - } - expression = "max(" + metric_def['name'] + ",deterministic) > 14" - definition = helpers.create_alarm_definition(name="Test Max Deterministic Function", - description="", - expression=expression, - match_by=["dim_to_match"]) - resp, resp_body = self.monasca_client.create_alarm_definitions(definition) - self.assertEqual(201, resp.status) - definition_id = resp_body['id'] - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - - self._send_measurement(metric_def, 1) - - alarm_id, initial_state = self._wait_for_alarm_creation(definition_id) - self.assertEqual("OK", initial_state) - - self._send_measurement(metric_def, 20) - - self._wait_for_alarm_transition(alarm_id, "ALARM") - - @decorators.attr(type="gate") - def test_alarm_last_function(self): - metric_def = { - 'name': data_utils.rand_name("last_test"), - 'dimensions': { - 'dim_to_match': data_utils.rand_name("last_match") - } - } - expression = "last(" + metric_def['name'] + ") > 14" - definition = helpers.create_alarm_definition(name="Test Last Function", - description="", - expression=expression, - match_by=["dim_to_match"]) - resp, resp_body = self.monasca_client.create_alarm_definitions(definition) - self.assertEqual(201, resp.status) - definition_id = resp_body['id'] - # Ensure the new Alarm Definition gets to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - - self._send_measurement(metric_def, 1) - - alarm_id, initial_state = self._wait_for_alarm_creation(definition_id) - self.assertEqual("OK", initial_state) - - self._send_measurement(metric_def, 20) - - self._wait_for_alarm_transition(alarm_id, "ALARM") - - self._send_measurement(metric_def, 3) - - self._wait_for_alarm_transition(alarm_id, "OK") - - @decorators.attr(type="gate") - def test_alarm_last_with_deterministic(self): - metric_def = { - 'name': data_utils.rand_name("last_deterministic_test"), - 'dimensions': { - 'dim_to_match': data_utils.rand_name("last_match") - } - } - expression = "last(" + metric_def['name'] + ",deterministic) > 14" - definition = helpers.create_alarm_definition(name="Test Last Deterministic Function", - description="", - expression=expression, - match_by=["dim_to_match"]) - resp, resp_body = self.monasca_client.create_alarm_definitions(definition) - self.assertEqual(201, resp.status) - definition_id = resp_body['id'] - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - - self._send_measurement(metric_def, 1) - - alarm_id, initial_state = self._wait_for_alarm_creation(definition_id) - self.assertEqual("OK", initial_state) - - self._send_measurement(metric_def, 20) - - self._wait_for_alarm_transition(alarm_id, "ALARM") - - self._send_measurement(metric_def, 3) - - self._wait_for_alarm_transition(alarm_id, "OK") - - @decorators.attr(type="gate") - def test_alarm_metric_mixcase(self): - metric_def = { - 'name': data_utils.rand_name("MixCase_Test"), - 'dimensions': { - 'dim_to_match': data_utils.rand_name("max_match") - } - } - expression = "max(" + metric_def['name'] + ") > 14" - definition = helpers.create_alarm_definition(name="Metric Mixcase Test", - description="", - expression=expression, - match_by=["dim_to_match"]) - resp, resp_body = self.monasca_client.create_alarm_definitions(definition) - self.assertEqual(201, resp.status) - definition_id = resp_body['id'] - - # Ensure the new Alarm Definition gets to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - - self._send_measurement(metric_def, 1) - - alarm_id, initial_state = self._wait_for_alarm_creation(definition_id) - self.assertEqual("UNDETERMINED", initial_state) - - self._send_measurement(metric_def, 20) - - self._wait_for_alarm_transition(alarm_id, "ALARM") diff --git a/monasca_tempest_tests/tests/api/test_alarms.py b/monasca_tempest_tests/tests/api/test_alarms.py deleted file mode 100644 index f808262..0000000 --- a/monasca_tempest_tests/tests/api/test_alarms.py +++ /dev/null @@ -1,1089 +0,0 @@ -# (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time -import urllib.parse as urlparse - -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import constants -from monasca_tempest_tests.tests.api import helpers -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators -from tempest.lib import exceptions - - -class TestAlarms(base.BaseMonascaTest): - - @classmethod - def resource_setup(cls): - super(TestAlarms, cls).resource_setup() - - @classmethod - def resource_cleanup(cls): - super(TestAlarms, cls).resource_cleanup() - - @decorators.attr(type=["gate", "smoke"]) - def test_list_alarms(self): - alarm_definition_ids, expected_metric \ - = self._create_alarms_for_test_alarms(num=1) - resp, response_body = self.monasca_client.list_alarms() - self.assertEqual(200, resp.status) - for element in response_body['elements']: - self._verify_alarm_keys(element) - metric = element['metrics'][0] - if metric['name'] == expected_metric['name']: - self._verify_metric_in_alarm(metric, expected_metric) - return - self.fail("Failed test_list_alarms: cannot find the alarm just " - "created.") - - @decorators.attr(type="gate") - def test_list_alarms_by_alarm_definition_id(self): - alarm_definition_ids, expected_metric \ - = self._create_alarms_for_test_alarms(num=1) - query_param = '?alarm_definition_id=' + str(alarm_definition_ids[0]) - resp, response_body = self.monasca_client.list_alarms(query_param) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=1) - element = response_body['elements'][0] - metric = element['metrics'][0] - self._verify_metric_in_alarm(metric, expected_metric) - - @decorators.attr(type="gate") - def test_list_alarms_by_metric_name(self): - alarm_definition_ids, expected_metric \ - = self._create_alarms_for_test_alarms(num=1) - query_parms = '?metric_name=' + expected_metric['name'] - resp, response_body = self.monasca_client.list_alarms(query_parms) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=1) - element = response_body['elements'][0] - metric = element['metrics'][0] - self._verify_metric_in_alarm(metric, expected_metric) - self.assertEqual(alarm_definition_ids[0], element[ - 'alarm_definition']['id']) - - @decorators.attr(type="gate") - def test_list_alarms_by_metric_dimensions(self): - alarm_definition_ids, expected_metric \ - = self._create_alarms_for_test_alarms(num=1) - for key in expected_metric['dimensions']: - value = expected_metric['dimensions'][key] - query_parms = '?metric_dimensions=' + key + ':' + value - resp, response_body = self.monasca_client.list_alarms(query_parms) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=1) - element = response_body['elements'][0] - metric = element['metrics'][0] - self._verify_metric_in_alarm(metric, expected_metric) - self.assertEqual(alarm_definition_ids[0], - element['alarm_definition']['id']) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_alarms_by_metric_dimensions_key_exceeds_max_length(self): - key = 'x' * (constants.MAX_ALARM_METRIC_DIMENSIONS_KEY_LENGTH + 1) - query_parms = '?metric_dimensions=' + key - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_alarms, query_parms) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_alarms_by_metric_dimensions_value_exceeds_max_length(self): - value = 'x' * (constants.MAX_ALARM_METRIC_DIMENSIONS_VALUE_LENGTH + 1) - query_parms = '?metric_dimensions=key:' + value - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_alarms, query_parms) - - @decorators.attr(type="gate") - def test_list_alarms_by_multiple_metric_dimensions(self): - metric = helpers.create_metric( - name=data_utils.rand_name("multi-dimension"), - dimensions={data_utils.rand_name("key-1"): data_utils.rand_name("value-1"), - data_utils.rand_name("key-2"): data_utils.rand_name("value-2")}, - value=20 - ) - dimension_strings = [key + '=' + value for key, value in metric['dimensions'].items()] - alarm_def = helpers.create_alarm_definition( - name=data_utils.rand_name("multi-dimensions"), - expression=metric['name'] + "{" + ','.join(dimension_strings) + '} > 15' - ) - - resp, response_body = self.monasca_client.create_alarm_definitions(alarm_def) - self.assertEqual(201, resp.status) - alarm_def_id = response_body['id'] - - # Ensure the new Alarm Definition gets to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - - resp, response_body = self.monasca_client.create_metrics(metric) - self.assertEqual(204, resp.status) - self._wait_for_alarms(1, alarm_def_id) - - query_dimensions = [key + ':' + value for key, value in metric['dimensions'].items()] - query_parms = "?metric_dimensions=" + ','.join(query_dimensions) - - resp, response_body = self.monasca_client.list_alarms(query_parms) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=1) - element = response_body['elements'][0] - metric = element['metrics'][0] - self._verify_metric_in_alarm(metric, metric) - self.assertEqual(alarm_def_id, - element['alarm_definition']['id']) - - @decorators.attr(type="gate") - def test_list_alarms_by_metric_dimensions_no_value(self): - metric_name = data_utils.rand_name('metric') - match_by_key = data_utils.rand_name('key') - dim_key = data_utils.rand_name('key') - alarm_def = helpers.create_alarm_definition( - name=data_utils.rand_name('definition'), - expression=metric_name + " > 1", - match_by=[match_by_key]) - metric_1 = helpers.create_metric(metric_name, - {match_by_key: data_utils.rand_name('value'), - dim_key: data_utils.rand_name('value')}) - metric_2 = helpers.create_metric(metric_name, - {match_by_key: data_utils.rand_name('value'), - dim_key: data_utils.rand_name('value')}) - metric_3 = helpers.create_metric(metric_name, - {match_by_key: data_utils.rand_name('value')}) - metrics = [metric_1, metric_2, metric_3] - resp, response_body = self.monasca_client.create_alarm_definitions(alarm_def) - self.assertEqual(201, resp.status) - - # Ensure the new Alarm Definition gets to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - - for i in range(constants.MAX_RETRIES): - resp, alarm_def_result = self.monasca_client.create_metrics(metrics) - self.assertEqual(204, resp.status) - resp, response_body = self.monasca_client.list_alarms('?metric_name=' + metric_name) - self.assertEqual(200, resp.status) - if len(response_body['elements']) >= 3: - break - time.sleep(constants.RETRY_WAIT_SECS) - if i >= constants.MAX_RETRIES - 1: - self.fail("Timeout creating alarms, required 3 but found {}".format( - len(response_body['elements']))) - - query_parms = '?metric_dimensions=' + dim_key - resp, response_body = self.monasca_client.list_alarms(query_parms) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=2) - dimension_sets = [] - for element in response_body['elements']: - self.assertEqual(metric_name, element['metrics'][0]['name']) - dimension_sets.append(element['metrics'][0]['dimensions']) - self.assertIn(metric_1['dimensions'], dimension_sets) - self.assertIn(metric_2['dimensions'], dimension_sets) - self.assertNotIn(metric_3['dimensions'], dimension_sets) - - @decorators.attr(type="gate") - def test_list_alarms_by_metric_dimensions_multi_value(self): - metric_name = data_utils.rand_name('metric') - match_by_key = data_utils.rand_name('key') - dim_key = data_utils.rand_name('key') - dim_value_1 = data_utils.rand_name('value') - dim_value_2 = data_utils.rand_name('value') - alarm_def = helpers.create_alarm_definition( - name=data_utils.rand_name('definition'), - expression=metric_name + " > 1", - match_by=[match_by_key]) - metric_1 = helpers.create_metric(metric_name, {match_by_key: data_utils.rand_name('value'), - dim_key: dim_value_1}) - metric_2 = helpers.create_metric(metric_name, {match_by_key: data_utils.rand_name('value'), - dim_key: dim_value_2}) - metric_3 = helpers.create_metric(metric_name, {match_by_key: data_utils.rand_name('value')}) - metrics = [metric_1, metric_2, metric_3] - resp, response_body = self.monasca_client.create_alarm_definitions(alarm_def) - self.assertEqual(201, resp.status) - # Ensure the new Alarm Definition gets to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - for i in range(constants.MAX_RETRIES): - resp, alarm_def_result = self.monasca_client.create_metrics(metrics) - self.assertEqual(204, resp.status) - resp, response_body = self.monasca_client.list_alarms('?metric_name=' + metric_name) - self.assertEqual(200, resp.status) - if len(response_body['elements']) >= 3: - break - time.sleep(constants.RETRY_WAIT_SECS) - if i >= constants.MAX_RETRIES - 1: - self.fail("Timeout creating alarms, required 3 but found {}".format( - len(response_body['elements']))) - - query_parms = '?metric_dimensions=' + dim_key + ':' + dim_value_1 + '|' + dim_value_2 - resp, response_body = self.monasca_client.list_alarms(query_parms) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=2) - dimension_sets = [] - for element in response_body['elements']: - self.assertEqual(metric_name, element['metrics'][0]['name']) - dimension_sets.append(element['metrics'][0]['dimensions']) - self.assertIn(metric_1['dimensions'], dimension_sets) - self.assertIn(metric_2['dimensions'], dimension_sets) - self.assertNotIn(metric_3['dimensions'], dimension_sets) - - @decorators.attr(type="gate") - def test_list_alarms_by_state(self): - helpers.delete_alarm_definitions(self.monasca_client) - self._create_alarms_for_test_alarms(num=3) - resp, response_body = self.monasca_client.list_alarms() - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=3) - elements = response_body['elements'] - len0 = len(elements) - query_parms = '?state=UNDETERMINED' - resp, response_body1 = self.monasca_client.list_alarms(query_parms) - len1 = len(response_body1['elements']) - self.assertEqual(200, resp.status) - query_parms = '?state=ok' - resp, response_body2 = self.monasca_client.list_alarms(query_parms) - len2 = len(response_body2['elements']) - self.assertEqual(200, resp.status) - query_parms = '?state=ALARM' - resp, response_body3 = self.monasca_client.list_alarms(query_parms) - len3 = len(response_body3['elements']) - self.assertEqual(200, resp.status) - self.assertEqual(len0, len1 + len2 + len3) - - @decorators.attr(type="gate") - def test_list_alarms_by_severity(self): - metric_name = data_utils.rand_name("severity-metric") - alarm_defs = [] - alarm_defs.append(helpers.create_alarm_definition( - name=data_utils.rand_name("alarm-severity"), - expression=metric_name + " > 12", - severity='LOW' - )) - alarm_defs.append(helpers.create_alarm_definition( - name=data_utils.rand_name("alarm-severity"), - expression=metric_name + " > 12", - severity='MEDIUM' - )) - alarm_defs.append(helpers.create_alarm_definition( - name=data_utils.rand_name("alarm-severity"), - expression=metric_name + " > 12", - severity='HIGH' - )) - alarm_defs.append(helpers.create_alarm_definition( - name=data_utils.rand_name("alarm-severity"), - expression=metric_name + " > 12", - severity='CRITICAL' - )) - - alarm_def_ids = [] - for definition in alarm_defs: - resp, response_body = self.monasca_client.create_alarm_definitions(definition) - self.assertEqual(201, resp.status) - alarm_def_ids.append(response_body['id']) - - # Ensure the new Alarm Definitions get to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - metric = helpers.create_metric(name=metric_name, - value=14) - resp, response_body = self.monasca_client.create_metrics(metric) - self.assertEqual(204, resp.status) - for def_id in alarm_def_ids: - self._wait_for_alarms(1, def_id) - - query_parms = '?severity=LOW' - resp, response_body = self.monasca_client.list_alarms(query_parms) - self.assertEqual(200, resp.status) - for alarm in response_body['elements']: - self.assertEqual('LOW', alarm['alarm_definition']['severity']) - - query_parms = '?severity=HIGH' - resp, response_body = self.monasca_client.list_alarms(query_parms) - self.assertEqual(200, resp.status) - for alarm in response_body['elements']: - self.assertEqual('HIGH', alarm['alarm_definition']['severity']) - - query_parms = '?severity=CRITICAL' - resp, response_body = self.monasca_client.list_alarms(query_parms) - self.assertEqual(200, resp.status) - for alarm in response_body['elements']: - self.assertEqual('CRITICAL', alarm['alarm_definition']['severity']) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_alarms_by_severity_invalid_severity(self): - query_parms = '?severity=false_severity' - self.assertRaises(exceptions.UnprocessableEntity, self.monasca_client.list_alarms, - query_parms) - - @decorators.attr(type="gate") - def test_list_alarms_by_severity_multiple_values(self): - metric_name = data_utils.rand_name("severity-metric") - alarm_defs = [] - alarm_defs.append(helpers.create_alarm_definition( - name=data_utils.rand_name("alarm-severity"), - expression=metric_name + " > 12", - severity='LOW' - )) - alarm_defs.append(helpers.create_alarm_definition( - name=data_utils.rand_name("alarm-severity"), - expression=metric_name + " > 12", - severity='MEDIUM' - )) - alarm_defs.append(helpers.create_alarm_definition( - name=data_utils.rand_name("alarm-severity"), - expression=metric_name + " > 12", - severity='HIGH' - )) - alarm_defs.append(helpers.create_alarm_definition( - name=data_utils.rand_name("alarm-severity"), - expression=metric_name + " > 12", - severity='CRITICAL' - )) - - alarm_def_ids = [] - for definition in alarm_defs: - resp, response_body = self.monasca_client.create_alarm_definitions(definition) - self.assertEqual(201, resp.status) - alarm_def_ids.append(response_body['id']) - - # Ensure the new Alarm Definitions get to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - metric = helpers.create_metric(name=metric_name, - value=14) - resp, response_body = self.monasca_client.create_metrics(metric) - self.assertEqual(204, resp.status) - for def_id in alarm_def_ids: - self._wait_for_alarms(1, def_id) - - query_parms = '?severity=LOW|MEDIUM' - resp, response_body = self.monasca_client.list_alarms(query_parms) - self.assertEqual(200, resp.status) - for alarm in response_body['elements']: - self.assertIn(alarm['alarm_definition']['severity'], ['LOW', 'MEDIUM']) - - query_parms = '?severity=HIGH|CRITICAL' - resp, response_body = self.monasca_client.list_alarms(query_parms) - self.assertEqual(200, resp.status) - for alarm in response_body['elements']: - self.assertIn(alarm['alarm_definition']['severity'], ['HIGH', 'CRITICAL']) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_alarms_by_severity_multiple_values_invalid_severity(self): - query_parms = '?severity=false_severity|MEDIUM' - self.assertRaises(exceptions.UnprocessableEntity, self.monasca_client.list_alarms, - query_parms) - - query_parms = '?severity=MEDIUM|false_severity' - self.assertRaises(exceptions.UnprocessableEntity, self.monasca_client.list_alarms, - query_parms) - - query_parms = '?severity=LOW|false_severity|HIGH' - self.assertRaises(exceptions.UnprocessableEntity, self.monasca_client.list_alarms, - query_parms) - - @decorators.attr(type="gate") - def test_list_alarms_by_lifecycle_state(self): - alarm_definition_ids, expected_metric \ - = self._create_alarms_for_test_alarms(num=1) - query_param = '?alarm_definition_id=' + str(alarm_definition_ids[0]) - resp, response_body = self.monasca_client.list_alarms(query_param) - self.assertEqual(200, resp.status) - alarm_id = response_body['elements'][0]['id'] - self.monasca_client.patch_alarm(id=alarm_id, lifecycle_state="OPEN") - query_parms = '?alarm_definition_id=' + str( - alarm_definition_ids[0]) + '&lifecycle_state=OPEN' - resp, response_body = self.monasca_client.list_alarms(query_parms) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=1) - element = response_body['elements'][0] - metric = element['metrics'][0] - self._verify_metric_in_alarm(metric, expected_metric) - self.assertEqual(alarm_definition_ids[0], - element['alarm_definition']['id']) - - @decorators.attr(type="gate") - def test_list_alarms_by_link(self): - alarm_definition_ids, expected_metric \ - = self._create_alarms_for_test_alarms(num=1) - query_param = '?alarm_definition_id=' + str(alarm_definition_ids[0]) - resp, response_body = self.monasca_client.list_alarms(query_param) - self.assertEqual(200, resp.status) - alarm_id = response_body['elements'][0]['id'] - self.monasca_client.patch_alarm( - id=alarm_id, link="http://somesite.com/this-alarm-info") - query_parms = '?link=http://somesite.com/this-alarm-info' - resp, response_body = self.monasca_client.list_alarms(query_parms) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=1) - element = response_body['elements'][0] - metric = element['metrics'][0] - self._verify_metric_in_alarm(metric, expected_metric) - self.assertEqual(alarm_definition_ids[0], - element['alarm_definition']['id']) - - @decorators.attr(type="gate") - def test_list_alarms_by_state_updated_start_time(self): - alarm_definition_ids, expected_metric \ - = self._create_alarms_for_test_alarms(num=1) - query_param = '?alarm_definition_id=' + str(alarm_definition_ids[0]) - resp, response_body = self.monasca_client.list_alarms(query_param) - self.assertEqual(200, resp.status) - element = response_body['elements'][0] - state_updated_start_time = element['state_updated_timestamp'] - query_parms = '?alarm_definition_id=' + str(alarm_definition_ids[0])\ - + '&state_updated_timestamp=' + \ - str(state_updated_start_time) - resp, response_body = self.monasca_client.list_alarms(query_parms) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=1) - first_element = response_body['elements'][0] - self.assertEqual(element, first_element) - metric = element['metrics'][0] - self._verify_metric_in_alarm(metric, expected_metric) - self.assertEqual(alarm_definition_ids[0], - element['alarm_definition']['id']) - - @decorators.attr(type="gate") - def test_list_alarms_by_offset_limit(self): - definition_ids, expected_metric = self._create_alarms_for_test_alarms(num=3) - resp, response_body = self.monasca_client.list_alarms('?metric_name=' + - expected_metric['name']) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=3) - elements = response_body['elements'] - second_element = elements[1] - offset = 1 - limit = 1 - query_parms = '?metric_name=' + expected_metric['name'] + \ - '&offset=' + str(offset) + '&limit=' + str(limit) - resp, response_body1 = self.monasca_client.list_alarms(query_parms) - elements = response_body1['elements'] - self.assertEqual(1, len(elements)) - self.assertEqual(elements[0]['id'], second_element['id']) - self.assertEqual(elements[0], second_element) - links = response_body1['links'] - next_offset = None - next_limit = None - for link in links: - if link['rel'] == 'next': - next_offset = helpers.get_query_param(link['href'], 'offset') - next_limit = helpers.get_query_param(link['href'], 'limit') - self.assertEqual(str(offset + limit), next_offset) - self.assertEqual(str(limit), next_limit) - - @decorators.attr(type="gate") - def test_get_alarm(self): - alarm_definition_ids, expected_metric \ - = self._create_alarms_for_test_alarms(num=1) - query_param = '?alarm_definition_id=' + str(alarm_definition_ids[0]) - resp, response_body = self.monasca_client.list_alarms(query_param) - self.assertEqual(200, resp.status) - element = response_body['elements'][0] - alarm_id = element['id'] - resp, response_body = self.monasca_client.get_alarm(alarm_id) - self.assertEqual(200, resp.status) - self._verify_alarm_keys(response_body) - metric = element['metrics'][0] - self._verify_metric_in_alarm(metric, expected_metric) - - @decorators.attr(type="gate") - def test_list_alarms_sort_by(self): - alarm_definition_ids, expected_metric = self._create_alarms_for_test_alarms(num=3) - resp, response_body = self.monasca_client.list_alarms('?metric_name=' + - expected_metric['name']) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=3) - - resp, response_body = self.monasca_client.list_alarms('?metric_name=' + - expected_metric['name'] + - '&sort_by=created_timestamp') - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=3) - - elements = response_body['elements'] - last_timestamp = elements[0]['created_timestamp'] - for element in elements: - assert element['created_timestamp'] >= last_timestamp, \ - "Created_timestamps are not in sorted " \ - "order {} came before {}".format(last_timestamp, element['created_timestamp']) - last_timestamp = element['created_timestamp'] - - # Set link and lifecycle_state to sort in opposite order - self.monasca_client.patch_alarm(elements[0]['id'], lifecycle_state='3', link='2') - self.monasca_client.patch_alarm(elements[1]['id'], lifecycle_state='2', link='2') - self.monasca_client.patch_alarm(elements[2]['id'], lifecycle_state='4', link='1') - for iter in range(2): - sort_by_params = 'link,lifecycle_state' - if iter == 1: - query_parms = urlparse.urlencode([('sort_by', sort_by_params)]) - else: - query_parms = 'sort_by=' + sort_by_params - resp, response_body = self.monasca_client.list_alarms( - '?metric_name=' + expected_metric['name'] + '&' + query_parms) - elements = response_body['elements'] - self.assertEqual(3, len(elements)) - self.assertEqual('1', elements[0]['link']) - self.assertEqual('4', elements[0]['lifecycle_state']) - self.assertEqual('2', elements[1]['link']) - self.assertEqual('2', elements[1]['lifecycle_state']) - self.assertEqual('2', elements[2]['link']) - self.assertEqual('3', elements[2]['lifecycle_state']) - - allowed_sort_by = {'alarm_id', 'alarm_definition_id', 'alarm_definition_name', - 'state', 'severity', 'lifecycle_state', 'link', - 'state_updated_timestamp', 'updated_timestamp', - 'created_timestamp'} - for sort_by in allowed_sort_by: - resp, response_body = self.monasca_client.list_alarms( - '?metric_name=' + expected_metric['name'] + '&sort_by=' + sort_by) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=3) - - elements = response_body['elements'] - last_sort_by = self._get_field_from_alarm_element(elements[0], sort_by) - for element in elements: - sort_by_field = self._get_field_from_alarm_element(element, sort_by) - assert sort_by_field >= last_sort_by, \ - "{} are not in sorted order {} came before {}".format(sort_by, - last_sort_by, - sort_by_field) - last_sort_by = sort_by_field - - @decorators.attr(type='gate') - def test_list_alarms_sort_by_asc_desc(self): - alarm_definition_ids, expected_metric = self._create_alarms_for_test_alarms(num=3) - resp, response_body = self.monasca_client.list_alarms('?metric_name=' + - expected_metric['name']) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=3) - - resp, response_body = self.monasca_client.list_alarms( - '?metric_name=' + expected_metric['name'] + - '&sort_by=' + urlparse.quote('created_timestamp asc')) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=3) - - elements = response_body['elements'] - last_timestamp = elements[0]['created_timestamp'] - for element in elements: - assert element['created_timestamp'] >= last_timestamp,\ - "Created_timestamps are not in ascending" \ - " order {} came before {}".format(last_timestamp, element['created_timestamp']) - last_timestamp = element['created_timestamp'] - - resp, response_body = self.monasca_client.list_alarms( - '?metric_name=' + expected_metric['name'] + - '&sort_by=' + urlparse.quote('created_timestamp desc')) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=3) - - elements = response_body['elements'] - last_timestamp = elements[0]['created_timestamp'] - for element in elements: - assert element['created_timestamp'] <= last_timestamp,\ - "Created_timestamps are not in descending" \ - " order {} came before {}".format(last_timestamp, element['created_timestamp']) - last_timestamp = element['created_timestamp'] - - @decorators.attr(type="gate") - def test_list_alarms_sort_by_offset_limit(self): - metric_1 = {'name': data_utils.rand_name('sorting-metric-1'), - 'dimensions': { - data_utils.rand_name('key-1'): data_utils.rand_name('value-1')}, - 'value': 3} - metric_2 = {'name': metric_1['name'], - 'dimensions': { - data_utils.rand_name('key-2'): data_utils.rand_name('value-2')}, - 'value': 3} - alarm_def = helpers.create_alarm_definition( - name=data_utils.rand_name('sorting-def'), - expression=metric_1['name'] + " < 12", - match_by=["hostname"] - ) - resp, response_body = self.monasca_client.create_alarm_definitions(alarm_def) - self.assertEqual(201, resp.status) - alarm_def_id = response_body['id'] - - # Ensure the new Alarm Definition gets to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - for i in range(3): - hostname = data_utils.rand_name('host') - metric_1['dimensions']['hostname'] = hostname - metric_2['dimensions']['hostname'] = hostname - metric_1['timestamp'] = int(time.time() * 1000) - metric_2['timestamp'] = int(time.time() * 1000) - resp, response_body = self.monasca_client.create_metrics([metric_1, metric_2]) - self.assertEqual(204, resp.status) - self._wait_for_alarms(3, alarm_def_id) - - resp, response_body = self.monasca_client.list_alarms('?alarm_definition_id=' + - alarm_def_id) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=3) - - resp, response_body = self.monasca_client.list_alarms('?alarm_definition_id=' + - alarm_def_id + - '&sort_by=alarm_id') - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=3) - - full_elements = response_body['elements'] - previous_id = full_elements[0]['id'] - for element in full_elements[1:]: - assert element['id'] >= previous_id, \ - "IDs are not in sorted order {} came before {}".format(previous_id, - element['id']) - previous_id = element['id'] - - resp, response_body = self.monasca_client.list_alarms('?alarm_definition_id=' + - alarm_def_id + - '&sort_by=alarm_id&limit=1') - self.assertEqual(200, resp.status) - elements = response_body['elements'] - self.assertEqual(1, len(elements)) - self.assertEqual(full_elements[0]['id'], elements[0]['id']) - - resp, response_body = self.monasca_client.list_alarms('?alarm_definition_id=' + - alarm_def_id + - '&sort_by=alarm_id&offset=1') - self.assertEqual(200, resp.status) - elements = response_body['elements'] - self.assertEqual(2, len(elements)) - self.assertEqual(full_elements[1]['id'], elements[0]['id']) - - resp, response_body = self.monasca_client.list_alarms( - '?alarm_definition_id=' + alarm_def_id + '&sort_by=state_updated_timestamp&offset=1') - self.assertEqual(200, resp.status) - elements = response_body['elements'] - self.assertEqual(2, len(elements)) - - @decorators.attr(type="gate") - def test_list_alarms_invalid_sort_by(self): - query_parms = '?sort_by=not_valid_field' - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_alarms, query_parms) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_get_alarm_with_invalid_id(self): - alarm_id = data_utils.rand_name() - self.assertRaises(exceptions.NotFound, self.monasca_client.get_alarm, - alarm_id) - - @decorators.attr(type="gate") - def test_update_alarm(self): - alarm_definition_ids, expected_metric \ - = self._create_alarms_for_test_alarms(num=1) - query_param = '?alarm_definition_id=' + str(alarm_definition_ids[0]) - resp, response_body = self.monasca_client.list_alarms(query_param) - self.assertEqual(200, resp.status) - element = response_body['elements'][0] - alarm_id = element['id'] - updated_state = "ALARM" - updated_lifecycle_state = "OPEN" - updated_link = "http://somesite.com" - resp, response_body = self.monasca_client.update_alarm( - id=alarm_id, state=updated_state, - lifecycle_state=updated_lifecycle_state, link=updated_link) - self.assertEqual(200, resp.status) - self._verify_alarm_keys(response_body) - # Validate fields updated - resp, response_body = self.monasca_client.list_alarms(query_param) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=1) - element = response_body['elements'][0] - self.assertEqual(updated_state, element['state']) - self.assertEqual(updated_lifecycle_state, element['lifecycle_state']) - self.assertEqual(updated_link, element['link']) - - @decorators.attr(type="gate") - def test_patch_alarm(self): - alarm_definition_ids, expected_metric \ - = self._create_alarms_for_test_alarms(num=1) - query_param = '?alarm_definition_id=' + str(alarm_definition_ids[0]) - resp, response_body = self.monasca_client.list_alarms(query_param) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - alarm_id = elements[0]['id'] - patch_link = "http://somesite.com" - resp, response_body = self.monasca_client.patch_alarm( - id=alarm_id, link=patch_link) - self.assertEqual(200, resp.status) - self._verify_alarm_keys(response_body) - # Validate the field patched - resp, response_body = self.monasca_client.list_alarms(query_param) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=1) - self.assertEqual(patch_link, response_body['elements'][0]['link']) - - @decorators.attr(type="gate") - def test_delete_alarm(self): - alarm_definition_ids, expected_metric \ - = self._create_alarms_for_test_alarms(num=1) - query_param = '?alarm_definition_id=' + str(alarm_definition_ids[0]) - resp, response_body = self.monasca_client.list_alarms(query_param) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - alarm_id = elements[0]['id'] - resp, response_body = self.monasca_client.delete_alarm(alarm_id) - self.assertEqual(204, resp.status) - resp, response_body = self.monasca_client.list_alarms(query_param) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=0) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_delete_alarm_with_invalid_id(self): - id = data_utils.rand_name() - self.assertRaises(exceptions.NotFound, - self.monasca_client.delete_alarm, id) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_patch_alarm_with_invalid_id(self): - id = data_utils.rand_name() - self.assertRaises(exceptions.NotFound, - self.monasca_client.patch_alarm, id=id, - lifecycle_state="OPEN") - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_update_alarm_with_invalid_id(self): - alarm_id = data_utils.rand_name() - updated_state = "ALARM" - updated_lifecycle_state = "OPEN" - updated_link = "http://somesite.com" - self.assertRaises(exceptions.NotFound, - self.monasca_client.update_alarm, - id=alarm_id, state=updated_state, - lifecycle_state=updated_lifecycle_state, - link=updated_link) - - @decorators.attr(type="gate") - def test_create_alarms_with_match_by(self): - # Create an alarm definition with no match_by - name = data_utils.rand_name('alarm_definition_1') - expression = "max(cpu.idle_perc{service=monitoring}) < 20" - alarm_definition = helpers.create_alarm_definition( - name=name, description="description", expression=expression) - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition) - alarm_definition_id = response_body['id'] - self._create_metrics_for_match_by( - num=1, alarm_definition_id=alarm_definition_id) - query_param = '?alarm_definition_id=' + str(alarm_definition_id) - resp, response_body = self.monasca_client.list_alarms(query_param) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=1) - elements = response_body['elements'] - metrics = elements[0]['metrics'] - self.assertEqual(len(metrics), 2) - self.assertNotEqual(metrics[0], metrics[1]) - - # Create an alarm definition with match_by - name = data_utils.rand_name('alarm_definition_2') - expression = "max(cpu.idle_perc{service=monitoring}) < 20" - match_by = ['hostname'] - alarm_definition = helpers.create_alarm_definition( - name=name, description="description", expression=expression, - match_by=match_by) - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition) - alarm_definition_id = response_body['id'] - # create some metrics - self._create_metrics_for_match_by( - num=2, alarm_definition_id=alarm_definition_id) - query_param = '?alarm_definition_id=' + str(alarm_definition_id) - resp, response_body = self.monasca_client.list_alarms(query_param) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=2) - elements = response_body['elements'] - self.assertEqual(len(elements[0]['metrics']), 1) - self.assertEqual(len(elements[1]['metrics']), 1) - self.assertNotEqual(elements[0]['metrics'], elements[1]['metrics']) - - @decorators.attr(type="gate") - def test_create_alarms_with_sub_expressions_and_match_by(self): - # Create an alarm definition with sub-expressions and match_by - name = data_utils.rand_name('alarm_definition_3') - expression = "max(cpu.idle_perc{service=monitoring}) < 10 or " \ - "max(cpu.user_perc{service=monitoring}) > 60" - match_by = ['hostname'] - alarm_definition = helpers.create_alarm_definition( - name=name, description="description", expression=expression, - match_by=match_by) - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition) - alarm_definition_id = response_body['id'] - self._create_metrics_for_match_by_sub_expressions( - num=2, alarm_definition_id=alarm_definition_id) - query_param = '?alarm_definition_id=' + str(alarm_definition_id) - resp, response_body = self.monasca_client.list_alarms(query_param) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=2) - elements = response_body['elements'] - hostnames = [] - for i in range(2): - self.assertEqual(len(elements[i]['metrics']), 2) - for i in range(2): - for j in range(2): - hostnames.append(elements[i]['metrics'][j]['dimensions'][ - 'hostname']) - self.assertEqual(hostnames[0], hostnames[1]) - self.assertEqual(hostnames[2], hostnames[3]) - self.assertNotEqual(hostnames[0], hostnames[2]) - - @decorators.attr(type="gate") - def test_create_alarms_with_match_by_list(self): - # Create an alarm definition with match_by as a list - name = data_utils.rand_name('alarm_definition') - expression = "max(cpu.idle_perc{service=monitoring}) < 10" - match_by = ['hostname', 'device'] - alarm_definition = helpers.create_alarm_definition( - name=name, description="description", expression=expression, - match_by=match_by) - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition) - alarm_definition_id = response_body['id'] - query_param = '?alarm_definition_id=' + str(alarm_definition_id) - # create some metrics - self._create_metrics_for_match_by_sub_expressions_list( - num=4, alarm_definition_id=alarm_definition_id) - resp, response_body = self.monasca_client.list_alarms(query_param) - self._verify_list_alarms_elements(resp, response_body, - expect_num_elements=4) - elements = response_body['elements'] - dimensions = [] - for i in range(4): - self.assertEqual(len(elements[i]['metrics']), 1) - dimensions.append(elements[i]['metrics'][0]['dimensions']) - for i in range(4): - for j in range(4): - if i != j: - self.assertNotEqual(dimensions[i], dimensions[j]) - - @decorators.attr(type="gate") - def test_verify_deterministic_alarm(self): - metric_name = data_utils.rand_name('log.fancy') - metric_dimensions = {'service': 'monitoring', - 'hostname': 'mini-mon'} - - name = data_utils.rand_name('alarm_definition') - expression = ('count(%s{service=monitoring},deterministic) > 10' - % metric_name) - match_by = ['hostname', 'device'] - description = 'deterministic' - - alarm_definition = helpers.create_alarm_definition( - name=name, description=description, - expression=expression, match_by=match_by) - - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition) - - alarm_definition_id = response_body['id'] - query_param = '?alarm_definition_id=' + str(alarm_definition_id) - - # Ensure the new Alarm Definition gets to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - - # 1. ensure alarm was not created - resp, response_body = self.monasca_client.list_alarms(query_param) - self._verify_list_alarms_elements(resp, response_body, 0) - - # 2. put some metrics here to create it, should be in ok - metrics_count = 5 - for it in range(0, metrics_count): - metric = helpers.create_metric(name=metric_name, - value=1.0, - dimensions=metric_dimensions) - self.monasca_client.create_metrics(metric) - - self._wait_for_alarms(1, alarm_definition_id) - - resp, response_body = self.monasca_client.list_alarms(query_param) - self._verify_list_alarms_elements(resp, response_body, 1) - element = response_body['elements'][0] - - self.assertEqual('OK', element['state']) - - # 3. exceed threshold - metrics_count = 20 - for it in range(0, metrics_count): - metric = helpers.create_metric(name=metric_name, - value=1.0, - dimensions=metric_dimensions) - self.monasca_client.create_metrics(metric) - - self._wait_for_alarms(1, alarm_definition_id) - - resp, response_body = self.monasca_client.list_alarms(query_param) - self._verify_list_alarms_elements(resp, response_body, 1) - element = response_body['elements'][0] - - self.assertEqual('ALARM', element['state']) - - def _verify_list_alarms_elements(self, resp, response_body, - expect_num_elements): - self.assertEqual(200, resp.status) - self.assertTrue(set(['links', 'elements']) == - set(response_body)) - error_msg = ("Failed: {} alarm is needed and current number " - "of alarm is {}").format(expect_num_elements, - len(response_body['elements'])) - self.assertEqual(len(response_body['elements']), - expect_num_elements, error_msg) - - def _create_alarms_for_test_alarms(self, num): - metric_name = data_utils.rand_name('name') - key = data_utils.rand_name('key') - value = data_utils.rand_name('value') - alarm_definition_ids = [] - for i in range(num): - # create an alarm definition - expression = "max(" + metric_name + ") > 0" - name = data_utils.rand_name('name-1') - alarm_definition = helpers.create_alarm_definition( - name=name, expression=expression) - resp, response_body = self.monasca_client.create_alarm_definitions( - alarm_definition) - alarm_definition_ids.append(response_body['id']) - expected_metric = helpers.create_metric(name=metric_name, - dimensions={key: value}) - # Ensure the new Alarm Definitions get to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - # create some metrics - for j in range(num): - for i in range(constants.MAX_RETRIES): - self.monasca_client.create_metrics(expected_metric) - time.sleep(constants.RETRY_WAIT_SECS) - query_param = '?alarm_definition_id=' + \ - str(alarm_definition_ids[j]) - resp, response_body = self.monasca_client.list_alarms( - query_param) - elements = response_body['elements'] - if len(elements) >= 1: - break - return alarm_definition_ids, expected_metric - - def _create_metrics_for_match_by(self, num, alarm_definition_id): - # Ensure the new Alarm Definition gets to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - metric1 = helpers.create_metric( - name='cpu.idle_perc', - dimensions={'service': 'monitoring', - 'hostname': 'mini-mon'}) - metric2 = helpers.create_metric( - name='cpu.idle_perc', - dimensions={'service': 'monitoring', - 'hostname': 'devstack'}) - self.monasca_client.create_metrics(metric1) - self.monasca_client.create_metrics(metric2) - self._wait_for_alarms(num, alarm_definition_id) - - def _create_metrics_for_match_by_sub_expressions(self, num, - alarm_definition_id): - # Ensure the new Alarm Definition gets to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - metric1 = helpers.create_metric( - name='cpu.idle_perc', - dimensions={'service': 'monitoring', - 'hostname': 'mini-mon'}) - metric2 = helpers.create_metric( - name='cpu.idle_perc', - dimensions={'service': 'monitoring', - 'hostname': 'devstack'}) - self.monasca_client.create_metrics(metric1) - self.monasca_client.create_metrics(metric2) - metric3 = helpers.create_metric( - name='cpu.user_perc', - dimensions={'service': 'monitoring', - 'hostname': 'mini-mon'}) - metric4 = helpers.create_metric( - name='cpu.user_perc', - dimensions={'service': 'monitoring', - 'hostname': 'devstack'}) - self.monasca_client.create_metrics(metric3) - self.monasca_client.create_metrics(metric4) - self._wait_for_alarms(num, alarm_definition_id) - - def _create_metrics_for_match_by_sub_expressions_list(self, num, - alarm_definition_id): - # Ensure the new Alarm Definition gets to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - # create some metrics - metric1 = helpers.create_metric( - name='cpu.idle_perc', - dimensions={'service': 'monitoring', - 'hostname': 'mini-mon', - 'device': '/dev/sda1'}) - metric2 = helpers.create_metric( - name='cpu.idle_perc', - dimensions={'service': 'monitoring', - 'hostname': 'devstack', - 'device': '/dev/sda1'}) - metric3 = helpers.create_metric( - name='cpu.idle_perc', - dimensions={'service': 'monitoring', - 'hostname': 'mini-mon', - 'device': 'tmpfs'}) - metric4 = helpers.create_metric( - name='cpu.idle_perc', - dimensions={'service': 'monitoring', - 'hostname': 'devstack', - 'device': 'tmpfs'}) - self.monasca_client.create_metrics(metric1) - self.monasca_client.create_metrics(metric2) - self.monasca_client.create_metrics(metric3) - self.monasca_client.create_metrics(metric4) - self._wait_for_alarms(num, alarm_definition_id) - - def _wait_for_alarms(self, num, alarm_definition_id): - query_param = '?alarm_definition_id=' + str(alarm_definition_id) - for i in range(constants.MAX_RETRIES): - time.sleep(constants.RETRY_WAIT_SECS) - resp, response_body = self.monasca_client.\ - list_alarms(query_param) - elements = response_body['elements'] - if len(elements) >= num: - break - - def _verify_alarm_keys(self, response_body): - expected_keys = ['id', - 'links', - 'alarm_definition', - 'metrics', - 'state', - 'lifecycle_state', - 'link', - 'state_updated_timestamp', - 'updated_timestamp', - 'created_timestamp'] - for key in expected_keys: - self.assertIn(key, response_body) - - def _verify_metric_in_alarm(self, metric, expected_metric): - self.assertEqual(metric['dimensions'], expected_metric['dimensions']) - self.assertEqual(metric['name'], expected_metric['name']) - - def _get_field_from_alarm_element(self, element, sort_by): - if sort_by == 'alarm_id': - return element['id'] - elif sort_by == 'alarm_definition_id': - return element['alarm_definition']['id'] - elif sort_by == 'alarm_definition_name': - return element['alarm_definition']['name'] - elif sort_by == 'severity': - return element['alarm_definition']['severity'] - else: - return element[sort_by] diff --git a/monasca_tempest_tests/tests/api/test_alarms_count.py b/monasca_tempest_tests/tests/api/test_alarms_count.py deleted file mode 100644 index 0187152..0000000 --- a/monasca_tempest_tests/tests/api/test_alarms_count.py +++ /dev/null @@ -1,373 +0,0 @@ -# (C) Copyright 2016-2018 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time -import urllib.parse as parse - -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators -from tempest.lib import exceptions - -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import constants -from monasca_tempest_tests.tests.api import helpers - - -GROUP_BY_ALLOWED_PARAMS = {'alarm_definition_id', 'name', 'state', 'severity', - 'link', 'lifecycle_state', 'metric_name', - 'dimension_name', 'dimension_value'} - - -class TestAlarmsCount(base.BaseMonascaTest): - - @classmethod - def resource_setup(cls): - super(TestAlarmsCount, cls).resource_setup() - - num_hosts = 20 - - alarm_definitions = [] - expected_alarm_counts = [] - metrics_to_send = [] - - # OK, LOW - expression = "max(test_metric_01) > 10" - name = data_utils.rand_name('test-counts-01') - alarm_definitions.append(helpers.create_alarm_definition( - name=name, - expression=expression, - severity='LOW', - match_by=['hostname', 'unique'])) - for i in range(100): - metrics_to_send.append(helpers.create_metric( - name='test_metric_01', - dimensions={'hostname': 'test_' + str(i % num_hosts), - 'unique': str(i)}, - value=1 - )) - expected_alarm_counts.append(100) - - # ALARM, MEDIUM - expression = "max(test_metric_02) > 10" - name = data_utils.rand_name('test-counts-02') - alarm_definitions.append(helpers.create_alarm_definition( - name=name, - expression=expression, - severity='MEDIUM', - match_by=['hostname', 'unique'])) - for i in range(75): - metrics_to_send.append(helpers.create_metric( - name='test_metric_02', - dimensions={'hostname': 'test_' + str(i % num_hosts), - 'unique': str(i)}, - value=11 - )) - # append again to move from undetermined to alarm - metrics_to_send.append(helpers.create_metric( - name='test_metric_02', - dimensions={'hostname': 'test_' + str(i % num_hosts), - 'unique': str(i)}, - value=11 - )) - expected_alarm_counts.append(75) - - # OK, HIGH, shared dimension - expression = "max(test_metric_03) > 100" - name = data_utils.rand_name('test_counts-03') - alarm_definitions.append(helpers.create_alarm_definition( - name=name, - expression=expression, - severity='HIGH', - match_by=['hostname', 'unique'])) - for i in range(50): - metrics_to_send.append(helpers.create_metric( - name='test_metric_03', - dimensions={'hostname': 'test_' + str(i % num_hosts), - 'unique': str(i), - 'height': '55'}, - value=i - )) - expected_alarm_counts.append(50) - - # UNDERTERMINED, CRITICAL - expression = "max(test_metric_undet) > 100" - name = data_utils.rand_name('test-counts-04') - alarm_definitions.append(helpers.create_alarm_definition( - name=name, - expression=expression, - severity='CRITICAL', - match_by=['hostname', 'unique'])) - for i in range(25): - metrics_to_send.append(helpers.create_metric( - name='test_metric_undet', - dimensions={'hostname': 'test_' + str(i % num_hosts), - 'unique': str(i)}, - value=1 - )) - expected_alarm_counts.append(25) - - # create alarm definitions - cls.alarm_definition_ids = [] - for definition in alarm_definitions: - resp, response_body = cls.monasca_client.create_alarm_definitions( - definition) - if resp.status == 201: - cls.alarm_definition_ids.append(response_body['id']) - else: - msg = "Failed to create alarm_definition during setup: {} {}".format(resp.status, - response_body) - assert False, msg - - # Give Thresh time to process the new Alarm Definitions - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - - # create alarms - for metric in metrics_to_send: - metric['timestamp'] = int(time.time() * 1000) - cls.monasca_client.create_metrics(metric) - # ensure metric timestamps are unique - time.sleep(0.01) - - # check that alarms exist - time_out = time.time() + 70 - while time.time() < time_out: - setup_complete = True - alarm_count = 0 - for i in range(len(cls.alarm_definition_ids)): - resp, response_body = cls.monasca_client.list_alarms( - '?alarm_definition_id=' + cls.alarm_definition_ids[i]) - if resp.status != 200: - msg = "Error listing alarms: {} {}".format(resp.status, response_body) - assert False, msg - if len(response_body['elements']) < expected_alarm_counts[i]: - setup_complete = False - alarm_count += len(response_body['elements']) - break - - if setup_complete: - # allow alarm transitions to occur - # time.sleep(15) - return - - msg = "Failed to create all specified alarms" \ - " during setup, alarm_count was {}".format(alarm_count) - assert False, msg - - @classmethod - def resource_cleanup(cls): - super(TestAlarmsCount, cls).resource_cleanup() - - def _verify_counts_format(self, response_body, group_by=None, expected_length=None): - expected_keys = ['links', 'counts', 'columns'] - for key in expected_keys: - self.assertIn(key, response_body) - self.assertIsInstance(response_body[key], list) - - expected_columns = ['count'] - if isinstance(group_by, list): - expected_columns.extend(group_by) - self.assertEqual(expected_columns, response_body['columns']) - - if expected_length is not None: - self.assertEqual(expected_length, len(response_body['counts'])) - else: - expected_length = len(response_body['counts']) - - for i in range(expected_length): - self.assertEqual(len(expected_columns), len(response_body['counts'][i])) - - # test with no params - @decorators.attr(type='gate') - def test_count(self): - resp, response_body = self.monasca_client.count_alarms() - self.assertEqual(200, resp.status) - self._verify_counts_format(response_body) - self.assertEqual(250, response_body['counts'][0][0]) - - # test with each group_by parameter singularly - @decorators.attr(type='gate') - def test_group_by_singular(self): - resp, response_body = self.monasca_client.list_alarms("?state=ALARM") - self.assertEqual(200, resp.status) - alarm_state_count = len(response_body['elements']) - resp, response_body = self.monasca_client.list_alarms("?state=undetermined") - self.assertEqual(200, resp.status) - undet_state_count = len(response_body['elements']) - - resp, response_body = self.monasca_client.count_alarms("?group_by=state") - self.assertEqual(200, resp.status) - self._verify_counts_format(response_body, group_by=['state']) - - self.assertEqual('ALARM', response_body['counts'][0][1]) - self.assertEqual(alarm_state_count, response_body['counts'][0][0]) - self.assertEqual('UNDETERMINED', response_body['counts'][-1][1]) - self.assertEqual(undet_state_count, response_body['counts'][-1][0]) - - resp, response_body = self.monasca_client.count_alarms("?group_by=name") - self.assertEqual(200, resp.status) - self._verify_counts_format(response_body, group_by=['name'], expected_length=4) - - # test with group by a parameter that is not allowed - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_group_by_not_allowed(self): - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.count_alarms, "?group_by=not_allowed") - - # test with a few group_by fields - @decorators.attr(type='gate') - def test_group_by_multiple(self): - resp, response_body = self.monasca_client.list_alarms() - alarm_low_count = 0 - for alarm in response_body['elements']: - if alarm['state'] == 'ALARM' and alarm.get('severity', '') == 'LOW': - alarm_low_count += 1 - - # Using urlencode mimics the CLI behavior. Without the urlencode, falcon - # treats group_by as a list, with the urlencode it treats group_by as - # a string. The API needs to handle both. - # test_with_all_group_by_params tests multiple group_by without - # urlencode - query_params = parse.urlencode([('group_by', 'state,severity')]) - resp, response_body = self.monasca_client.count_alarms("?" + query_params) - self._verify_counts_format(response_body, group_by=['state', 'severity']) - - def run_count_test(self, query_string): - resp, response_body = self.monasca_client.list_alarms(query_string) - self.assertEqual(200, resp.status) - expected_count = len(response_body['elements']) - # Make sure something was found - self.assertTrue(expected_count > 0) - - resp, response_body = self.monasca_client.count_alarms(query_string) - self.assertEqual(200, resp.status) - self._verify_counts_format(response_body, expected_length=1) - self.assertEqual(expected_count, response_body['counts'][0][0]) - - # test filter by severity - @decorators.attr(type='gate') - def test_filter_severity(self): - self.run_count_test("?severity=LOW") - - # test filter by state - @decorators.attr(type='gate') - def test_filter_state(self): - self.run_count_test("?state=ALARM") - - # test filter by metric name - @decorators.attr(type='gate') - def test_filter_metric_name(self): - self.run_count_test("?metric_name=test_metric_01") - - # test with multiple metric dimensions - @decorators.attr(type='gate') - def test_filter_multiple_dimensions(self): - self.run_count_test("?metric_dimensions=hostname:test_1,unique:1") - - # test with multiple metric dimensions values - @decorators.attr(type='gate') - def test_filter_multiple_dimensions_values_1(self): - self.run_count_test("?metric_dimensions=hostname:test_1|test_2,unique:1") - - # test with multiple metric dimensions values (order should not matter) - @decorators.attr(type='gate') - def test_filter_multiple_dimensions_values_2(self): - self.run_count_test("?metric_dimensions=hostname:test_2|test_1,unique:1") - - # test with filter and group_by parameters - @decorators.attr(type='gate') - def test_filter_and_group_by_params(self): - resp, response_body = self.monasca_client.list_alarms("?state=ALARM") - self.assertEqual(200, resp.status) - expected_count = 0 - for element in response_body['elements']: - if element['alarm_definition']['severity'] == 'MEDIUM': - expected_count += 1 - - resp, response_body = self.monasca_client.count_alarms("?state=ALARM&group_by=severity") - self.assertEqual(200, resp.status) - self._verify_counts_format(response_body, group_by=['severity']) - self.assertEqual(expected_count, response_body['counts'][0][0]) - - @decorators.attr(type='gate') - def test_with_all_group_by_params(self): - resp, response_body = self.monasca_client.list_alarms() - self.assertEqual(200, resp.status) - expected_num_count = len(response_body['elements']) - - query_params = "?group_by=" + ','.join(GROUP_BY_ALLOWED_PARAMS) - resp, response_body = self.monasca_client.count_alarms(query_params) - self.assertEqual(200, resp.status) - self._verify_counts_format(response_body, group_by=list(GROUP_BY_ALLOWED_PARAMS)) - - # Expect duplicates - msg = "Not enough distinct counts. Expected at " \ - "least {}, found {}".format(expected_num_count, len(response_body['counts'])) - assert expected_num_count <= len(response_body['counts']), msg - - @decorators.attr(type='gate') - def test_limit(self): - resp, response_body = self.monasca_client.count_alarms( - "?group_by=metric_name,dimension_name,dimension_value") - self.assertEqual(200, resp.status) - self._verify_counts_format(response_body, - group_by=['metric_name', 'dimension_name', 'dimension_value']) - assert len(response_body['counts']) > 1, "Too few counts to test limit, found 1" - - resp, response_body = self.monasca_client.count_alarms( - "?group_by=metric_name,dimension_name,dimension_value&limit=1") - self.assertEqual(200, resp.status) - self._verify_counts_format(response_body, - group_by=['metric_name', 'dimension_name', 'dimension_value'], - expected_length=1) - - @decorators.attr(type='gate') - def test_offset(self): - resp, response_body = self.monasca_client.count_alarms( - "?group_by=metric_name,dimension_name,dimension_value") - self.assertEqual(200, resp.status) - self._verify_counts_format(response_body, - group_by=['metric_name', 'dimension_name', 'dimension_value']) - expected_counts = len(response_body['counts']) - 1 - - resp, response_body = self.monasca_client.count_alarms( - "?group_by=metric_name,dimension_name,dimension_value&offset=1") - self.assertEqual(200, resp.status) - self._verify_counts_format(response_body, - group_by=['metric_name', 'dimension_name', 'dimension_value'], - expected_length=expected_counts) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_invalid_offset(self): - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.count_alarms, - "?group_by=metric_name&offset=not_an_int") - - @decorators.attr(type='gate') - def test_limit_and_offset(self): - resp, response_body = self.monasca_client.count_alarms( - "?group_by=metric_name,dimension_name,dimension_value") - self.assertEqual(200, resp.status) - self._verify_counts_format(response_body, - group_by=['metric_name', 'dimension_name', 'dimension_value']) - expected_first_result = response_body['counts'][1] - - resp, response_body = self.monasca_client.count_alarms( - "?group_by=metric_name,dimension_name,dimension_value&offset=1&limit=5") - self.assertEqual(200, resp.status) - self._verify_counts_format(response_body, - group_by=['metric_name', 'dimension_name', 'dimension_value'], - expected_length=5) - self.assertEqual(expected_first_result, response_body['counts'][0]) diff --git a/monasca_tempest_tests/tests/api/test_alarms_state_history_one_transition.py b/monasca_tempest_tests/tests/api/test_alarms_state_history_one_transition.py deleted file mode 100644 index d35c47a..0000000 --- a/monasca_tempest_tests/tests/api/test_alarms_state_history_one_transition.py +++ /dev/null @@ -1,239 +0,0 @@ -# (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time - -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import constants -from monasca_tempest_tests.tests.api import helpers -from oslo_utils import timeutils -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - -NUM_ALARM_DEFINITIONS = 3 -MIN_HISTORY = 3 - - -class TestAlarmsStateHistoryOneTransition(base.BaseMonascaTest): - # Alarms state histories with one transition but different alarm - # definitions are needed for this test class. - - @classmethod - def resource_setup(cls): - super(TestAlarmsStateHistoryOneTransition, cls).resource_setup() - - for i in range(MIN_HISTORY): - alarm_definition = helpers.create_alarm_definition( - name=data_utils.rand_name('alarm_state_history' + str(i + 1)), - expression="min(name-" + str(i + 1) + ") < " + str(i + 1)) - cls.monasca_client.create_alarm_definitions(alarm_definition) - # Ensure the new Alarm Definitions get to the Threshold Engine - time.sleep(constants.ALARM_DEFINITION_CREATION_WAIT) - - num_transitions = 0 - for timer in range(constants.MAX_RETRIES): - for i in range(MIN_HISTORY): - # Create some metrics to prime the system and waiting for the - # alarms to be created and then for them to change state. - # MIN_HISTORY number of Alarms State History are needed. - metric = helpers.create_metric(name="name-" + str(i + 1)) - cls.monasca_client.create_metrics(metric) - # Ensure alarms transition at different times - time.sleep(0.1) - resp, response_body = cls.monasca_client.\ - list_alarms_state_history() - elements = response_body['elements'] - if len(elements) >= MIN_HISTORY: - return - else: - num_transitions = len(elements) - time.sleep(constants.RETRY_WAIT_SECS) - assert False, "Required {} alarm state transitions, but found {}".\ - format(MIN_HISTORY, num_transitions) - - @classmethod - def resource_cleanup(cls): - super(TestAlarmsStateHistoryOneTransition, cls).resource_cleanup() - - @decorators.attr(type="gate") - def test_list_alarms_state_history(self): - resp, response_body = self.monasca_client.list_alarms_state_history() - self.assertEqual(200, resp.status) - # Test response body - self.assertTrue(set(['links', 'elements']) == set(response_body)) - elements = response_body['elements'] - number_of_alarms = len(elements) - if number_of_alarms < 1: - error_msg = "Failed test_list_alarms_state_history: need " \ - "at least one alarms state history to test." - self.fail(error_msg) - else: - element = elements[0] - self.assertTrue(set(['id', 'alarm_id', 'metrics', 'old_state', - 'new_state', 'reason', 'reason_data', - 'timestamp', 'sub_alarms']) - == set(element)) - - @decorators.attr(type="gate") - def test_list_alarms_state_history_with_dimensions(self): - resp, response_body = self.monasca_client.list_alarms_state_history() - elements = response_body['elements'] - if elements: - element = elements[0] - dimension = element['metrics'][0]['dimensions'] - dimension_items = list(dimension.items()) - dimension_item = dimension_items[0] - dimension_item_0 = dimension_item[0] - dimension_item_1 = dimension_item[1] - name = element['metrics'][0]['name'] - - query_parms = '?dimensions=' + str(dimension_item_0) + ':' + str( - dimension_item_1) - resp, response_body = self.monasca_client.\ - list_alarms_state_history(query_parms) - name_new = response_body['elements'][0]['metrics'][0]['name'] - self.assertEqual(200, resp.status) - self.assertEqual(name, name_new) - else: - error_msg = "Failed test_list_alarms_state_history_with_" \ - "dimensions: need at least one alarms state history " \ - "to test." - self.fail(error_msg) - - @decorators.attr(type="gate") - def test_list_alarms_state_history_with_start_time(self): - # 1, get all histories - resp, all_response_body = self.monasca_client.\ - list_alarms_state_history() - all_elements = all_response_body['elements'] - - if len(all_elements) < 3: - error_msg = "Failed test_list_alarms_state_history_with_" \ - "start_time: need 3 or more alarms state history " \ - "to test." - self.fail(error_msg) - - # 2, query second(timestamp) <= x - min_element, second_element, max_element = \ - self._get_elements_with_min_max_timestamp(all_elements) - start_time = second_element['timestamp'] - query_params = '?start_time=' + str(start_time) - resp, selected_response_body = self.monasca_client.\ - list_alarms_state_history(query_params) - selected_elements = selected_response_body['elements'] - - # 3. compare #1 and #2 - expected_elements = all_elements - expected_elements.remove(min_element) - self.assertEqual(expected_elements, selected_elements) - - @decorators.attr(type="gate") - def test_list_alarms_state_history_with_end_time(self): - # 1, get all histories - resp, all_response_body = self.monasca_client.\ - list_alarms_state_history() - all_elements = all_response_body['elements'] - - if len(all_elements) < 3: - error_msg = "Failed test_list_alarms_state_history_with_" \ - "end_time: need 3 or more alarms state history " \ - "to test." - self.fail(error_msg) - - # 2, query x <= second(timestamp) - min_element, second_element, max_element = \ - self._get_elements_with_min_max_timestamp(all_elements) - end_time = second_element['timestamp'] - query_params = '?end_time=' + str(end_time) - resp, selected_response_body = self.monasca_client.\ - list_alarms_state_history(query_params) - selected_elements = selected_response_body['elements'] - - # 3. compare #1 and #2 - expected_elements = all_elements - expected_elements.remove(max_element) - self.assertEqual(expected_elements, selected_elements) - - @decorators.attr(type="gate") - def test_list_alarms_state_history_with_start_end_time(self): - # 1, get all histories - resp, all_response_body = self.monasca_client.\ - list_alarms_state_history() - all_elements = all_response_body['elements'] - - if len(all_elements) < 3: - error_msg = "Failed test_list_alarms_state_history_with_" \ - "start_end_time: need 3 or more alarms state history" \ - "to test." - self.fail(error_msg) - - # 2, query min(timestamp) <= x <= max(timestamp) - min_element, second_element, max_element = \ - self._get_elements_with_min_max_timestamp(all_elements) - start_time = min_element['timestamp'] - end_time = max_element['timestamp'] - query_params = '?start_time=' + str(start_time) + '&end_time=' + \ - str(end_time) - resp, selected_response_body = self.monasca_client.\ - list_alarms_state_history(query_params) - selected_elements = selected_response_body['elements'] - - # 3. compare #1 and #2 - self.assertEqual(all_elements, selected_elements) - - @decorators.attr(type="gate") - def test_list_alarms_state_history_with_offset_limit(self): - resp, response_body = self.monasca_client.list_alarms_state_history() - elements_set1 = response_body['elements'] - number_of_alarms = len(elements_set1) - if number_of_alarms >= MIN_HISTORY: - query_parms = '?limit=' + str(number_of_alarms) - resp, response_body = self.monasca_client.\ - list_alarms_state_history(query_parms) - self.assertEqual(200, resp.status) - elements_set2 = response_body['elements'] - self.assertEqual(number_of_alarms, len(elements_set2)) - for index in range(MIN_HISTORY - 1): - self.assertEqual(elements_set1[index], elements_set2[index]) - for index in range(MIN_HISTORY - 1): - alarm_history = elements_set2[index] - max_limit = len(elements_set2) - index - for limit in range(1, max_limit): - first_index = index + 1 - last_index = first_index + limit - expected_elements = elements_set2[first_index:last_index] - - query_parms = '?offset=' + str(alarm_history['timestamp'])\ - + '&limit=' + str(limit) - resp, response_body = self.\ - monasca_client.list_alarms_state_history(query_parms) - self.assertEqual(200, resp.status) - new_elements = response_body['elements'] - self.assertEqual(limit, len(new_elements)) - for i in range(len(expected_elements)): - self.assertEqual(expected_elements[i], new_elements[i]) - else: - error_msg = ("Failed test_list_alarms_state_history_with_offset " - "limit: need three alarms state history to test. " - "Current number of alarms = {}").format( - number_of_alarms) - self.fail(error_msg) - - def _get_elements_with_min_max_timestamp(self, elements): - sorted_elements = sorted(elements, key=lambda element: timeutils. - parse_isotime(element['timestamp'])) - min_element = sorted_elements[0] - second_element = sorted_elements[1] - max_element = sorted_elements[-1] - return min_element, second_element, max_element diff --git a/monasca_tempest_tests/tests/api/test_dimensions.py b/monasca_tempest_tests/tests/api/test_dimensions.py deleted file mode 100644 index 93045aa..0000000 --- a/monasca_tempest_tests/tests/api/test_dimensions.py +++ /dev/null @@ -1,334 +0,0 @@ -# (C) Copyright 2016 Hewlett Packard Enterprise Development LP -# (C) Copyright 2017 SUSE LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time -from urllib.parse import urlencode - -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators -from tempest.lib import exceptions - -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import constants -from monasca_tempest_tests.tests.api import helpers - - -class TestDimensions(base.BaseMonascaTest): - - @classmethod - def resource_setup(cls): - super(TestDimensions, cls).resource_setup() - start_timestamp = int(round(time.time() * 1000)) - start_time_iso = helpers.timestamp_to_iso(start_timestamp) - # NOTE (brtknr): use interval of a day because the tag based queries - # appear to only support smallest granularity of a day, and disregard - # time of day, which is fine for most use cases. - day = 60 * 60 * 24 * 1000 - end_timestamp = start_timestamp + 10 * day - end_time_iso = helpers.timestamp_to_iso(end_timestamp) - - metric_name1 = data_utils.rand_name() - name1 = "name_1" - name2 = "name_2" - value1 = "value_1" - value2 = "value_2" - timestamp1 = start_timestamp - day - timestamp2 = start_timestamp + day - timestamp3 = start_timestamp + day + day - timestamp4 = end_timestamp + day - metric1 = helpers.create_metric(name=metric_name1, - timestamp=timestamp1, - dimensions={name1: value1, - name2: value2, - }) - cls.monasca_client.create_metrics(metric1) - metric1 = helpers.create_metric(name=metric_name1, - timestamp=timestamp2, - dimensions={name1: value2}) - cls.monasca_client.create_metrics(metric1) - - metric_name2 = data_utils.rand_name() - name3 = "name_3" - value3 = "value_3" - value4 = "value_4" - metric2 = helpers.create_metric(name=metric_name2, - timestamp=timestamp3, - dimensions={name1: value3, - name3: value4, - }) - cls.monasca_client.create_metrics(metric2) - - metric_name3 = data_utils.rand_name() - metric3 = helpers.create_metric(name=metric_name3, - timestamp=timestamp4, - dimensions={name2: value3}) - cls.monasca_client.create_metrics(metric3) - - cls._test_metric1 = metric1 - cls._test_metric2 = metric2 - cls._test_metric_names = {metric_name1, metric_name2, metric_name3} - cls._dim_names_metric1 = [name1, name2] - cls._dim_names_metric1_in_timerange = [name1] - cls._dim_names_metric2 = [name1, name3] - cls._dim_names_metric2_in_timerange = [name1, name3] - cls._dim_names = sorted(set(cls._dim_names_metric1 - + cls._dim_names_metric2)) - cls._dim_names_in_timerange = sorted(set( - cls._dim_names_metric1_in_timerange + - cls._dim_names_metric2_in_timerange)) - cls._dim_name1 = name1 - cls._dim_name1_values_for_metric1 = [value1, value2] - cls._dim_name1_values_for_metric1_in_timerange = [value2] - cls._dim_name1_values = [value1, value2, value3] - cls._dim_name1_values_in_timerange = [value2, value3] - cls._start_time = start_time_iso - cls._end_time = end_time_iso - - param = '?start_time=' + start_time_iso - returned_name_set = set() - for i in range(constants.MAX_RETRIES): - resp, response_body = cls.monasca_client.list_metrics( - param) - elements = response_body['elements'] - metric_name1_count = 0 - for element in elements: - returned_name_set.add(str(element['name'])) - if (str(element['name']) == metric_name1): - metric_name1_count += 1 - # Java version of influxdb never returns both metric1 in the list but Python does. - if cls._test_metric_names.issubset(returned_name_set) \ - and (metric_name1_count == 2 or i == constants.MAX_RETRIES - 1): - return - time.sleep(constants.RETRY_WAIT_SECS) - - assert False, 'Unable to initialize metrics' - - @classmethod - def resource_cleanup(cls): - super(TestDimensions, cls).resource_cleanup() - - def _test_list_dimension_values_without_metric_name(self, timerange): - param = '?dimension_name=' + self._dim_name1 - if timerange: - param += '&start_time=' + self._start_time - param += '&end_time=' + self._end_time - resp, response_body = self.monasca_client.list_dimension_values(param) - self.assertEqual(200, resp.status) - self.assertTrue({'links', 'elements'} == set(response_body)) - response_values_length = len(response_body['elements']) - values = [str(response_body['elements'][i]['dimension_value']) - for i in range(response_values_length)] - if timerange: - self.assertEqual(values, self._dim_name1_values_in_timerange) - else: - self.assertEqual(values, self._dim_name1_values) - - @decorators.attr(type='gate') - def test_list_dimension_values_without_metric_name(self): - self._test_list_dimension_values_without_metric_name(timerange=False) - - @decorators.attr(type='gate') - @decorators.attr(type='timerange') - def test_list_dimension_values_without_metric_name_with_timerange(self): - self._test_list_dimension_values_without_metric_name(timerange=True) - - def _test_list_dimension_values_with_metric_name(self, timerange): - param = '?metric_name=' + self._test_metric1['name'] - param += '&dimension_name=' + self._dim_name1 - if timerange: - param += '&start_time=' + self._start_time - param += '&end_time=' + self._end_time - resp, response_body = self.monasca_client.list_dimension_values(param) - self.assertEqual(200, resp.status) - self.assertTrue({'links', 'elements'} == set(response_body)) - response_values_length = len(response_body['elements']) - values = [str(response_body['elements'][i]['dimension_value']) - for i in range(response_values_length)] - if timerange: - self.assertEqual(values, self._dim_name1_values_for_metric1_in_timerange) - else: - self.assertEqual(values, self._dim_name1_values_for_metric1) - - @decorators.attr(type='gate') - def test_list_dimension_values_with_metric_name(self): - self._test_list_dimension_values_with_metric_name(timerange=False) - - @decorators.attr(type='gate') - @decorators.attr(type='timerange') - def test_list_dimension_values_with_metric_name_with_timerange(self): - self._test_list_dimension_values_with_metric_name(timerange=True) - - def _test_list_dimension_values_limit_and_offset(self, timerange): - param = '?dimension_name=' + self._dim_name1 - if timerange: - param += '&start_time=' + self._start_time - param += '&end_time=' + self._end_time - resp, response_body = self.monasca_client.list_dimension_values(param) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - num_dim_values = len(elements) - for limit in range(1, num_dim_values): - start_index = 0 - params = [('limit', limit)] - offset = None - while True: - num_expected_elements = limit - if (num_expected_elements + start_index) > num_dim_values: - num_expected_elements = num_dim_values - start_index - - these_params = list(params) - # Use the offset returned by the last call if available - if offset: - these_params.extend([('offset', str(offset))]) - query_param = '?dimension_name=' + self._dim_name1 - if timerange: - query_param += '&start_time=' + self._start_time - query_param += '&end_time=' + self._end_time - query_param += '&' + urlencode(these_params) - resp, response_body = \ - self.monasca_client.list_dimension_values(query_param) - self.assertEqual(200, resp.status) - if not response_body['elements']: - self.fail("No metrics returned") - response_values_length = len(response_body['elements']) - if response_values_length == 0: - self.fail("No dimension names returned") - new_elements = [str(response_body['elements'][i] - ['dimension_value']) for i in - range(response_values_length)] - self.assertEqual(num_expected_elements, len(new_elements)) - - expected_elements = elements[start_index:start_index + limit] - expected_dimension_values = \ - [expected_elements[i]['dimension_value'] for i in range( - len(expected_elements))] - self.assertEqual(expected_dimension_values, new_elements) - start_index += num_expected_elements - if start_index >= num_dim_values: - break - # Get the next set - offset = self._get_offset(response_body) - - @decorators.attr(type='gate') - def test_list_dimension_values_limit_and_offset(self): - self._test_list_dimension_values_limit_and_offset(timerange=False) - - @decorators.attr(type='gate') - @decorators.attr(type='timerange') - def test_list_dimension_values_limit_and_offset_with_timerange(self): - self._test_list_dimension_values_limit_and_offset(timerange=True) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_list_dimension_values_no_dimension_name(self): - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_dimension_values) - - @decorators.attr(type=["gate", "smoke"]) - def test_list_dimension_names(self): - resp, response_body = self.monasca_client.list_dimension_names() - self.assertEqual(200, resp.status) - self.assertTrue({'links', 'elements'} == set(response_body)) - response_names_length = len(response_body['elements']) - names = [str(response_body['elements'][i]['dimension_name']) for i - in range(response_names_length)] - self.assertEqual(names, self._dim_names) - - @decorators.attr(type='gate') - def test_list_dimension_names_with_metric_name(self): - self._test_list_dimension_names_with_metric_name( - self._test_metric1['name'], self._dim_names_metric1, - timerange=False) - self._test_list_dimension_names_with_metric_name( - self._test_metric2['name'], self._dim_names_metric2, - timerange=False) - - @decorators.attr(type='gate') - @decorators.attr(type='timerange') - def test_list_dimension_names_with_metric_name_with_timerange(self): - self._test_list_dimension_names_with_metric_name( - self._test_metric1['name'], - self._dim_names_metric1_in_timerange, - timerange=True) - self._test_list_dimension_names_with_metric_name( - self._test_metric2['name'], - self._dim_names_metric2_in_timerange, - timerange=True) - - @decorators.attr(type='gate') - def test_list_dimension_names_limit_and_offset(self): - resp, response_body = self.monasca_client.list_dimension_names() - self.assertEqual(200, resp.status) - elements = response_body['elements'] - num_dim_names = len(elements) - for limit in range(1, num_dim_names): - start_index = 0 - params = [('limit', limit)] - offset = None - while True: - num_expected_elements = limit - if (num_expected_elements + start_index) > num_dim_names: - num_expected_elements = num_dim_names - start_index - - these_params = list(params) - # If not the first call, use the offset returned by the last - # call - if offset: - these_params.extend([('offset', str(offset))]) - query_param = '?' + urlencode(these_params) - resp, response_body = self.monasca_client.list_dimension_names( - query_param) - self.assertEqual(200, resp.status) - if not response_body['elements']: - self.fail("No metrics returned") - response_names_length = len(response_body['elements']) - if response_names_length == 0: - self.fail("No dimension names returned") - new_elements = [str(response_body['elements'][i] - ['dimension_name']) for i in - range(response_names_length)] - self.assertEqual(num_expected_elements, len(new_elements)) - - expected_elements = elements[start_index:start_index + limit] - expected_dimension_names = \ - [expected_elements[i]['dimension_name'] for i in range( - len(expected_elements))] - self.assertEqual(expected_dimension_names, new_elements) - start_index += num_expected_elements - if start_index >= num_dim_names: - break - # Get the next set - offset = self._get_offset(response_body) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_list_dimension_names_with_wrong_metric_name(self): - self._test_list_dimension_names_with_metric_name( - 'wrong_metric_name', [], timerange=False) - - def _test_list_dimension_names_with_metric_name(self, metric_name, - dimension_names, - timerange): - param = '?metric_name=' + metric_name - if timerange: - param += '&start_time=' + self._start_time - param += '&end_time=' + self._end_time - resp, response_body = self.monasca_client.list_dimension_names(param) - self.assertEqual(200, resp.status) - self.assertTrue(set(['links', 'elements']) == set(response_body)) - response_names_length = len(response_body['elements']) - names = [str(response_body['elements'][i]['dimension_name']) for i - in range(response_names_length)] - self.assertEqual(names, dimension_names) diff --git a/monasca_tempest_tests/tests/api/test_measurements.py b/monasca_tempest_tests/tests/api/test_measurements.py deleted file mode 100644 index f40fc31..0000000 --- a/monasca_tempest_tests/tests/api/test_measurements.py +++ /dev/null @@ -1,410 +0,0 @@ -# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time - -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import constants -from monasca_tempest_tests.tests.api import helpers -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators -from tempest.lib import exceptions - -NUM_MEASUREMENTS = 50 -ONE_SECOND = 1000 - - -class TestMeasurements(base.BaseMonascaTest): - - @classmethod - def resource_setup(cls): - super(TestMeasurements, cls).resource_setup() - - start_timestamp = int(time.time() * 1000) - start_time = str(helpers.timestamp_to_iso(start_timestamp)) - metrics = [] - name1 = data_utils.rand_name() - name2 = data_utils.rand_name() - cls._names_list = [name1, name2] - key = data_utils.rand_name('key') - value = data_utils.rand_name('value') - cls._key = key - cls._value = value - cls._start_timestamp = start_timestamp - - for i in range(NUM_MEASUREMENTS): - metric = helpers.create_metric( - name=name1, - timestamp=start_timestamp + (i * 10), - value=i) - metrics.append(metric) - cls.monasca_client.create_metrics(metrics) - - # Create metric2 for test_list_measurements_with_dimensions - metric2 = helpers.create_metric( - name=name1, timestamp=start_timestamp + ONE_SECOND * 2, - dimensions={key: value}, value=NUM_MEASUREMENTS) - cls.monasca_client.create_metrics(metric2) - - # Create metric3 for test_list_measurements_with_offset_limit - metric3 = [ - helpers.create_metric( - name=name2, timestamp=start_timestamp + ONE_SECOND * 3, - dimensions={'key1': 'value1', 'key2': 'value5', 'key3': 'value7'}), - helpers.create_metric( - name=name2, timestamp=start_timestamp + ONE_SECOND * 3 + 10, - dimensions={'key1': 'value2', 'key2': 'value5', 'key3': 'value7'}), - helpers.create_metric( - name=name2, timestamp=start_timestamp + ONE_SECOND * 3 + 20, - dimensions={'key1': 'value3', 'key2': 'value6', 'key3': 'value7'}), - helpers.create_metric( - name=name2, timestamp=start_timestamp + ONE_SECOND * 3 + 30, - dimensions={'key1': 'value4', 'key2': 'value6', 'key3': 'value8'}) - ] - cls.monasca_client.create_metrics(metric3) - - # Create metric3 for test_list_measurements_with_no_merge_metrics - metric4 = helpers.create_metric( - name=name1, timestamp=start_timestamp + ONE_SECOND * 4, - dimensions={'key-1': 'value-1'}, - value=NUM_MEASUREMENTS + 1) - cls.monasca_client.create_metrics(metric4) - - end_time = str(helpers.timestamp_to_iso( - start_timestamp + NUM_MEASUREMENTS + ONE_SECOND * 5)) - queries = [] - queries.append('?name={}&start_time={}&end_time={}&merge_metrics=true'. - format(name1, start_time, end_time)) - queries.append('?name={}&start_time={}&end_time={}&merge_metrics=true'. - format(name2, start_time, end_time)) - - for timer in range(constants.MAX_RETRIES): - responses = list(map(cls.monasca_client.list_measurements, queries)) - resp_first = responses[0][0] - response_body_first = responses[0][1] - resp_second = responses[1][0] - response_body_second = responses[1][1] - if resp_first.status == 200 and resp_second.status == 200 \ - and len(response_body_first['elements']) == 1 \ - and len(response_body_second['elements']) == 1: - len_meas_first = len( - response_body_first['elements'][0]['measurements']) - len_meas_second = len( - response_body_second['elements'][0]['measurements']) - if len_meas_first == NUM_MEASUREMENTS + 2 \ - and len_meas_second == 4: - break - else: - time.sleep(constants.RETRY_WAIT_SECS) - else: - time.sleep(constants.RETRY_WAIT_SECS) - - cls._start_time = start_time - cls._end_time = end_time - - @decorators.attr(type=["gate", "smoke"]) - def test_list_measurements(self): - query_parms = '?name=' + str(self._names_list[0]) + \ - '&merge_metrics=true' + \ - '&start_time=' + str(self._start_time) + \ - '&end_time=' + str(self._end_time) - resp, response_body = self.monasca_client.list_measurements( - query_parms) - self._verify_list_measurements(resp, response_body) - elements = response_body['elements'] - self._verify_list_measurements_elements( - elements=elements, test_key=None, test_value=None) - measurements = elements[0]['measurements'] - self._verify_list_measurements_meas_len( - measurements, test_len=NUM_MEASUREMENTS + 2) - i = 0 - for measurement in measurements: - self._verify_list_measurements_measurement(measurement, i) - i += 1 - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_measurements_with_no_start_time(self): - query_parms = '?name=' + str(self._names_list[0]) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_measurements, query_parms) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_measurements_with_no_name(self): - query_parms = '?start_time=' + str(self._start_time) + '&end_time=' + \ - str(self._end_time) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_measurements, query_parms) - - @decorators.attr(type="gate") - def test_list_measurements_with_dimensions(self): - query_parms = '?name=' + self._names_list[0] + '&start_time=' + \ - str(self._start_time) + '&end_time=' + \ - str(self._end_time) + '&dimensions=' + self._key + ':' \ - + self._value - resp, response_body = self.monasca_client.list_measurements( - query_parms) - self._verify_list_measurements(resp, response_body) - elements = response_body['elements'] - self._verify_list_measurements_elements( - elements=elements, test_key=None, test_value=None) - measurements = elements[0]['measurements'] - self._verify_list_measurements_meas_len(measurements, 1) - measurement = measurements[0] - self._verify_list_measurements_measurement( - measurement=measurement, test_value=NUM_MEASUREMENTS) - - @decorators.attr(type="gate") - def test_list_measurements_with_endtime(self): - time_iso = helpers.timestamp_to_iso( - self._start_timestamp + ONE_SECOND * 2) - query_parms = '?name=' + str(self._names_list[0]) + \ - '&merge_metrics=true' \ - '&start_time=' + str(self._start_time) + \ - '&end_time=' + str(time_iso) - resp, response_body = self.monasca_client.list_measurements( - query_parms) - self._verify_list_measurements(resp, response_body) - elements = response_body['elements'] - self._verify_list_measurements_elements(elements=elements, - test_key=None, test_value=None) - measurements = elements[0]['measurements'] - self._verify_list_measurements_meas_len(measurements=measurements, - test_len=NUM_MEASUREMENTS) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_measurements_with_endtime_equals_starttime(self): - query_parms = '?name=' + str(self._names_list[0]) + \ - '&merge_metrics=true' \ - '&start_time=' + str(self._start_time) + \ - '&end_time=' + str(self._start_time) - self.assertRaises(exceptions.BadRequest, - self.monasca_client.list_measurements, query_parms) - - @decorators.attr(type="gate") - def test_list_measurements_with_offset_limit(self): - query_parms = '?name=' + str(self._names_list[1]) + \ - '&merge_metrics=true&start_time=' + self._start_time + \ - '&end_time=' + self._end_time - resp, response_body = self.monasca_client.list_measurements( - query_parms) - self._verify_list_measurements(resp, response_body) - elements = response_body['elements'] - self._verify_list_measurements_elements(elements=elements, - test_key=None, test_value=None) - measurements = elements[0]['measurements'] - self._verify_list_measurements_meas_len(measurements=measurements, - test_len=4) - - for measurement_index in range(1, len(measurements) - 3): - max_limit = len(measurements) - measurement_index - - # Get first offset from api - query_parms = '?name=' + str(self._names_list[1]) + \ - '&merge_metrics=true&start_time=' + \ - measurements[measurement_index - 1][0] + \ - '&end_time=' + self._end_time + \ - '&limit=1' - resp, response_body = self.monasca_client.list_measurements(query_parms) - for link in response_body['links']: - if link['rel'] == 'next': - next_link = link['href'] - if not next_link: - self.fail("No next link returned with query parameters: {}".formet(query_parms)) - offset = helpers.get_query_param(next_link, "offset") - - first_index = measurement_index + 1 - - for limit in range(1, max_limit): - last_index = measurement_index + limit + 1 - expected_measurements = measurements[first_index:last_index] - - query_parms = '?name=' + str(self._names_list[1]) + \ - '&merge_metrics=true&start_time=' + \ - self._start_time + '&end_time=' + \ - self._end_time + '&limit=' + str(limit) + \ - '&offset=' + str(offset) - - resp, response_body = self.monasca_client.list_measurements( - query_parms) - self._verify_list_measurements(resp, response_body) - new_measurements = response_body['elements'][0]['measurements'] - - self.assertEqual(limit, len(new_measurements)) - for i in range(len(expected_measurements)): - self.assertEqual(expected_measurements[i], - new_measurements[i]) - - @decorators.attr(type="gate") - def test_list_measurements_with_merge_metrics(self): - query_parms = '?name=' + str(self._names_list[0]) + \ - '&merge_metrics=true' + \ - '&start_time=' + str(self._start_time) + \ - '&end_time=' + str(self._end_time) - resp, response_body = self.monasca_client.list_measurements( - query_parms) - self.assertEqual(200, resp.status) - - @decorators.attr(type="gate") - def test_list_measurements_with_group_by_one(self): - query_parms = '?name=' + str(self._names_list[1]) + \ - '&group_by=key2' + \ - '&start_time=' + str(self._start_time) + \ - '&end_time=' + str(self._end_time) - resp, response_body = self.monasca_client.list_measurements( - query_parms) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - self.assertEqual(len(elements), 2) - self._verify_list_measurements_elements(elements, None, None) - for measurements in elements: - self.assertEqual(1, len(measurements['dimensions'].keys())) - self.assertEqual([u'key2'], list(measurements['dimensions'].keys())) - - @decorators.attr(type="gate") - def test_list_measurements_with_group_by_multiple(self): - query_parms = '?name=' + str(self._names_list[1]) + \ - '&group_by=key2,key3' + \ - '&start_time=' + str(self._start_time) + \ - '&end_time=' + str(self._end_time) - resp, response_body = self.monasca_client.list_measurements( - query_parms) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - self.assertEqual(len(elements), 3) - self._verify_list_measurements_elements(elements, None, None) - for measurements in elements: - self.assertEqual(2, len(measurements['dimensions'].keys())) - self.assertEqual({u'key2', u'key3'}, set(measurements['dimensions'].keys())) - - @decorators.attr(type="gate") - def test_list_measurements_with_group_by_all(self): - query_parms = '?name=' + str(self._names_list[1]) + \ - '&group_by=*' + \ - '&start_time=' + str(self._start_time) + \ - '&end_time=' + str(self._end_time) - resp, response_body = self.monasca_client.list_measurements( - query_parms) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - self.assertEqual(len(elements), 4) - self._verify_list_measurements_elements(elements, None, None) - - @decorators.attr(type="gate") - def test_list_measurements_with_group_by_and_merge(self): - query_parms = '?name=' + str(self._names_list[1]) + \ - '&group_by=*' + \ - '&merge_metrics=true' + \ - '&start_time=' + str(self._start_time) + \ - '&end_time=' + str(self._end_time) - resp, response_body = self.monasca_client.list_measurements( - query_parms) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - self.assertEqual(len(elements), 4) - self._verify_list_measurements_elements(elements, None, None) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_measurements_with_name_exceeds_max_length(self): - long_name = "x" * (constants.MAX_LIST_MEASUREMENTS_NAME_LENGTH + 1) - query_parms = '?name=' + str(long_name) + '&merge_metrics=true' + \ - '&start_time=' + str(self._start_time) + \ - '&end_time=' + str(self._end_time) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_measurements, query_parms) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_measurements_with_no_merge_metrics(self): - query_parms = '?name=' + str(self._names_list[0]) + \ - '&start_time=' + str(self._start_time) + '&end_time=' \ - + str(self._end_time) - self.assertRaises(exceptions.Conflict, - self.monasca_client.list_measurements, query_parms) - - @decorators.attr(type="gate") - def test_list_measurements_with_duplicate_query_param_merges_positive( - self): - queries = [] - queries.append('?name={}&merge_metrics=true&start_time={}&end_time={' - '}&merge_metrics=true'. - format(self._names_list[0], self._start_time, - self._end_time)) - queries.append('?name={}&merge_metrics=true&start_time={}&end_time={' - '}&merge_metrics=false'. - format(self._names_list[0], self._start_time, - self._end_time)) - responses = list(map(self.monasca_client.list_measurements, queries)) - for i in range(2): - self._verify_list_measurements(responses[i][0], responses[i][1]) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_measurements_with_duplicate_query_param_merges_negative( - self): - queries = [] - queries.append('?name={}&merge_metrics=false&start_time={}&end_time={' - '}&merge_metrics=true'. - format(self._names_list[0], self._start_time, - self._end_time)) - queries.append('?name={}&merge_metrics=false&start_time={}&end_time={' - '}&merge_metrics=false'. - format(self._names_list[0], self._start_time, - self._end_time)) - for i in range(2): - self.assertRaises(exceptions.Conflict, - self.monasca_client.list_measurements, - queries[i]) - - def _verify_list_measurements_measurement(self, measurement, test_value): - self.assertEqual(test_value, float(measurement[1])) - - def _verify_list_measurements(self, resp, response_body): - self.assertEqual(200, resp.status) - self.assertTrue(set(['links', 'elements']) == set(response_body)) - - def _verify_list_measurements_elements(self, elements, test_key, - test_value): - if not elements: - error_msg = "Failed: at least one element is needed. " \ - "Number of element = 0." - self.fail(error_msg) - - for element in elements: - # element = elements[0] - self.assertEqual(set(element), - set(['columns', 'dimensions', 'id', - 'measurements', 'name'])) - self.assertTrue(type(element['name']) is str) - self.assertTrue(type(element['dimensions']) is dict) - self.assertTrue(type(element['columns']) is list) - self.assertTrue(type(element['measurements']) is list) - self.assertEqual(set(element['columns']), - set(['timestamp', 'value', 'value_meta'])) - self.assertTrue(str(element['id']) is not None) - if test_key is not None and test_value is not None: - self.assertEqual(str(element['dimensions'][test_key]), - test_value) - - def _verify_list_measurements_meas_len(self, measurements, test_len): - if measurements: - len_measurements = len(measurements) - self.assertEqual(len_measurements, test_len) - else: - error_msg = "Failed: one specific measurement is needed. " \ - "Number of measurements = 0" - self.fail(error_msg) diff --git a/monasca_tempest_tests/tests/api/test_metrics.py b/monasca_tempest_tests/tests/api/test_metrics.py deleted file mode 100644 index 87709c3..0000000 --- a/monasca_tempest_tests/tests/api/test_metrics.py +++ /dev/null @@ -1,712 +0,0 @@ -# -*- coding: utf-8 -*- -# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# TODO(RMH): Check if ' should be added in the list of INVALID_CHARS. -# TODO(RMH): test_create_metric_no_value, should return 422 if value not sent -import time -from urllib import parse as urlparse - -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators -from tempest.lib import exceptions - -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import constants -from monasca_tempest_tests.tests.api import helpers - - -class TestMetrics(base.BaseMonascaTest): - - @decorators.attr(type=["gate", "smoke"]) - def test_create_metric(self): - name = data_utils.rand_name(u'name') - key = data_utils.rand_name(u'key') - value = data_utils.rand_name(u'value') - timestamp = int(round(time.time() * 1000)) - time_iso = helpers.timestamp_to_iso(timestamp) - end_timestamp = int(round((time.time() + 3600 * 24) * 1000)) - end_time_iso = helpers.timestamp_to_iso(end_timestamp) - value_meta_key = data_utils.rand_name(u'value_meta_key') - value_meta_value = data_utils.rand_name(u'value_meta_value') - metric = helpers.create_metric(name=name, - dimensions={key: value}, - timestamp=timestamp, - value=1.23, - value_meta={ - value_meta_key: value_meta_value - }) - resp, response_body = self.monasca_client.create_metrics(metric) - self.assertEqual(204, resp.status) - query_param = '?name=' + name + '&start_time=' + time_iso + \ - '&end_time=' + end_time_iso - for i in range(constants.MAX_RETRIES): - resp, response_body = self.monasca_client.\ - list_measurements(query_param) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - for element in elements: - # check if metric is there and dimension info already available - if element['name'] == name and len(element['dimensions']) > 0: - self._verify_list_measurements_element(element, key, value) - measurement = element['measurements'][0] - self._verify_list_measurements_measurement( - measurement, metric, value_meta_key, value_meta_value) - return - time.sleep(constants.RETRY_WAIT_SECS) - if i == constants.MAX_RETRIES - 1: - error_msg = "Failed test_create_metric: " \ - "timeout on waiting for metrics: at least " \ - "one metric is needed. Current number of " \ - "metrics = 0" - self.fail(error_msg) - - @decorators.attr(type='gate') - def test_create_metric_with_multibyte_character(self): - name = data_utils.rand_name(u'name') - key = data_utils.rand_name(u'key') - value = data_utils.rand_name(u'value') - timestamp = int(round(time.time() * 1000)) - time_iso = helpers.timestamp_to_iso(timestamp) - end_timestamp = int(round((time.time() + 3600 * 24) * 1000)) - end_time_iso = helpers.timestamp_to_iso(end_timestamp) - value_meta_key = data_utils.rand_name(u'value_meta_key') - value_meta_value = data_utils.rand_name(u'value_meta_value') - metric = helpers.create_metric(name=name, - dimensions={key: value}, - timestamp=timestamp, - value=1.23, - value_meta={ - value_meta_key: value_meta_value - }) - resp, response_body = self.monasca_client.create_metrics(metric) - self.assertEqual(204, resp.status) - query_param = '?name=' + urlparse.quote(name.encode('utf8')) + \ - '&start_time=' + time_iso + '&end_time=' + end_time_iso - for i in range(constants.MAX_RETRIES): - resp, response_body = self.monasca_client.\ - list_measurements(query_param) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - for element in elements: - if element['name'] == name: - self._verify_list_measurements_element(element, key, value) - measurement = element['measurements'][0] - self._verify_list_measurements_measurement( - measurement, metric, value_meta_key, value_meta_value) - return - time.sleep(constants.RETRY_WAIT_SECS) - if i == constants.MAX_RETRIES - 1: - error_msg = "Failed test_create_metric: " \ - "timeout on waiting for metrics: at least " \ - "one metric is needed. Current number of " \ - "metrics = 0" - self.fail(error_msg) - - @decorators.attr(type='gate') - def test_create_metrics(self): - name = data_utils.rand_name(u'name') - key = data_utils.rand_name(u'key') - value = data_utils.rand_name(u'value') - timestamp = int(round(time.time() * 1000)) - time_iso = helpers.timestamp_to_iso(timestamp) - end_timestamp = int(round(timestamp + 3600 * 24 * 1000)) - end_time_iso = helpers.timestamp_to_iso(end_timestamp) - value_meta_key1 = data_utils.rand_name(u'meta_key') - value_meta_value1 = data_utils.rand_name(u'meta_value') - value_meta_key2 = data_utils.rand_name(u'value_meta_key') - value_meta_value2 = data_utils.rand_name(u'value_meta_value') - metrics = [ - helpers.create_metric(name=name, - dimensions={key: value}, - timestamp=timestamp, - value=1.23, - value_meta={ - value_meta_key1: value_meta_value1 - }), - helpers.create_metric(name=name, - dimensions={key: value}, - timestamp=timestamp + 6000, - value=4.56, - value_meta={ - value_meta_key2: value_meta_value2 - }) - ] - resp, response_body = self.monasca_client.create_metrics(metrics) - self.assertEqual(204, resp.status) - query_param = '?name=' + name + '&start_time=' + str(time_iso) + \ - '&end_time=' + str(end_time_iso) - for i in range(constants.MAX_RETRIES): - resp, response_body = self.monasca_client.\ - list_measurements(query_param) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - for element in elements: - if (element['name'] == name and - len(element['measurements']) == 2): - self._verify_list_measurements_element(element, key, value) - first_measurement = element['measurements'][0] - second_measurement = element['measurements'][1] - self._verify_list_measurements_measurement( - first_measurement, metrics[0], value_meta_key1, - value_meta_value1) - self._verify_list_measurements_measurement( - second_measurement, metrics[1], value_meta_key2, - value_meta_value2) - return - time.sleep(constants.RETRY_WAIT_SECS) - if i == constants.MAX_RETRIES - 1: - error_msg = "Failed test_create_metrics: " \ - "timeout on waiting for metrics: at least " \ - "one metric is needed. Current number of " \ - "metrics = 0" - self.fail(error_msg) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_with_no_name(self): - metric = helpers.create_metric(name=None) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_with_empty_name(self): - metric = helpers.create_metric(name='') - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_with_empty_value_in_dimensions(self): - name = data_utils.rand_name(u'name') - metric = helpers.create_metric(name=name, - dimensions={u'key': ''}) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_with_empty_key_in_dimensions(self): - name = data_utils.rand_name(u'name') - metric = helpers.create_metric(name=name, - dimensions={'': u'value'}) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type='gate') - def test_create_metric_with_no_dimensions(self): - name = data_utils.rand_name(u'name') - timestamp = int(round(time.time() * 1000)) - time_iso = helpers.timestamp_to_iso(timestamp) - end_timestamp = int(round(timestamp + 3600 * 24 * 1000)) - end_time_iso = helpers.timestamp_to_iso(end_timestamp) - value_meta_key = data_utils.rand_name(u'value_meta_key') - value_meta_value = data_utils.rand_name(u'value_meta_value') - metric = helpers.create_metric(name=name, - dimensions=None, - timestamp=timestamp, - value=1.23, - value_meta={ - value_meta_key: value_meta_value}) - resp, response_body = self.monasca_client.create_metrics(metric) - self.assertEqual(204, resp.status) - query_param = '?name=' + str(name) + '&start_time=' + str(time_iso) \ - + '&end_time=' + str(end_time_iso) - for i in range(constants.MAX_RETRIES): - resp, response_body = self.monasca_client.\ - list_measurements(query_param) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - for element in elements: - if element['name'] == name: - self._verify_list_measurements_element( - element, test_key=None, test_value=None) - if len(element['measurements']) > 0: - measurement = element['measurements'][0] - self._verify_list_measurements_measurement( - measurement, metric, value_meta_key, - value_meta_value) - return - time.sleep(constants.RETRY_WAIT_SECS) - if i == constants.MAX_RETRIES - 1: - error_msg = "Failed test_create_metric_with_no_dimensions: " \ - "timeout on waiting for metrics: at least " \ - "one metric is needed. Current number of " \ - "metrics = 0" - self.fail(error_msg) - - @decorators.attr(type='gate') - def test_create_metric_with_colon_in_dimension_value(self): - name = data_utils.rand_name(u'name') - key = u'url' - value = u'http://localhost:8070/v2.0' - timestamp = int(round(time.time() * 1000)) - time_iso = helpers.timestamp_to_iso(timestamp) - end_timestamp = int(round((time.time() + 3600 * 24) * 1000)) - end_time_iso = helpers.timestamp_to_iso(end_timestamp) - metric = helpers.create_metric(name=name, - dimensions={key: value}) - resp, response_body = self.monasca_client.create_metrics(metric) - self.assertEqual(204, resp.status) - query_param = '?name=' + name + '&start_time=' + time_iso + \ - '&end_time=' + end_time_iso + \ - '&dimensions=' + key + ':' + value - for i in range(constants.MAX_RETRIES): - resp, response_body = self.monasca_client. \ - list_measurements(query_param) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - for element in elements: - if element['name'] == name: - self._verify_list_measurements_element(element, key, value) - measurement = element['measurements'][0] - self._verify_list_measurements_measurement( - measurement, metric, None, None) - return - time.sleep(constants.RETRY_WAIT_SECS) - if i == constants.MAX_RETRIES - 1: - error_msg = "Failed test_create_metric: " \ - "timeout on waiting for metrics: at least " \ - "one metric is needed. Current number of " \ - "metrics = 0" - self.fail(error_msg) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_with_no_timestamp(self): - metric = helpers.create_metric() - metric['timestamp'] = None - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_no_value(self): - timestamp = int(round(time.time() * 1000)) - metric = helpers.create_metric(timestamp=timestamp, - value=None) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_with_name_exceeds_max_length(self): - long_name = u"x" * (constants.MAX_METRIC_NAME_LENGTH + 1) - metric = helpers.create_metric(long_name) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_with_invalid_chars_in_name(self): - for invalid_char in constants.INVALID_NAME_CHARS: - metric = helpers.create_metric(invalid_char) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_with_invalid_chars_in_dimensions(self): - for invalid_char in constants.INVALID_DIMENSION_CHARS: - metric = helpers.create_metric(u'name-1', {u'key-1': invalid_char}) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - for invalid_char in constants.INVALID_DIMENSION_CHARS: - metric = helpers.create_metric(u'name-1', - {invalid_char: u'value-1'}) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_dimension_key_exceeds_max_length(self): - long_key = u"x" * (constants.MAX_DIMENSION_KEY_LENGTH + 1) - metric = helpers.create_metric(u'name-1', {long_key: u'value-1'}) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_dimension_value_exceeds_max_length(self): - long_value = u"x" * (constants.MAX_DIMENSION_VALUE_LENGTH + 1) - metric = helpers.create_metric(u'name-1', {u'key-1': long_value}) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_with_value_meta_name_exceeds_max_length(self): - long_value_meta_name = u"x" * (constants.MAX_VALUE_META_NAME_LENGTH + 1) - value_meta_dict = {long_value_meta_name: u"value_meta_value"} - metric = helpers.create_metric(name=u'name', value_meta=value_meta_dict) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_with_value_meta_exceeds_max_length(self): - value_meta_name = u"x" - long_value_meta_value = u"y" * constants.MAX_VALUE_META_TOTAL_LENGTH - value_meta_dict = {value_meta_name: long_value_meta_value} - metric = helpers.create_metric(name=u'name', value_meta=value_meta_dict) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.create_metrics, - metric) - - @decorators.attr(type=["gate", "smoke"]) - def test_list_metrics(self): - resp, response_body = self.monasca_client.list_metrics() - self.assertEqual(200, resp.status) - self.assertTrue(set(['links', 'elements']) == set(response_body)) - elements = response_body['elements'] - element = elements[0] - self._verify_list_metrics_element(element, test_key=None, - test_value=None, test_name=None) - self.assertTrue(set(['id', 'name', 'dimensions']) == set(element)) - - @decorators.attr(type='gate') - def test_list_metrics_with_dimensions(self): - name = data_utils.rand_name(u'name') - key = data_utils.rand_name(u'key') - value = data_utils.rand_name(u'value') - metric = helpers.create_metric(name=name, dimensions={key: value}) - resp, response_body = self.monasca_client.create_metrics(metric) - self.assertEqual(204, resp.status) - query_param = '?dimensions=' + key + ':' + value - for i in range(constants.MAX_RETRIES): - resp, response_body = self.monasca_client.list_metrics(query_param) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - for element in elements: - if element['dimensions'][key] == value: - self._verify_list_metrics_element(element, test_name=name) - return - time.sleep(constants.RETRY_WAIT_SECS) - if i == constants.MAX_RETRIES - 1: - error_msg = "Failed test_list_metrics_with_dimensions: " \ - "timeout on waiting for metrics: at least " \ - "one metric is needed. Current number of " \ - "metrics = 0" - self.fail(error_msg) - - @decorators.attr(type='gate') - def test_list_metrics_dimension_query_multi_value_with_diff_names(self): - metrics, name, key_service, values = \ - self._create_metrics_with_different_dimensions(same_name=False) - metric_dimensions = self._get_metric_dimensions( - key_service, values, same_metric_name=False) - query_param = '?dimensions=' + key_service + ':' + values[0] + '|' +\ - values[1] - self._verify_dimensions(query_param, metric_dimensions) - - @decorators.attr(type='gate') - def test_list_metrics_dimension_query_no_value_with_diff_names(self): - metrics, name, key_service, values = \ - self._create_metrics_with_different_dimensions(same_name=False) - metric_dimensions = self._get_metric_dimensions( - key_service, values, same_metric_name=False) - query_param = '?dimensions=' + key_service - self._verify_dimensions(query_param, metric_dimensions) - - @decorators.attr(type='gate') - def test_list_metrics_dimension_query_multi_value_with_same_name(self): - # Skip the test for now due to InfluxDB Inconsistency - return - metrics, name, key_service, values = \ - self._create_metrics_with_different_dimensions(same_name=True) - metric_dimensions = self._get_metric_dimensions( - key_service, values, same_metric_name=True) - query_param = '?name=' + name + '&dimensions=' + key_service + ':' +\ - values[0] + '|' + values[1] - self._verify_dimensions(query_param, metric_dimensions) - - @decorators.attr(type='gate') - def test_list_metrics_dimension_query_no_value_with_same_name(self): - # Skip the test for now due to InfluxDB Inconsistency - return - metrics, name, key_service, values = \ - self._create_metrics_with_different_dimensions(same_name=True) - metric_dimensions = self._get_metric_dimensions( - key_service, values, same_metric_name=True) - query_param = '?name=' + name + '&dimensions=' + key_service - self._verify_dimensions(query_param, metric_dimensions) - - @decorators.attr(type='gate') - def test_list_metrics_with_name(self): - name = data_utils.rand_name(u'name') - key = data_utils.rand_name(u'key') - value = data_utils.rand_name(u'value') - metric = helpers.create_metric(name=name, - dimensions={key: value}) - resp, response_body = self.monasca_client.create_metrics(metric) - self.assertEqual(204, resp.status) - query_param = '?name=' + str(name) - for i in range(constants.MAX_RETRIES): - resp, response_body = self.monasca_client.list_metrics(query_param) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - for element in elements: - if element['name'] == name: - self._verify_list_metrics_element(element, test_key=key, - test_value=value) - return - time.sleep(constants.RETRY_WAIT_SECS) - if i == constants.MAX_RETRIES - 1: - error_msg = "Failed test_list_metrics_with_name: " \ - "timeout on waiting for metrics: at least " \ - "one metric is needed. Current number of " \ - "metrics = 0" - self.fail(error_msg) - - @decorators.attr(type='gate') - def test_list_metrics_with_project(self): - name = data_utils.rand_name(u'name') - key = data_utils.rand_name(u'key') - value = data_utils.rand_name(u'value') - project = self.projects_client.create_project( - name=data_utils.rand_name(u'test_project'))['project'] - # Delete the project at the end of the test - self.addCleanup(self.projects_client.delete_project, project['id']) - metric = helpers.create_metric(name=name, - dimensions={key: value}) - resp, response_body = self.monasca_client.create_metrics( - metric, tenant_id=project['id']) - self.assertEqual(204, resp.status) - query_param = '?tenant_id=' + str(project['id']) - for i in range(constants.MAX_RETRIES): - resp, response_body = self.monasca_client.list_metrics(query_param) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - for element in elements: - if element['name'] == name: - self._verify_list_metrics_element(element, test_key=key, - test_value=value) - return - time.sleep(constants.RETRY_WAIT_SECS) - if i == constants.MAX_RETRIES - 1: - error_msg = "Failed test_list_metrics_with_tenant: " \ - "timeout on waiting for metrics: at least " \ - "one metric is needed. Current number of " \ - "metrics = 0" - self.fail(error_msg) - - @decorators.attr(type='gate') - def test_list_metrics_with_offset_limit(self): - name = data_utils.rand_name() - key1 = data_utils.rand_name() - key2 = data_utils.rand_name() - - metrics = [ - helpers.create_metric(name=name, dimensions={ - key1: u'value-1', key2: u'value-1'}), - helpers.create_metric(name=name, dimensions={ - key1: u'value-2', key2: u'value-2'}), - helpers.create_metric(name=name, dimensions={ - key1: u'value-3', key2: u'value-3'}), - helpers.create_metric(name=name, dimensions={ - key1: u'value-4', key2: u'value-4'}) - ] - self.monasca_client.create_metrics(metrics) - query_param = '?name=' + name - for i in range(constants.MAX_RETRIES): - resp, response_body = self.monasca_client.list_metrics(query_param) - elements = response_body['elements'] - if elements and len(elements) == 4: - break - time.sleep(constants.RETRY_WAIT_SECS) - if i == constants.MAX_RETRIES - 1: - error_msg = ("Failed test_list_metrics_with_offset_limit: " - "timeout on waiting for metrics: 4 metrics " - "are needed. Current number of elements = " - "{}").format(len(elements)) - self.fail(error_msg) - - first_element = elements[0] - query_parms = '?name=' + name + '&limit=4' - resp, response_body = self.monasca_client.list_metrics(query_parms) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - self.assertEqual(4, len(elements)) - self.assertEqual(first_element, elements[0]) - - for metric_index in range(len(elements) - 1): - metric = elements[metric_index] - max_limit = 3 - metric_index - - for limit in range(1, max_limit): - first_index = metric_index + 1 - last_index = first_index + limit - expected_elements = elements[first_index:last_index] - - query_parms = '?name=' + name + '&offset=' + \ - str(metric['id']) + '&limit=' + \ - str(limit) - resp, response_body = self.\ - monasca_client.list_metrics(query_parms) - self.assertEqual(200, resp.status) - new_elements = response_body['elements'] - - self.assertEqual(limit, len(new_elements)) - for i in range(len(expected_elements)): - self.assertEqual(expected_elements[i], new_elements[i]) - - def _verify_list_measurements_element(self, element, test_key, test_value): - self.assertEqual(set(element), - set(['columns', 'dimensions', 'id', 'measurements', - 'name'])) - self.assertEqual(set(element['columns']), - set(['timestamp', 'value', 'value_meta'])) - self.assertTrue(str(element['id']) is not None) - if test_key is not None and test_value is not None: - self.assertEqual( - element['dimensions'][test_key].encode('utf-8'), - test_value.encode('utf-8') - ) - - def _verify_list_measurements_measurement(self, measurement, - test_metric, test_vm_key, - test_vm_value): - # Timestamps stored in influx sometimes are 1 millisecond different to - # the value stored by the persister. Check if the timestamps are - # equal in one millisecond range to pass the test. - time_iso_millis = helpers.timestamp_to_iso_millis( - test_metric['timestamp'] + 0) - time_iso_millis_plus = helpers.timestamp_to_iso_millis( - test_metric['timestamp'] + 1) - time_iso_millis_minus = helpers.timestamp_to_iso_millis( - test_metric['timestamp'] - 1) - if str(measurement[0]) != time_iso_millis and str(measurement[0]) != \ - time_iso_millis_plus and str(measurement[0]) != \ - time_iso_millis_minus: - error_msg = ("Mismatch Error: None of {}, {}, {} matches {}").\ - format(time_iso_millis, time_iso_millis_plus, - time_iso_millis_minus, str(measurement[0])) - self.fail(error_msg) - self.assertEqual(measurement[1], test_metric['value']) - if test_vm_key is not None and test_vm_value is not None: - self.assertEqual( - measurement[2][test_vm_key].encode('utf-8'), - test_vm_value.encode('utf-8') - ) - - def _verify_list_metrics_element(self, element, test_key=None, - test_value=None, test_name=None): - self.assertTrue(type(element['id']) is str) - self.assertTrue(type(element['name']) is str) - self.assertTrue(type(element['dimensions']) is dict) - self.assertEqual(set(element), set(['dimensions', 'id', 'name'])) - self.assertTrue(str(element['id']) is not None) - if test_key is not None and test_value is not None: - self.assertEqual(element['dimensions'][test_key], test_value) - if test_name is not None: - self.assertEqual(element['name'], test_name) - - @decorators.attr(type='gate') - def test_list_metrics_with_time_args(self): - name = data_utils.rand_name(u'name') - key = data_utils.rand_name(u'key') - value_org = data_utils.rand_name(u'value') - - now = int(round(time.time() * 1000)) - # - # Built start and end time args before and after the measurement. - # - start_iso = helpers.timestamp_to_iso(now - 1000) - end_timestamp = int(round(now + 1000)) - end_iso = helpers.timestamp_to_iso(end_timestamp) - - metric = helpers.create_metric(name=name, - dimensions={key: value_org}, - timestamp=now) - - self.monasca_client.create_metrics(metric) - for timer in range(constants.MAX_RETRIES): - query_parms = '?name=' + name + '&start_time=' + start_iso + '&end_time=' + end_iso - resp, response_body = self.monasca_client.list_metrics(query_parms) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - if elements: - dimensions = elements[0] - dimension = dimensions['dimensions'] - value = dimension[str(key)] - self.assertEqual(value_org, value) - break - else: - time.sleep(constants.RETRY_WAIT_SECS) - if timer == constants.MAX_RETRIES - 1: - skip_msg = "Skipped test_list_metrics_with_time_args: " \ - "timeout on waiting for metrics: at least one " \ - "metric is needed. Current number of metrics " \ - "= 0" - raise self.skipException(skip_msg) - - @staticmethod - def _get_metric_dimensions(key_service, values, same_metric_name): - if same_metric_name: - metric_dimensions = [{key_service: values[0], 'key3': ''}, - {key_service: values[1], 'key3': ''}, - {key_service: '', 'key3': 'value3'}] - else: - metric_dimensions = [{key_service: values[0]}, - {key_service: values[1]}, - {'key3': 'value3'}] - return metric_dimensions - - def _verify_dimensions(self, query_param, metric_dimensions): - for i in range(constants.MAX_RETRIES): - resp, response_body = self.monasca_client.list_metrics(query_param) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - if len(elements) == 2: - dimension_sets = [] - for element in elements: - dimension_sets.append(element['dimensions']) - self.assertIn(metric_dimensions[0], dimension_sets) - self.assertIn(metric_dimensions[1], dimension_sets) - self.assertNotIn(metric_dimensions[2], dimension_sets) - return - time.sleep(constants.RETRY_WAIT_SECS) - if i == constants.MAX_RETRIES - 1: - error_msg = "Timeout on waiting for metrics: at least " \ - "2 metrics are needed. Current number of " \ - "metrics = {}".format(len(elements)) - self.fail(error_msg) - - def _create_metrics_with_different_dimensions(self, same_name=True): - name1 = data_utils.rand_name(u'name1') - name2 = name1 if same_name else data_utils.rand_name(u'name2') - name3 = name1 if same_name else data_utils.rand_name(u'name3') - key_service = data_utils.rand_name(u'service') - values = [data_utils.rand_name(u'value1'), - data_utils.rand_name(u'value2')] - metrics = [helpers.create_metric(name1, {key_service: values[0]}), - helpers.create_metric(name2, {key_service: values[1]}), - helpers.create_metric(name3, {u'key3': u'value3'})] - resp, response_body = self.monasca_client.create_metrics(metrics) - self.assertEqual(204, resp.status) - return metrics, name1, key_service, values diff --git a/monasca_tempest_tests/tests/api/test_metrics_names.py b/monasca_tempest_tests/tests/api/test_metrics_names.py deleted file mode 100644 index 6746478..0000000 --- a/monasca_tempest_tests/tests/api/test_metrics_names.py +++ /dev/null @@ -1,162 +0,0 @@ -# (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time -from urllib.parse import urlencode - -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import constants -from monasca_tempest_tests.tests.api import helpers -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators - - -class TestMetricsNames(base.BaseMonascaTest): - - @classmethod - def resource_setup(cls): - super(TestMetricsNames, cls).resource_setup() - name1 = data_utils.rand_name('name1') - name2 = data_utils.rand_name('name2') - name3 = data_utils.rand_name('name3') - key = data_utils.rand_name() - key1 = data_utils.rand_name() - value = data_utils.rand_name() - value1 = data_utils.rand_name() - - timestamp = int(round(time.time() * 1000)) - time_iso = helpers.timestamp_to_iso(timestamp) - - metric1 = helpers.create_metric(name=name1, - dimensions={key: value}) - metric2 = helpers.create_metric(name=name2, - dimensions={key1: value1}) - metric3 = helpers.create_metric(name=name3, - dimensions={key: value}) - cls._test_metric_names = {name1, name2, name3} - cls._expected_names_list = list(cls._test_metric_names) - cls._expected_names_list.sort() - cls._test_metric_names_with_same_dim = [name1, name3] - cls._test_metrics = [metric1, metric2, metric3] - cls._dimensions_param = key + ':' + value - - cls.monasca_client.create_metrics(cls._test_metrics) - - query_param = '?start_time=' + time_iso - returned_name_set = set() - for i in range(constants.MAX_RETRIES): - resp, response_body = cls.monasca_client.list_metrics(query_param) - elements = response_body['elements'] - for element in elements: - returned_name_set.add(str(element['name'])) - if cls._test_metric_names.issubset(returned_name_set): - return - time.sleep(constants.RETRY_WAIT_SECS) - - assert False, 'Unable to initialize metrics' - - @classmethod - def resource_cleanup(cls): - super(TestMetricsNames, cls).resource_cleanup() - - @decorators.attr(type=["gate", "smoke"]) - def test_list_metrics_names(self): - resp, response_body = self.monasca_client.list_metrics_names() - metric_names = self._verify_response(resp, response_body) - self.assertEqual(metric_names, self._expected_names_list) - - @decorators.attr(type='gate') - def test_list_metrics_names_with_dimensions(self): - query_params = '?dimensions=' + self._dimensions_param - resp, response_body = self.monasca_client.list_metrics_names( - query_params) - metric_names = self._verify_response(resp, response_body) - self.assertEqual(metric_names, - self._test_metric_names_with_same_dim) - - @decorators.attr(type='gate') - def test_list_metrics_names_with_limit_offset(self): - resp, response_body = self.monasca_client.list_metrics_names() - self.assertEqual(200, resp.status) - elements = response_body['elements'] - num_names = len(elements) - - for limit in range(1, num_names): - start_index = 0 - params = [('limit', limit)] - offset = None - while True: - num_expected_elements = limit - if (num_expected_elements + start_index) > num_names: - num_expected_elements = num_names - start_index - - these_params = list(params) - # If not the first call, use the offset returned by the last - # call - if offset: - these_params.extend([('offset', str(offset))]) - query_params = '?' + urlencode(these_params) - - resp, response_body = \ - self.monasca_client.list_metrics_names(query_params) - new_elements = self._verify_response(resp, response_body) - self.assertEqual(num_expected_elements, len(new_elements)) - - expected_elements = elements[start_index:start_index + limit] - expected_names = \ - [expected_elements[i]['name'] for i in range( - len(expected_elements))] - - self.assertEqual(expected_names, new_elements) - start_index += num_expected_elements - if start_index >= num_names: - break - # Get the next set - offset = self._get_offset(response_body) - - @decorators.attr(type='gate') - def test_list_metrics_names_with_offset_not_in_metrics_names_list(self): - offset1 = 'tempest-abc' - offset2 = 'tempest-name111' - offset3 = 'tempest-name4-random' - query_param1 = '?' + urlencode([('offset', offset1)]) - query_param2 = '?' + urlencode([('offset', offset2)]) - query_param3 = '?' + urlencode([('offset', offset3)]) - - resp, response_body = self.monasca_client.list_metrics_names( - query_param1) - metric_names = self._verify_response(resp, response_body) - - self.assertEqual(metric_names, self._expected_names_list[:]) - - resp, response_body = self.monasca_client.list_metrics_names( - query_param2) - metric_names = self._verify_response(resp, response_body) - self.assertEqual(metric_names, self._expected_names_list[1:]) - - resp, response_body = self.monasca_client.list_metrics_names( - query_param3) - self.assertEqual(response_body['elements'], []) - - def _verify_response(self, resp, response_body): - self.assertEqual(200, resp.status) - self.assertTrue(set(['links', 'elements']) == set(response_body)) - - response_names_length = len(response_body['elements']) - if response_names_length == 0: - self.fail("No metric names returned") - - metric_names = [str(response_body['elements'][i]['name']) for i in - range(response_names_length)] - return metric_names diff --git a/monasca_tempest_tests/tests/api/test_notification_method_type.py b/monasca_tempest_tests/tests/api/test_notification_method_type.py deleted file mode 100644 index 6f2bc30..0000000 --- a/monasca_tempest_tests/tests/api/test_notification_method_type.py +++ /dev/null @@ -1,33 +0,0 @@ -# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from monasca_tempest_tests.tests.api import base -from tempest.lib import decorators - - -class TestNotificationMethodType(base.BaseMonascaTest): - - @classmethod - def resource_setup(cls): - super(TestNotificationMethodType, cls).resource_setup() - - @classmethod - def resource_cleanup(cls): - super(TestNotificationMethodType, cls).resource_cleanup() - - @decorators.attr(type="gate") - def test_list_notification_method_type(self): - resp, response_body = (self.monasca_client. - list_notification_method_types()) - self.assertEqual(200, resp.status) diff --git a/monasca_tempest_tests/tests/api/test_notification_methods.py b/monasca_tempest_tests/tests/api/test_notification_methods.py deleted file mode 100644 index 9247523..0000000 --- a/monasca_tempest_tests/tests/api/test_notification_methods.py +++ /dev/null @@ -1,953 +0,0 @@ -# (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time -from urllib import parse as urlparse - -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import constants -from monasca_tempest_tests.tests.api import helpers -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators -from tempest.lib import exceptions - -DEFAULT_EMAIL_ADDRESS = 'john.doe@domain.com' - - -class TestNotificationMethods(base.BaseMonascaTest): - - @classmethod - def resource_setup(cls): - super(TestNotificationMethods, cls).resource_setup() - - @classmethod - def resource_cleanup(cls): - super(TestNotificationMethods, cls).resource_cleanup() - - @decorators.attr(type="gate") - def test_create_notification_method(self): - notification = helpers.create_notification() - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = response_body['id'] - - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_create_email_notification_method_with_lower_case_type(self): - notification = helpers.create_notification(name='lower case email notification', - type='email') - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = response_body['id'] - - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_create_email_notification_method_with_mixed_case_type(self): - notification = helpers.create_notification(name='mixed case email notification', - type='EmAil') - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = response_body['id'] - - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_create_notification_method_period_not_defined(self): - notification = helpers.create_notification(period=None) - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = response_body['id'] - - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_create_webhook_notification_method_with_non_zero_period(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name, - type='WEBHOOK', - address='http://localhost/test01', - period=60) - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = response_body['id'] - - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_create_notification_method_webhook_test_tld(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name, - type='WEBHOOK', - address='http://mytest.test/webhook', - period=60) - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = response_body['id'] - - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_create_notification_method_webhook_test_tld_and_port(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name, - type='WEBHOOK', - address='http://mytest.test:4533/webhook', - period=60) - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = response_body['id'] - - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_no_name(self): - notification = helpers.create_notification(name=None) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_no_type(self): - notification = helpers.create_notification(type=None) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_no_address(self): - notification = helpers.create_notification(address=None) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_name_exceeds_max_length(self): - long_name = "x" * (constants.MAX_NOTIFICATION_METHOD_NAME_LENGTH + 1) - notification = helpers.create_notification(name=long_name) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_address_exceeds_max_length(self): - long_address = "x" * ( - constants.MAX_NOTIFICATION_METHOD_ADDRESS_LENGTH + 1) - notification = helpers.create_notification(address=long_address) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_invalid_email_address(self): - notification = helpers.create_notification(address="name@") - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_invalid_scheme_webhook(self): - notification = helpers.create_notification(type="WEBHOOK", - address="ftp://localhost") - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_invalid_webhook_address(self): - notification = helpers.create_notification(type="WEBHOOK", - address="localhost:123") - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - # The below tests are making sure that we accept passing in case insensitive types - # and that we still validate the - # address if the types are case insensitive - @decorators.attr(type="gate") - def test_create_notification_method_webhook_with_lower_case_type(self): - notification = helpers.create_notification(type='webhook', - address='http://mytest.test:4533') - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = response_body['id'] - - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_create_notification_method_webhook_with_mixed_case_type(self): - notification = helpers.create_notification(type='webHooK', - address='http://mytest.test:4533') - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = response_body['id'] - - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_invalid_email_address_type_all_lower_case(self): - notification = helpers.create_notification(type="email", - address="name@") - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_invalid_email_address_type_all_mixed_case(self): - notification = helpers.create_notification(type="EmAil", - address="name@") - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_invalid_webhook_address_type_mixed_case(self): - notification = helpers.create_notification(type="WebHook", - address="localhost:123") - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_invalid_webhook_address_type_lower_case(self): - notification = helpers.create_notification(type="webhook", - address="localhost:123") - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_invalid_type(self): - notification = helpers.create_notification(type='random') - self.assertRaises( - (exceptions.BadRequest, exceptions.NotFound, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_invalid_float_period(self): - notification = helpers.create_notification(period=1.2) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_method_with_invalid_string_period(self): - notification = helpers.create_notification(period='random') - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_webhook_notification_method_with_invalid_period(self): - notification = helpers.create_notification(type='WEBHOOK', - address='http://localhost/test01', - period=10) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.create_notifications, - notification) - - @decorators.attr(type="gate") - def test_list_notification_methods(self): - notification = helpers.create_notification() - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = response_body['id'] - resp, response_body = self.monasca_client.list_notification_methods() - self.assertEqual(200, resp.status) - # Test response body - self.assertTrue(set(['links', 'elements']) == set(response_body)) - elements = response_body['elements'] - element = elements[0] - self.assertTrue(set(['id', 'links', 'name', 'type', 'address', 'period']) == - set(element)) - self.assertTrue(type(element['id']) is str) - self.assertTrue(type(element['links']) is list) - self.assertTrue(type(element['name']) is str) - self.assertTrue(type(element['type']) is str) - self.assertTrue(type(element['address']) is str) - - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_list_notification_methods_sort_by(self): - notifications = [helpers.create_notification( - name='notification sort by 01', - type='PAGERDUTY', - address='test03@localhost', - ), helpers.create_notification( - name='notification sort by 02', - type='WEBHOOK', - address='http://localhost/test01', - ), helpers.create_notification( - name='notification sort by 03', - type='EMAIL', - address='test02@localhost', - )] - for notification in notifications: - resp, response_body = self.monasca_client.create_notifications(notification) - notification['id'] = response_body['id'] - time.sleep(1) - - sort_params1 = ['id', 'name', 'type', 'address'] - for sort_by in sort_params1: - notif_sorted_by = sorted(notifications, - key=lambda obj: obj[sort_by]) - - resp, response_body = self.monasca_client.list_notification_methods( - '?sort_by=' + sort_by) - self.assertEqual(200, resp.status) - for i, element in enumerate(response_body['elements']): - self.assertEqual(notif_sorted_by[i][sort_by], element[sort_by]) - - resp, response_body = self.monasca_client.list_notification_methods( - '?sort_by=' + sort_by + urlparse.quote(' asc')) - self.assertEqual(200, resp.status) - for i, element in enumerate(response_body['elements']): - self.assertEqual(notif_sorted_by[i][sort_by], element[sort_by]) - - notif_sorted_by_reverse = sorted(notifications, - key=lambda obj: obj[sort_by], - reverse=True) - - resp, response_body = self.monasca_client.list_notification_methods( - '?sort_by=' + sort_by + urlparse.quote(' desc')) - self.assertEqual(200, resp.status) - for i, element in enumerate(response_body['elements']): - self.assertEqual(notif_sorted_by_reverse[i][sort_by], element[sort_by]) - - sort_params2 = ['created_at', 'updated_at'] - for sort_by in sort_params2: - resp, response_body = self.monasca_client.list_notification_methods( - '?sort_by=' + sort_by) - self.assertEqual(200, resp.status) - for i, element in enumerate(response_body['elements']): - self.assertEqual(notifications[i]['id'], element['id']) - - resp, response_body = self.monasca_client.list_notification_methods( - '?sort_by=' + sort_by + urlparse.quote(' asc')) - self.assertEqual(200, resp.status) - for i, element in enumerate(response_body['elements']): - self.assertEqual(notifications[i]['id'], element['id']) - - resp, response_body = self.monasca_client.list_notification_methods( - '?sort_by=' + sort_by + urlparse.quote(' desc')) - self.assertEqual(200, resp.status) - for i, element in enumerate(response_body['elements']): - self.assertEqual(notifications[-i - 1]['id'], element['id']) - - for notification in notifications: - self.monasca_client.delete_notification_method(notification['id']) - - @decorators.attr(type="gate") - def test_list_notification_methods_multiple_sort_by(self): - notifications = [helpers.create_notification( - name='notification sort by 01', - type='EMAIL', - address='test02@localhost', - ), helpers.create_notification( - name='notification sort by 02', - type='PAGERDUTY', - address='test03@localhost', - ), helpers.create_notification( - name='notification sort by 03', - type='EMAIL', - address='test04@localhost', - ), helpers.create_notification( - name='notification sort by 04', - type='EMAIL', - address='test01@localhost', - )] - for notification in notifications: - resp, response_body = self.monasca_client.create_notifications(notification) - notification['id'] = response_body['id'] - - resp, response_body = self.monasca_client.list_notification_methods( - '?sort_by=' + urlparse.quote('type asc,address desc,id')) - self.assertEqual(200, resp.status) - - expected_order = [2, 0, 3, 1] - - for i, element in enumerate(response_body['elements']): - self.assertEqual(notifications[expected_order[i]]['id'], element['id']) - - for element in response_body['elements']: - self.monasca_client.delete_notification_method(element['id']) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_notification_methods_invalid_sort_by(self): - query_parms = '?sort_by=random' - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_notification_methods, - query_parms) - - @decorators.attr(type="gate") - def test_list_notification_methods_with_offset_limit(self): - name1 = data_utils.rand_name('notification') - name2 = data_utils.rand_name('notification') - name3 = data_utils.rand_name('notification') - name4 = data_utils.rand_name('notification') - notification1 = helpers.create_notification(name=name1) - notification2 = helpers.create_notification(name=name2) - notification3 = helpers.create_notification(name=name3) - notification4 = helpers.create_notification(name=name4) - - resp, response_body = self.monasca_client.create_notifications( - notification1) - id1 = response_body['id'] - self.assertEqual(201, resp.status) - resp, response_body = self.monasca_client.create_notifications( - notification2) - id2 = response_body['id'] - self.assertEqual(201, resp.status) - resp, response_body = self.monasca_client.create_notifications( - notification3) - id3 = response_body['id'] - self.assertEqual(201, resp.status) - resp, response_body = self.monasca_client.create_notifications( - notification4) - id4 = response_body['id'] - self.assertEqual(201, resp.status) - - resp, response_body = self.monasca_client.list_notification_methods() - elements = response_body['elements'] - - first_element = elements[0] - last_element = elements[3] - - query_parms = '?limit=4' - resp, response_body = self.monasca_client.\ - list_notification_methods(query_parms) - self.assertEqual(200, resp.status) - self.assertEqual(4, len(response_body['elements'])) - self.assertEqual(first_element, response_body['elements'][0]) - - timeout = time.time() + 60 * 1 # 1 minute timeout - for limit in range(1, 5): - next_element = elements[limit - 1] - offset = limit - while True: - if time.time() < timeout: - query_parms = '?offset=' + str(offset) + \ - '&limit=' + str(limit) - resp, response_body = self.monasca_client.\ - list_notification_methods(query_parms) - self.assertEqual(200, resp.status) - new_elements = response_body['elements'] - if len(new_elements) > limit - 1: - self.assertEqual(limit, len(new_elements)) - next_element = new_elements[limit - 1] - offset += 1 - elif 0 < len(new_elements) <= limit - 1: - self.assertEqual(last_element, new_elements[0]) - break - else: - self.assertEqual(last_element, next_element) - break - else: - msg = "Failed " \ - "test_list_notification_methods_with_offset_limit:" \ - " one minute timeout on offset limit test loop." - raise exceptions.TimeoutException(msg) - - resp, response_body = self.monasca_client.\ - delete_notification_method(id1) - self.assertEqual(204, resp.status) - - resp, response_body = self.monasca_client.\ - delete_notification_method(id2) - self.assertEqual(204, resp.status) - - resp, response_body = self.monasca_client.\ - delete_notification_method(id3) - self.assertEqual(204, resp.status) - resp, response_body = self.monasca_client.\ - delete_notification_method(id4) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_get_notification_method(self): - notification = helpers.create_notification() - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = response_body['id'] - resp, response_body = self.monasca_client.get_notification_method(id) - self.assertEqual(200, resp.status) - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_get_notification_method_with_invalid_id(self): - notification = helpers.create_notification() - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = data_utils.rand_name() - self.assertRaises(exceptions.NotFound, - self.monasca_client.get_notification_method, - id) - resp, response_body = self.monasca_client.\ - delete_notification_method(response_body['id']) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_update_notification_method_name(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name) - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - self.assertEqual(name, response_body['name']) - id = response_body['id'] - new_name = name + 'update' - resp, response_body = self.monasca_client.\ - update_notification_method(id, new_name, - type=response_body['type'], - address=response_body['address'], - period=response_body['period']) - self.assertEqual(200, resp.status) - self.assertEqual(new_name, response_body['name']) - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_update_notification_method_type(self): - type = 'EMAIL' - notification = helpers.create_notification(type=type) - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - self.assertEqual(type, response_body['type']) - id = response_body['id'] - new_type = 'PAGERDUTY' - resp, response_body = \ - self.monasca_client.\ - update_notification_method(id, name=response_body['name'], - type=new_type, - address=response_body['address'], - period=response_body['period']) - self.assertEqual(200, resp.status) - self.assertEqual(new_type, response_body['type']) - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_update_notification_method_address(self): - address = DEFAULT_EMAIL_ADDRESS - notification = helpers.create_notification(address=address) - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - self.assertEqual(address, response_body['address']) - id = response_body['id'] - new_address = 'jane.doe@domain.com' - resp, response_body = self.monasca_client.\ - update_notification_method(id, - name=response_body['name'], - type=response_body['type'], - address=new_address, - period=0) - self.assertEqual(200, resp.status) - self.assertEqual(new_address, response_body['address']) - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_update_notification_method_name_exceeds_max_length(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name) - resp, response_body = self.monasca_client.create_notifications( - notification) - id = response_body['id'] - self.assertEqual(201, resp.status) - new_name_long = "x" * (constants.MAX_NOTIFICATION_METHOD_NAME_LENGTH - + 1) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.update_notification_method, id, - name=new_name_long, type=response_body['type'], - address=response_body['address'], period=response_body['period']) - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_update_notification_method_invalid_type(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name) - resp, response_body = self.monasca_client.create_notifications( - notification) - id = response_body['id'] - self.assertEqual(201, resp.status) - self.assertRaises( - (exceptions.BadRequest, exceptions.NotFound, exceptions.UnprocessableEntity), - self.monasca_client.update_notification_method, - id, name=response_body['name'], type='random', - address=response_body['address'], period=0) - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_update_notification_method_address_exceeds_max_length(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name) - resp, response_body = self.monasca_client.create_notifications( - notification) - id = response_body['id'] - self.assertEqual(201, resp.status) - new_address_long = "x" * ( - constants.MAX_NOTIFICATION_METHOD_ADDRESS_LENGTH + 1) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.update_notification_method, id, - name=response_body['name'], type=response_body['type'], - address=new_address_long, period=response_body['period']) - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_update_notification_method_with_no_address(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name) - resp, response_body = self.monasca_client.create_notifications( - notification) - id = response_body['id'] - self.assertEqual(201, resp.status) - self.assertRaises( - (exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.update_notification_method_with_no_address, id, - name="test_update_notification_method_name", - type=response_body['type']) - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_create_and_delete_notification_method(self): - notification = helpers.create_notification() - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = response_body['id'] - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_delete_notification_method_with_invalid_id(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name) - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - id = data_utils.rand_name() - self.assertRaises(exceptions.NotFound, - self.monasca_client.delete_notification_method, - id) - resp, response_body = self.monasca_client.\ - delete_notification_method(response_body['id']) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_patch_notification_method_with_invalid_id(self): - id = data_utils.rand_name() - name = data_utils.rand_name('notification-') - self.assertRaises(exceptions.NotFound, - self.monasca_client.patch_notification_method, - id, name) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_update_notification_method_with_invalid_id(self): - id = data_utils.rand_name() - name = data_utils.rand_name('notification-') - self.assertRaises(exceptions.NotFound, - self.monasca_client.update_notification_method, id, - name=name, type='EMAIL', - address='bob@thebridge.org', period=0) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_update_notification_method_with_non_int_period(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name) - resp, response_body = self.monasca_client.create_notifications( - notification) - id = response_body['id'] - self.assertEqual(201, resp.status) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.update_notification_method, id, - name=response_body['name'], type=response_body['type'], - address=response_body['name'], period='zero') - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_update_webhook_notification_method_with_invalid_period(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name, - type='WEBHOOK', - address='http://localhost/test01', - period=60) - resp, response_body = self.monasca_client.create_notifications( - notification) - id = response_body['id'] - self.assertEqual(201, resp.status) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.update_notification_method, id, - name=response_body['name'], type=response_body['type'], - address=response_body['address'], period=5) - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_patch_notification_method_name(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name) - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - self.assertEqual(name, response_body['name']) - id = response_body['id'] - new_name = name + 'update' - resp, response_body = self.monasca_client.\ - patch_notification_method(id, new_name) - self.assertEqual(200, resp.status) - self.assertEqual(new_name, response_body['name']) - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_patch_notification_method_type(self): - type = 'EMAIL' - notification = helpers.create_notification(type=type) - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - self.assertEqual(type, response_body['type']) - id = response_body['id'] - new_type = 'PAGERDUTY' - resp, response_body = \ - self.monasca_client.\ - patch_notification_method(id, type=new_type) - self.assertEqual(200, resp.status) - self.assertEqual(new_type, response_body['type']) - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_patch_notification_method_address(self): - address = DEFAULT_EMAIL_ADDRESS - notification = helpers.create_notification(address=address) - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - self.assertEqual(address, response_body['address']) - id = response_body['id'] - new_address = 'jane.doe@domain.com' - resp, response_body = self.monasca_client.\ - patch_notification_method(id, address=new_address) - self.assertEqual(200, resp.status) - self.assertEqual(new_address, response_body['address']) - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - def test_patch_notification_method_address_period(self): - type = 'WEBHOOK' - notification = helpers.create_notification( - type=type, address='http://localhost/test01', period=60) - resp, response_body = self.monasca_client.create_notifications( - notification) - self.assertEqual(201, resp.status) - self.assertEqual(type, response_body['type']) - id = response_body['id'] - - # test_patch_webhook_notification_to_email_with_zero_period - new_type = 'EMAIL' - new_period = 0 - resp, response_body = \ - self.monasca_client.\ - patch_notification_method(id, type=new_type, - address='john.doe@domain.com', - period=new_period) - self.assertEqual(200, resp.status) - self.assertEqual(new_type, response_body['type']) - self.assertEqual(new_period, response_body['period']) - - # test_patch_email_notification_to_webhook_with_nonzero_period - new_type = 'WEBHOOK' - new_period = 60 - resp, response_body = \ - self.monasca_client.\ - patch_notification_method(id, type=new_type, - address='http://localhost/test01', - period=new_period) - self.assertEqual(200, resp.status) - self.assertEqual(new_type, response_body['type']) - self.assertEqual(new_period, response_body['period']) - resp, response_body = self.monasca_client.\ - delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_patch_notification_method_name_exceeds_max_length(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name) - resp, response_body = self.monasca_client.create_notifications( - notification) - id = response_body['id'] - self.assertEqual(201, resp.status) - new_name_long = "x" * (constants.MAX_NOTIFICATION_METHOD_NAME_LENGTH - + 1) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.patch_notification_method, id, - name=new_name_long) - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_patch_notification_method_invalid_type(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name) - resp, response_body = self.monasca_client.create_notifications( - notification) - id = response_body['id'] - self.assertEqual(201, resp.status) - self.assertRaises( - (exceptions.BadRequest, exceptions.NotFound, exceptions.UnprocessableEntity), - self.monasca_client.patch_notification_method, id, type='random') - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_patch_notification_method_address_exceeds_max_length(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name) - resp, response_body = self.monasca_client.create_notifications( - notification) - id = response_body['id'] - self.assertEqual(201, resp.status) - new_address_long = "x" * ( - constants.MAX_NOTIFICATION_METHOD_ADDRESS_LENGTH + 1) - self.assertRaises( - (exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.patch_notification_method, id, address=new_address_long) - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_patch_notification_method_with_non_int_period(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name) - resp, response_body = self.monasca_client.create_notifications( - notification) - id = response_body['id'] - self.assertEqual(201, resp.status) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.patch_notification_method, id, period='zero') - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_patch_webhook_notification_method_with_invalid_period(self): - name = data_utils.rand_name('notification-') - notification = helpers.create_notification(name=name, - type='WEBHOOK', - address='http://localhost/test01', - period=60) - resp, response_body = self.monasca_client.create_notifications( - notification) - id = response_body['id'] - self.assertEqual(201, resp.status) - self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), - self.monasca_client.patch_notification_method, id, period=5) - resp, response_body = \ - self.monasca_client.delete_notification_method(id) - self.assertEqual(204, resp.status) diff --git a/monasca_tempest_tests/tests/api/test_read_only_role.py b/monasca_tempest_tests/tests/api/test_read_only_role.py deleted file mode 100644 index c0a75a8..0000000 --- a/monasca_tempest_tests/tests/api/test_read_only_role.py +++ /dev/null @@ -1,184 +0,0 @@ -# (C) Copyright 2016 Hewlett Packard Enterprise Development LP -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time - -from tempest.lib import decorators -from tempest.lib import exceptions - -from monasca_tempest_tests.clients import api as clients -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import helpers - - -class TestReadOnlyRole(base.BaseMonascaTest): - - @classmethod - def resource_setup(cls): - super(TestReadOnlyRole, cls).resource_setup() - credentials = cls.cred_provider.get_creds_by_roles( - ['monasca-read-only-user']).credentials - cls.os = clients.Manager(credentials=credentials) - cls.monasca_client = cls.os.monasca_client - - @classmethod - def resource_cleanup(cls): - super(TestReadOnlyRole, cls).resource_cleanup() - - @decorators.attr(type="gate") - def test_list_alarms_success(self): - resp, response_body = self.monasca_client.list_alarms() - # - # Validate the call succeeds with empty result (we didn't - # create any alarms) - # - self.assertEqual(200, resp.status) - self.assertEqual(0, len(response_body['elements'])) - self.assertTrue(response_body['links'][0]['href'].endswith('/v2.0/alarms')) - - @decorators.attr(type="gate") - def test_list_metrics_success(self): - resp, response_body = self.monasca_client.list_metrics() - # - # Validate the call succeeds with empty result (we didn't - # create any metrics) - # - self.assertEqual(200, resp.status) - self.assertEqual(0, len(response_body['elements'])) - self.assertTrue(response_body['links'][0]['href'].endswith('/v2.0/metrics')) - - @decorators.attr(type="gate") - def test_list_alarm_definition_success(self): - resp, response_body = self.monasca_client.list_alarm_definitions() - # - # Validate the call succeeds with empty result (we didn't - # create any alarm definitions) - # - self.assertEqual(200, resp.status) - self.assertEqual(0, len(response_body['elements'])) - self.assertTrue(response_body['links'][0]['href'].endswith('/v2.0/alarm-definitions')) - - @decorators.attr(type="gate") - def test_list_notification_methods_success(self): - resp, response_body = self.monasca_client.list_notification_methods() - # - # Validate the call succeeds with empty result (we didn't - # create any notifications) - # - self.assertEqual(200, resp.status) - self.assertEqual(0, len(response_body['elements'])) - self.assertTrue(response_body['links'][0]['href'].endswith('/v2.0/notification-methods')) - - @decorators.attr(type="gate") - def test_list_alarm_count_success(self): - resp, response_body = self.monasca_client.count_alarms() - # - # Validate the call succeeds with empty result (we didn't - # create any alarms to count) - # - self.assertEqual(200, resp.status) - self.assertEqual(0, response_body['counts'][0][0]) - self.assertTrue(response_body['links'][0]['href'].endswith('/v2.0/alarms/count')) - - @decorators.attr(type="gate") - def test_list_alarm_state_history_success(self): - resp, response_body = self.monasca_client.list_alarms_state_history() - # - # Validate the call succeeds with empty result (we didn't - # create any alarms that have history) - # - self.assertEqual(200, resp.status) - self.assertEqual(0, len(response_body['elements'])) - self.assertTrue(response_body['links'][0]['href'].endswith('/v2.0/alarms/state-history')) - - @decorators.attr(type="gate") - def test_list_dimension_values_success(self): - parms = '?dimension_name=foo' - resp, response_body = self.monasca_client.list_dimension_values(parms) - # - # Validate the call succeeds with empty result (we didn't - # create any metrics/dimensions) - # - url = '/v2.0/metrics/dimensions/names/values?dimension_name=foo' - self.assertEqual(200, resp.status) - self.assertEqual(0, len(response_body['elements'])) - self.assertTrue(response_body['links'][0]['href'].endswith(url)) - - @decorators.attr(type="gate") - def test_list_dimension_names_success(self): - resp, response_body = self.monasca_client.list_dimension_names() - # - # Validate the call succeeds with empty result (we didn't - # create any metrics/dimensions) - # - url = '/v2.0/metrics/dimensions/names' - self.assertEqual(200, resp.status) - self.assertEqual(0, len(response_body['elements'])) - self.assertTrue(response_body['links'][0]['href'].endswith(url)) - - @decorators.attr(type="gate") - def test_list_measurements_success(self): - start_timestamp = int(time.time() * 1000) - start_time = str(helpers.timestamp_to_iso(start_timestamp)) - parms = '?name=foo&start_time=' + start_time - resp, response_body = self.monasca_client.list_measurements(parms) - # - # Validate the call succeeds with empty result (we didn't - # create any metrics to get measurements for) - # - self.assertEqual(200, resp.status) - self.assertEqual(0, len(response_body['elements'])) - self.assertTrue('/v2.0/metrics/measurements' in response_body['links'][0]['href']) - - @decorators.attr(type="gate") - def test_list_statistics_success(self): - start_timestamp = int(time.time() * 1000) - start_time = str(helpers.timestamp_to_iso(start_timestamp)) - query_parms = '?name=foo&statistics=avg&start_time=' + start_time - resp, response_body = self.monasca_client.list_statistics( - query_parms) - # - # Validate the call succeeds with empty result (we didn't - # create any metrics to get statistics for) - # - self.assertEqual(200, resp.status) - self.assertEqual(0, len(response_body['elements'])) - self.assertTrue('/v2.0/metrics/statistics' in response_body['links'][0]['href']) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_delete_alarms_fails(self): - self.assertRaises(exceptions.Unauthorized, - self.monasca_client.delete_alarm, "foo") - - @decorators.attr(type='gate') - @decorators.attr(type=['negative']) - def test_create_metric_fails(self): - self.assertRaises(exceptions.Unauthorized, - self.monasca_client.create_metrics, - None) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_alarm_definition_fails(self): - self.assertRaises(exceptions.Unauthorized, - self.monasca_client.create_alarm_definitions, - None) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_create_notification_fails(self): - notif = helpers.create_notification() - self.assertRaises(exceptions.Unauthorized, - self.monasca_client.create_notifications, - notif) diff --git a/monasca_tempest_tests/tests/api/test_statistics.py b/monasca_tempest_tests/tests/api/test_statistics.py deleted file mode 100644 index 6daf371..0000000 --- a/monasca_tempest_tests/tests/api/test_statistics.py +++ /dev/null @@ -1,514 +0,0 @@ -# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP -# (C) Copyright 2017-2018 SUSE LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time -import urllib.parse as urlparse -from urllib.parse import urlencode - -from monasca_tempest_tests.tests.api import base -from monasca_tempest_tests.tests.api import constants -from monasca_tempest_tests.tests.api import helpers -from tempest.lib.common.utils import data_utils -from tempest.lib import decorators -from tempest.lib import exceptions - -NUM_MEASUREMENTS = 100 -MIN_REQUIRED_MEASUREMENTS = 2 -WAIT_TIME = 30 - - -class TestStatistics(base.BaseMonascaTest): - - @classmethod - def resource_setup(cls): - super(TestStatistics, cls).resource_setup() - name = data_utils.rand_name('name') - key = data_utils.rand_name('key') - value1 = data_utils.rand_name('value1') - value2 = data_utils.rand_name('value2') - cls._test_name = name - cls._test_key = key - cls._test_value1 = value1 - cls._start_timestamp = int(time.time() * 1000) - metrics = [ - helpers.create_metric(name=name, - dimensions={key: value1}, - timestamp=cls._start_timestamp, - value=1.23), - helpers.create_metric(name=name, - dimensions={key: value2}, - timestamp=cls._start_timestamp + 1000, - value=4.56) - ] - cls.metric_values = [m['value'] for m in metrics] - cls.monasca_client.create_metrics(metrics) - start_time_iso = helpers.timestamp_to_iso(cls._start_timestamp) - query_param = '?name=' + str(name) + '&start_time=' + \ - start_time_iso + '&merge_metrics=true' + '&end_time=' + \ - helpers.timestamp_to_iso(cls._start_timestamp + 1000 * 2) - start_time_iso = helpers.timestamp_to_iso(cls._start_timestamp) - cls._start_time_iso = start_time_iso - - num_measurements = 0 - for i in range(constants.MAX_RETRIES): - resp, response_body = cls.monasca_client.\ - list_measurements(query_param) - elements = response_body['elements'] - if len(elements) > 0: - num_measurements = len(elements[0]['measurements']) - if num_measurements >= MIN_REQUIRED_MEASUREMENTS: - break - time.sleep(constants.RETRY_WAIT_SECS) - - if num_measurements < MIN_REQUIRED_MEASUREMENTS: - assert False, "Required {} measurements, found {}".format(MIN_REQUIRED_MEASUREMENTS, - num_measurements) - - cls._end_timestamp = cls._start_timestamp + 3000 - cls._end_time_iso = helpers.timestamp_to_iso(cls._end_timestamp) - - name2 = data_utils.rand_name("group-by") - cls._group_by_metric_name = name2 - cls._group_by_end_time_iso = helpers.timestamp_to_iso(cls._start_timestamp + 4000) - - group_by_metrics = [ - helpers.create_metric(name=name2, - dimensions={'key1': 'value1', 'key2': 'value5', 'key3': 'value7'}, - timestamp=cls._start_timestamp + 1, value=2), - helpers.create_metric(name=name2, - dimensions={'key1': 'value2', 'key2': 'value5', 'key3': 'value7'}, - timestamp=cls._start_timestamp + 1001, value=3), - helpers.create_metric(name=name2, - dimensions={'key1': 'value3', 'key2': 'value6', 'key3': 'value7'}, - timestamp=cls._start_timestamp + 2001, value=5), - helpers.create_metric(name=name2, - dimensions={'key1': 'value4', 'key2': 'value6', 'key3': 'value8'}, - timestamp=cls._start_timestamp + 3001, value=7), - ] - - cls.monasca_client.create_metrics(group_by_metrics) - query_param = '?name=' + str(name2) + \ - '&start_time=' + start_time_iso + \ - '&merge_metrics=true' + \ - '&end_time=' + cls._group_by_end_time_iso - - num_measurements = 0 - for i in range(constants.MAX_RETRIES): - resp, response_body = cls.monasca_client. \ - list_measurements(query_param) - elements = response_body['elements'] - if len(elements) > 0: - num_measurements = len(elements[0]['measurements']) - if num_measurements >= len(group_by_metrics): - break - time.sleep(constants.RETRY_WAIT_SECS) - - if num_measurements < len(group_by_metrics): - assert False, "Required {} measurements, found {}".format(len(group_by_metrics), - response_body) - - @classmethod - def resource_cleanup(cls): - super(TestStatistics, cls).resource_cleanup() - - @decorators.attr(type="gate") - def test_list_statistics(self): - self._test_list_statistic(with_end_time=True) - - @decorators.attr(type="gate") - def test_list_statistics_with_no_end_time(self): - self._test_list_statistic(with_end_time=False) - - def _test_list_statistic(self, with_end_time=True): - query_parms = '?name=' + str(self._test_name) + \ - '&statistics=' + urlparse.quote('avg,sum,min,max,count') + \ - '&start_time=' + str(self._start_time_iso) + \ - '&merge_metrics=true' + '&period=100000' - if with_end_time is True: - query_parms += '&end_time=' + str(self._end_time_iso) - - resp, response_body = self.monasca_client.list_statistics( - query_parms) - self.assertEqual(200, resp.status) - self.assertTrue(set(['links', 'elements']) == set(response_body)) - element = response_body['elements'][0] - self._verify_element(element) - column = element['columns'] - num_statistics_method = 5 - statistics = element['statistics'][0] - self._verify_column_and_statistics( - column, num_statistics_method, statistics, self.metric_values) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_statistics_with_no_name(self): - query_parms = '?merge_metrics=true&statistics=avg&start_time=' + \ - str(self._start_time_iso) + '&end_time=' + \ - str(self._end_time_iso) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_statistics, query_parms) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_statistics_with_no_statistics(self): - query_parms = '?name=' + str(self._test_name) + '&start_time=' + str( - self._start_time_iso) + '&end_time=' + str(self._end_time_iso) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_statistics, query_parms) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_statistics_with_no_start_time(self): - query_parms = '?name=' + str(self._test_name) + '&statistics=avg' - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_statistics, query_parms) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_statistics_with_invalid_statistics(self): - query_parms = '?name=' + str(self._test_name) + '&statistics=abc' + \ - '&start_time=' + str(self._start_time_iso) + \ - '&end_time=' + str(self._end_time_iso) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_statistics, query_parms) - - @decorators.attr(type="gate") - def test_list_statistics_with_dimensions(self): - query_parms = '?name=' + str(self._test_name) + '&statistics=avg' \ - '&start_time=' + str(self._start_time_iso) + \ - '&end_time=' + str(self._end_time_iso) + \ - '&dimensions=' + str(self._test_key) + ':' + \ - str(self._test_value1) + '&period=100000' - resp, response_body = self.monasca_client.list_statistics( - query_parms) - self.assertEqual(200, resp.status) - dimensions = response_body['elements'][0]['dimensions'] - self.assertEqual(dimensions[self._test_key], self._test_value1) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_statistics_with_end_time_equals_start_time(self): - query_parms = '?name=' + str(self._test_name) + \ - '&merge_metrics=true&statistics=avg&' \ - 'start_time=' + str(self._start_time_iso) + \ - '&end_time=' + str(self._start_time_iso) + \ - '&period=100000' - self.assertRaises(exceptions.BadRequest, - self.monasca_client.list_statistics, query_parms) - - @decorators.attr(type="gate") - def test_list_statistics_with_period(self): - query_parms = '?name=' + str(self._test_name) + \ - '&merge_metrics=true&statistics=avg&' \ - 'start_time=' + str(self._start_time_iso) + \ - '&end_time=' + str(self._end_time_iso) + \ - '&period=1' - resp, response_body = self.monasca_client.list_statistics( - query_parms) - self.assertEqual(200, resp.status) - time_diff = self._end_timestamp - self._start_timestamp - len_statistics = len(response_body['elements'][0]['statistics']) - self.assertEqual(time_diff / 1000, len_statistics) - - @decorators.attr(type="gate") - def test_list_statistics_with_offset_limit(self): - start_timestamp = int(time.time() * 1000) - name = data_utils.rand_name() - metric = [ - helpers.create_metric(name=name, timestamp=start_timestamp + 1, - dimensions={'key1': 'value-1', - 'key2': 'value-1'}, - value=1), - helpers.create_metric(name=name, timestamp=start_timestamp + 1001, - dimensions={'key1': 'value-2', - 'key2': 'value-2'}, - value=2), - helpers.create_metric(name=name, timestamp=start_timestamp + 2001, - dimensions={'key1': 'value-3', - 'key2': 'value-3'}, - value=3), - helpers.create_metric(name=name, timestamp=start_timestamp + 3001, - dimensions={'key1': 'value-4', - 'key2': 'value-4'}, - value=4) - ] - - num_metrics = len(metric) - self.monasca_client.create_metrics(metric) - query_parms = '?name=' + name - for i in range(constants.MAX_RETRIES): - resp, response_body = self.monasca_client.list_metrics(query_parms) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - if elements and len(elements) == num_metrics: - break - else: - time.sleep(constants.RETRY_WAIT_SECS) - self._check_timeout(i, constants.MAX_RETRIES, elements, num_metrics) - - start_time = helpers.timestamp_to_iso(start_timestamp) - end_timestamp = start_timestamp + 4001 - end_time = helpers.timestamp_to_iso(end_timestamp) - query_parms = '?name=' + name + '&merge_metrics=true&statistics=avg' \ - + '&start_time=' + str(start_time) + '&end_time=' + \ - str(end_time) + '&period=1' - resp, body = self.monasca_client.list_statistics(query_parms) - self.assertEqual(200, resp.status) - elements = body['elements'][0]['statistics'] - first_element = elements[0] - - query_parms = '?name=' + name + '&merge_metrics=true&statistics=avg'\ - + '&start_time=' + str(start_time) + '&end_time=' + \ - str(end_time) + '&period=1' + '&limit=' + str(num_metrics) - resp, response_body = self.monasca_client.list_statistics( - query_parms) - self.assertEqual(200, resp.status) - elements = response_body['elements'][0]['statistics'] - self.assertEqual(num_metrics, len(elements)) - self.assertEqual(first_element, elements[0]) - - for limit in range(1, num_metrics): - start_index = 0 - params = [('name', name), - ('merge_metrics', 'true'), - ('statistics', 'avg'), - ('start_time', str(start_time)), - ('end_time', str(end_time)), - ('period', 1), - ('limit', limit)] - offset = None - while True: - num_expected_elements = limit - if (num_expected_elements + start_index) > num_metrics: - num_expected_elements = num_metrics - start_index - - these_params = list(params) - # If not the first call, use the offset returned by the last call - if offset: - these_params.extend([('offset', str(offset))]) - query_parms = '?' + urlencode(these_params) - resp, response_body = self.monasca_client.list_statistics(query_parms) - self.assertEqual(200, resp.status) - if not response_body['elements']: - self.fail("No metrics returned") - if not response_body['elements'][0]['statistics']: - self.fail("No statistics returned") - new_elements = response_body['elements'][0]['statistics'] - - self.assertEqual(num_expected_elements, len(new_elements)) - expected_elements = elements[start_index:start_index + limit] - self.assertEqual(expected_elements, new_elements) - start_index += num_expected_elements - if start_index >= num_metrics: - break - # Get the next set - offset = self._get_offset(response_body) - - @decorators.attr(type="gate") - def test_list_statistics_with_group_by_one(self): - query_parms = '?name=' + self._group_by_metric_name + \ - '&group_by=key2' + \ - '&statistics=max,avg,min' + \ - '&start_time=' + str(self._start_time_iso) + \ - '&end_time=' + str(self._group_by_end_time_iso) - resp, response_body = self.monasca_client.list_statistics( - query_parms) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - self.assertEqual(len(elements), 2) - for statistics in elements: - self.assertEqual(1, len(statistics['dimensions'].keys())) - self.assertEqual([u'key2'], list(statistics['dimensions'].keys())) - - @decorators.attr(type="gate") - def test_list_statistics_with_group_by_multiple(self): - query_parms = '?name=' + self._group_by_metric_name + \ - '&group_by=key2,key3' + \ - '&statistics=max,avg,min' + \ - '&start_time=' + str(self._start_time_iso) + \ - '&end_time=' + str(self._group_by_end_time_iso) - resp, response_body = self.monasca_client.list_statistics( - query_parms) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - self.assertEqual(len(elements), 3) - for statistics in elements: - self.assertEqual(2, len(statistics['dimensions'].keys())) - self.assertEqual({u'key2', u'key3'}, set(statistics['dimensions'].keys())) - - @decorators.attr(type="gate") - def test_list_statistics_with_group_by_all(self): - query_parms = '?name=' + self._group_by_metric_name + \ - '&group_by=*' + \ - '&statistics=max,avg,min' + \ - '&start_time=' + str(self._start_time_iso) + \ - '&end_time=' + str(self._group_by_end_time_iso) - resp, response_body = self.monasca_client.list_statistics( - query_parms) - self.assertEqual(200, resp.status) - elements = response_body['elements'] - self.assertEqual(len(elements), 4) - - @decorators.attr(type="gate") - def test_list_statistics_with_group_by_offset_limit(self): - query_parms = '?name=' + str(self._group_by_metric_name) + \ - '&group_by=key2' + \ - '&statistics=avg,max' + \ - '&start_time=' + str(self._start_time_iso) + \ - '&end_time=' + str(self._group_by_end_time_iso) + \ - '&period=1' - resp, response_body = self.monasca_client.list_statistics(query_parms) - self.assertEqual(200, resp.status) - all_expected_elements = response_body['elements'] - - for limit in range(1, 4): - offset = None - for i in range(4 - limit): - query_parms = '?name=' + str(self._group_by_metric_name) + \ - '&group_by=key2' + \ - '&statistics=avg,max' + \ - '&start_time=' + str(self._start_time_iso) + \ - '&end_time=' + str(self._group_by_end_time_iso) + \ - '&period=1' + \ - '&limit=' + str(limit) - if i > 0: - offset = self._get_offset(response_body) - query_parms += "&offset=" + offset - - expected_elements = helpers.get_expected_elements_inner_offset_limit( - all_expected_elements, - offset, - limit, - 'statistics') - - resp, response_body = self.monasca_client.list_statistics(query_parms) - self.assertEqual(200, resp.status) - self.assertEqual(expected_elements, response_body['elements']) - - @decorators.attr(type="gate") - def test_list_statistics_with_long_start_time(self): - query_parms = '?name=' + str(self._test_name) + \ - '&statistics=' + urlparse.quote('avg,sum,min,max,count') + \ - '&start_time=' + "2017-01-01T00:00:00.00Z" + \ - '&end_time=' + str(self._end_time_iso) + \ - '&merge_metrics=true' + '&period=100000' - resp, response_body = self.monasca_client.list_statistics( - query_parms) - self.assertEqual(200, resp.status) - self.assertTrue(set(['links', 'elements']) == set(response_body)) - element = response_body['elements'][0] - self._verify_element(element) - column = element['columns'] - num_statistics_method = 5 - statistics = element['statistics'][0] - self._verify_column_and_statistics( - column, num_statistics_method, statistics, self.metric_values) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_statistics_with_no_merge_metrics(self): - key = data_utils.rand_name('key') - value = data_utils.rand_name('value') - metric3 = helpers.create_metric( - name=self._test_name, - dimensions={key: value}, - timestamp=self._start_timestamp + 2000) - self.monasca_client.create_metrics(metric3) - query_param = '?name=' + str(self._test_name) + '&start_time=' + \ - self._start_time_iso + '&end_time=' + helpers.\ - timestamp_to_iso(self._start_timestamp + 1000 * 4) + \ - '&merge_metrics=True' - - for i in range(constants.MAX_RETRIES): - resp, response_body = self.monasca_client.\ - list_measurements(query_param) - elements = response_body['elements'] - for element in elements: - if str(element['name']) == self._test_name and len( - element['measurements']) == 3: - end_time_iso = helpers.timestamp_to_iso( - self._start_timestamp + 1000 * 4) - query_parms = '?name=' + str(self._test_name) + \ - '&statistics=avg' + '&start_time=' + \ - str(self._start_time_iso) + '&end_time=' +\ - str(end_time_iso) + '&period=100000' - self.assertRaises(exceptions.Conflict, - self.monasca_client.list_statistics, - query_parms) - return - time.sleep(constants.RETRY_WAIT_SECS) - self._check_timeout(i, constants.MAX_RETRIES, elements, 3) - - @decorators.attr(type="gate") - @decorators.attr(type=['negative']) - def test_list_statistics_with_name_exceeds_max_length(self): - long_name = "x" * (constants.MAX_LIST_STATISTICS_NAME_LENGTH + 1) - query_parms = '?name=' + str(long_name) + '&merge_metrics=true' + \ - '&start_time=' + str(self._start_time_iso) + \ - '&end_time=' + str(self._end_time_iso) - self.assertRaises(exceptions.UnprocessableEntity, - self.monasca_client.list_statistics, query_parms) - - @decorators.attr(type="gate") - def test_list_statistics_response_body_statistic_result_type(self): - query_parms = '?name=' + str(self._test_name) + '&period=100000' + \ - '&statistics=avg' + '&merge_metrics=true' + \ - '&start_time=' + str(self._start_time_iso) + \ - '&end_time=' + str(self._end_time_iso) - resp, response_body = self.monasca_client.list_statistics( - query_parms) - self.assertEqual(200, resp.status) - element = response_body['elements'][0] - statistic = element['statistics'] - statistic_result_type = type(statistic[0][1]) - self.assertEqual(statistic_result_type, float) - - def _verify_element(self, element): - self.assertTrue(set(['id', 'name', 'dimensions', 'columns', - 'statistics']) == set(element)) - self.assertTrue(type(element['id']) is str) - self.assertTrue(element['id'] is not None) - self.assertTrue(type(element['name']) is str) - self.assertTrue(type(element['dimensions']) is dict) - self.assertEqual(len(element['dimensions']), 0) - self.assertTrue(type(element['columns']) is list) - self.assertTrue(type(element['statistics']) is list) - self.assertEqual(element['name'], self._test_name) - - def _verify_column_and_statistics( - self, column, num_statistics_method, statistics, values): - self.assertTrue(type(column) is list) - self.assertTrue(type(statistics) is list) - self.assertEqual(len(column), num_statistics_method + 1) - self.assertEqual(column[0], 'timestamp') - for i, method in enumerate(column): - if method == 'avg': - self.assertAlmostEqual(statistics[i], float(sum(values) / len(values))) - elif method == 'max': - self.assertEqual(statistics[i], max(values)) - elif method == 'min': - self.assertEqual(statistics[i], min(values)) - elif method == 'sum': - self.assertAlmostEqual(statistics[i], sum(values)) - elif method == 'count': - self.assertEqual(statistics[i], len(values)) - - def _check_timeout(self, timer, max_retries, elements, - expect_num_elements): - if timer == max_retries - 1: - error_msg = ("Failed: timeout on waiting for metrics: {} elements " - "are needed. Current number of elements = {}").\ - format(expect_num_elements, len(elements)) - raise self.fail(error_msg) diff --git a/monasca_tempest_tests/tests/api/test_versions.py b/monasca_tempest_tests/tests/api/test_versions.py deleted file mode 100644 index 00e2e21..0000000 --- a/monasca_tempest_tests/tests/api/test_versions.py +++ /dev/null @@ -1,50 +0,0 @@ -# (C) Copyright 2015,2017 Hewlett Packard Enterprise Development Company LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime - -from oslo_serialization import jsonutils as json - -from monasca_tempest_tests.tests.api import base -from tempest.lib import decorators - - -class TestVersions(base.BaseMonascaTest): - - @classmethod - def resource_setup(cls): - super(TestVersions, cls).resource_setup() - - @decorators.attr(type='gate') - def test_get_version(self): - resp, response_body = self.monasca_client.get_version() - self.assertEqual(resp.status, 200) - response_body = json.loads(response_body) - - self.assertIsInstance(response_body, dict) - version = response_body - self.assertTrue(set(['id', 'links', 'status', 'updated']) == - set(version)) - self.assertEqual(version['id'], u'v2.0') - self.assertEqual(version['status'], u'CURRENT') - date_object = datetime.datetime.strptime(version['updated'], - "%Y-%m-%dT%H:%M:%S.%fZ") - self.assertIsInstance(date_object, datetime.datetime) - links = response_body['links'] - self.assertIsInstance(links, list) - link = links[0] - self.assertTrue(set(['rel', 'href']) == - set(link)) - self.assertEqual(link['rel'], u'self') - self.assertTrue(link['href'].endswith('/v2.0')) diff --git a/monasca_tempest_tests/tests/event_api/__init__.py b/monasca_tempest_tests/tests/event_api/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/monasca_tempest_tests/tests/event_api/base.py b/monasca_tempest_tests/tests/event_api/base.py deleted file mode 100644 index 6b2d640..0000000 --- a/monasca_tempest_tests/tests/event_api/base.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright 2019 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from datetime import datetime -import json -from os import path -import pytz -import random -import string - -from oslo_config import cfg -from tempest.common import credentials_factory as cred_factory -from tempest import test - -from monasca_tempest_tests.clients import event_api as clients - -CONF = cfg.CONF - - -def get_simple_event(): - json_file_path = path.join(path.dirname(__file__), - 'req_simple_event.json') - with open(json_file_path, 'r') as f: - return json.loads(f.read()) - - -def create_header(header={}, content_type='application/json'): - header.update({'Content-Type': content_type, - 'kbn-version': CONF.monitoring.kibana_version}) - return header - - -def generate_simple_event_type_string(): - letters = string.ascii_lowercase - random_string = ''.join((random.choice(letters) for _ in range(15))) - return '{}.{}'.format(random_string[:7], random_string[8:]) - - -def generate_simple_event(event_type=None, timestamp=None, events=None, num_of_events=1): - if event_type is None: - event_type = generate_simple_event_type_string() - if events is None: - events = \ - [{ - 'dimensions': { - 'service': 'compute', - 'topic': 'notification.sample', - 'hostname': 'mars'}, - 'project_id': '6f70656e737461636b20342065766572', - 'event': { - 'event_type': event_type, - 'payload': { - 'nova_object.data': { - 'architecture': 'x86_64', - 'availability_zone': 'nova', - 'created_at': '2012-10-29T13:42:11Z'}}}}] \ - * num_of_events - if timestamp is None: - timestamp = datetime.now(tz=pytz.utc).strftime("%Y-%m-%dT%H:%M:%SZ%z") - return {'timestamp': timestamp, - 'events': events} - - -class BaseEventsTestCase(test.BaseTestCase): - """Base test case class for all Event API tests.""" - - @classmethod - def skip_checks(cls): - super(BaseEventsTestCase, cls).skip_checks() - - @classmethod - def resource_setup(cls): - super(BaseEventsTestCase, cls).resource_setup() - auth_version = CONF.identity.auth_version - cred_provider = cred_factory.get_credentials_provider( - cls.__name__, - identity_version=auth_version) - credentials = cred_provider.get_creds_by_roles( - ['admin']).credentials - cls.os_primary = clients.Manager(credentials=credentials) - - cls.events_api_client = cls.os_primary.events_api_client - cls.events_search_client = cls.os_primary.events_search_client diff --git a/monasca_tempest_tests/tests/event_api/test_simple.py b/monasca_tempest_tests/tests/event_api/test_simple.py deleted file mode 100644 index e6dc5d7..0000000 --- a/monasca_tempest_tests/tests/event_api/test_simple.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright 2019 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators -from tempest.lib import exceptions - -from monasca_tempest_tests.tests.event_api import base - -RETRY_COUNT = 15 -RETRY_WAIT = 2 - - -class BaseEventsTestCase(base.BaseEventsTestCase): - - def check_if_events_are_present_in_db(self, event_type): - return len(self.events_search_client.search_event_by_event_type(event_type)) > 0 - - def send_and_retrieve_events(self, events=None, header=None, events_number=1): - if events is None: - event_type = base.generate_simple_event_type_string() - events = base.generate_simple_event(event_type, num_of_events=events_number) - if header is None: - header = base.create_header() - response, _ = self.events_api_client.send_events(events, header) - self.assertEqual(200, response.status) - test_utils.call_until_true(self.check_if_events_are_present_in_db, - RETRY_COUNT * RETRY_WAIT, - RETRY_WAIT, - event_type) - response = self.events_search_client.search_event_by_event_type(event_type) - - self.assertEqual(events_number, len(response)) - - @decorators.attr(type=['gate', 'smoke']) - def test_single_event(self): - self.send_and_retrieve_events() - - @decorators.attr(type='gate') - def test_multiple_events(self): - self.send_and_retrieve_events(events_number=5) - - @decorators.attr(type='gate') - def test_missing_body(self): - header = base.create_header() - try: - response, _ = self.events_api_client.send_events(None, header) - except exceptions.UnprocessableEntity as exc: - self.assertEqual(422, exc.resp.status) - - @decorators.attr(type='gate') - def test_empty_event(self): - header = base.create_header() - body = base.generate_simple_event(events=[]) - try: - response, _ = self.events_api_client.send_events(body, header) - except exceptions.UnprocessableEntity as exc: - self.assertEqual(422, exc.resp.status) - - def test_empty_content_type(self): - body = base.generate_simple_event() - try: - response, _ = self.events_api_client.send_events(body, {}) - except exceptions.BadRequest as exc: - self.assertEqual(400, exc.resp.status) diff --git a/monasca_tempest_tests/tests/log_api/__init__.py b/monasca_tempest_tests/tests/log_api/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/monasca_tempest_tests/tests/log_api/base.py b/monasca_tempest_tests/tests/log_api/base.py deleted file mode 100644 index 378dcc5..0000000 --- a/monasca_tempest_tests/tests/log_api/base.py +++ /dev/null @@ -1,138 +0,0 @@ -# coding=utf-8 -# -# Copyright 2015 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import random -import string - -from oslo_config import cfg -from tempest.common import credentials_factory as cred_factory -from tempest import exceptions -from tempest import test - -from monasca_tempest_tests.clients import log_api as clients - -CONF = cfg.CONF -_ONE_MB = 1024 * 1024 # MB - - -def _get_message_size(size_base): - """Returns message size in number of characters. - - Method relies on UTF-8 where 1 character = 1 byte. - - """ - return int(round(size_base * _ONE_MB, 1)) - - -_SMALL_MESSAGE_SIZE = _get_message_size(0.001) -_MEDIUM_MESSAGE_SIZE = _get_message_size(0.01) -_LARGE_MESSAGE_SIZE = _get_message_size(0.1) -# rejectable message must be larger than [service]max_log_size -# from monasca-log-api.conf -_reject_size = CONF.monitoring.log_api_max_log_size/_ONE_MB + 0.1 -_REJECTABLE_MESSAGE_SIZE = _get_message_size(_reject_size) - - -def generate_unique_message(message=None, size=50): - letters = string.ascii_lowercase - - def rand(amount, space=True): - space = ' ' if space else '' - return ''.join((random.choice(letters + space) for _ in range(amount))) - - sid = rand(10, space=False) - - if not message: - message = rand(size) - return sid, sid + ' ' + message - - -def generate_small_message(message=None): - return generate_unique_message(message, _SMALL_MESSAGE_SIZE) - - -def generate_medium_message(message=None): - return generate_unique_message(message, _MEDIUM_MESSAGE_SIZE) - - -def generate_large_message(message=None): - return generate_unique_message(message, _LARGE_MESSAGE_SIZE) - - -def generate_rejectable_message(message=None): - return generate_unique_message(message, _REJECTABLE_MESSAGE_SIZE) - - -def _get_headers(headers=None, content_type="application/json"): - if not headers: - headers = {} - headers.update({ - 'Content-Type': content_type, - 'kbn-version': CONF.monitoring.kibana_version, - 'kbn-xsrf': 'kibana' - }) - return headers - - -def _get_data(message): - data = { - 'logs': [{ - 'message': message - }] - } - return data - - -class BaseLogsTestCase(test.BaseTestCase): - """Base test case class for all Logs tests.""" - - @classmethod - def skip_checks(cls): - super(BaseLogsTestCase, cls).skip_checks() - if not CONF.service_available.logs: - raise cls.skipException("Monasca logs support is required") - - @classmethod - def resource_setup(cls): - super(BaseLogsTestCase, cls).resource_setup() - auth_version = CONF.identity.auth_version - cred_provider = cred_factory.get_credentials_provider( - cls.__name__, - identity_version=auth_version) - credentials = cred_provider.get_creds_by_roles( - ['monasca-user', 'admin']).credentials - cls.os_primary = clients.Manager(credentials=credentials) - - cls.logs_client = cls.os_primary.log_api_client - cls.logs_search_client = cls.os_primary.log_search_client - - @staticmethod - def cleanup_resources(method, list_of_ids): - for resource_id in list_of_ids: - try: - method(resource_id) - except exceptions.EndpointNotFound: - pass - - -class BaseLogsSearchTestCase(BaseLogsTestCase): - """Base test case class for all LogsSearch tests.""" - @classmethod - def skip_checks(cls): - super(BaseLogsSearchTestCase, cls).skip_checks() - # logs-search tests need both, 'logs' and 'logs-search' - if not CONF.service_available.logs_search: - raise cls.skipException("Monasca logs-search support is required") diff --git a/monasca_tempest_tests/tests/log_api/test_constraints.py b/monasca_tempest_tests/tests/log_api/test_constraints.py deleted file mode 100644 index c14c7ed..0000000 --- a/monasca_tempest_tests/tests/log_api/test_constraints.py +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright 2015-2017 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest.lib import decorators -from tempest.lib import exceptions - -from monasca_tempest_tests.tests.log_api import base - - -class TestLogApiConstraints(base.BaseLogsTestCase): - @decorators.attr(type='gate') - def test_should_reject_if_body_is_empty(self): - headers = base._get_headers() - try: - self.logs_client.custom_request('POST', headers, None) - except exceptions.BadRequest as urc: - self.assertEqual(400, urc.resp.status) - return - - self.assertTrue(False, 'API should respond with an error') - - @decorators.attr(type='gate') - def test_should_reject_if_content_type_missing(self): - headers = base._get_headers(content_type='') - try: - self.logs_client.custom_request('POST', headers, '{}') - except exceptions.BadRequest as urc: - self.assertEqual(400, urc.resp.status) - return - - self.assertTrue(False, 'API should respond with 400') - - @decorators.attr(type='gate') - def test_should_reject_if_wrong_content_type(self): - headers = base._get_headers(content_type='video/3gpp') - try: - self.logs_client.custom_request('POST', headers, '{}') - except exceptions.InvalidContentType as urc: - self.assertEqual(415, urc.resp.status) - return - except exceptions.BadRequest as urc: - self.assertEqual(400, urc.resp.status) - return - - self.assertTrue(False, 'API should respond with 400') - - @decorators.attr(type='gate') - def test_should_reject_too_big_message(self): - _, message = base.generate_rejectable_message() - headers = base._get_headers(self.logs_client.get_headers()) - # Add 'Connection: Keep-Alive' to send large message before - # connection is closed by client. In class ClosingHttp is added - # header 'connection:close' (which will cause closing socket before sending whole message). - # Data are send in small TCP packages. - # Without this header set to Keep-Alive Tempest lib will try to retry connection and finally - # raise ProtocolError. - headers.update({'Connection': 'Keep-Alive'}) - data = base._get_data(message) - try: - self.logs_client.send_single_log(data, headers) - except exceptions.OverLimit as urc: - self.assertEqual(413, urc.resp.status) - return - except exceptions.UnexpectedContentType as uct: - self.assertEqual(503, uct.resp.status) - return - - self.assertTrue(False, 'API should respond with 413 or 503') - - @decorators.attr(type='gate') - def test_should_reject_too_big_message_multiline(self): - _, message = base.generate_rejectable_message() - message = message.replace(' ', '\n') - headers = base._get_headers(self.logs_client.get_headers()) - # Add Connection: Keep-Alive to send large message before - # connection is closed by cli. In class ClosingHttp is added - # header connection:close (which will cause closing socket before sending whole message). - # Data are send in small TCP packages. - # Without this header set to Keep-Alive Tempest lib will try to retry connection and finally - # raise ProtocolError. - headers.update({'Connection': 'Keep-Alive'}) - data = base._get_data(message) - try: - self.logs_client.send_single_log(data, headers) - except exceptions.OverLimit as urc: - self.assertEqual(413, urc.resp.status) - return - except exceptions.UnexpectedContentType as uct: - self.assertEqual(503, uct.resp.status) - return - - self.assertTrue(False, 'API should respond with 413 or 503') diff --git a/monasca_tempest_tests/tests/log_api/test_single.py b/monasca_tempest_tests/tests/log_api/test_single.py deleted file mode 100644 index 351d551..0000000 --- a/monasca_tempest_tests/tests/log_api/test_single.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright 2015-2017 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest import config -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators -from testtools import matchers - -from monasca_tempest_tests.tests.log_api import base - -CONF = config.CONF -_RETRY_COUNT = 15 -_RETRY_WAIT = 2 - - -class TestSingleLog(base.BaseLogsSearchTestCase): - def _run_and_wait(self, key, data, - content_type='application/json', - headers=None, fields=None): - - headers = base._get_headers(headers, content_type) - - def wait(): - return self.logs_search_client.count_search_messages(key, - headers) > 0 - - self.assertEqual(0, self.logs_search_client.count_search_messages(key, - headers), - 'Find log message in elasticsearch: {0}'.format(key)) - - headers = base._get_headers(headers, content_type) - data = base._get_data(data) - - client = self.logs_client - response, _ = client.send_single_log(data, headers, fields) - self.assertEqual(204, response.status) - - test_utils.call_until_true(wait, _RETRY_COUNT * _RETRY_WAIT, - _RETRY_WAIT) - response = self.logs_search_client.search_messages(key, headers) - self.assertEqual(1, len(response)) - - return response - - @decorators.attr(type=["gate", "smoke"]) - def test_small_message(self): - self._run_and_wait(*base.generate_small_message()) - - @decorators.attr(type="gate") - def test_medium_message(self): - self._run_and_wait(*base.generate_medium_message()) - - @decorators.attr(type="gate") - def test_big_message(self): - self._run_and_wait(*base.generate_large_message()) - - @decorators.attr(type="gate") - def test_small_message_multiline(self): - sid, message = base.generate_small_message() - self._run_and_wait(sid, message.replace(' ', '\n')) - - @decorators.attr(type="gate") - def test_medium_message_multiline(self): - sid, message = base.generate_medium_message() - self._run_and_wait(sid, message.replace(' ', '\n')) - - @decorators.attr(type="gate") - def test_big_message_multiline(self): - sid, message = base.generate_large_message() - self._run_and_wait(sid, message.replace(' ', '\n')) - - @decorators.attr(type="gate") - def test_send_cross_project(self): - sid, message = base.generate_small_message() - headers = {'X-Roles': 'admin, monitoring-delegate'} - cross_tennant_id = '2106b2c8da0eecdb3df4ea84a0b5624b' - fields = {'project_id': cross_tennant_id} - response = self._run_and_wait(sid, message, headers=headers, fields=fields) - log_msg = response[0] - for key in CONF.monitoring.log_project_id_path: - log_msg = log_msg.pop(key) - self.assertThat(log_msg, - matchers.StartsWith(cross_tennant_id)) - - # TODO(trebski) following test not passing - failed to retrieve - # big message from elasticsearch - - # @decorators.attr(type='gate') - # def test_should_truncate_big_message(self): - # message_size = base._get_message_size(0.9999) - # sid, message = base.generate_unique_message(size=message_size) - # - # headers = base._get_headers(self.logs_clients.get_headers()) - # response = self._run_and_wait(sid, message, headers=headers) - # - # self.assertTrue(False, 'API should respond with 500') diff --git a/monasca_tempest_tests/tests/log_api/test_unicode.py b/monasca_tempest_tests/tests/log_api/test_unicode.py deleted file mode 100644 index c462fe8..0000000 --- a/monasca_tempest_tests/tests/log_api/test_unicode.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2017 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest.lib.common.utils import test_utils -from tempest.lib import decorators - -from monasca_common.tests.validation import test_metric_validation -from monasca_tempest_tests.tests.log_api import base - -_RETRY_COUNT = 15 -_RETRY_WAIT = 2 -_UNICODE_CASES = test_metric_validation.UNICODE_MESSAGES - - -class TestUnicodeV3(base.BaseLogsSearchTestCase): - - def _run_and_wait(self, key, data, - content_type='application/json', - headers=None, fields=None): - - headers = base._get_headers(headers, content_type) - - def wait(): - return self.logs_search_client.count_search_messages(key, - headers) > 0 - - self.assertEqual(0, self.logs_search_client.count_search_messages(key, - headers), - 'Find log message in elasticsearch: {0}'.format(key)) - - headers = base._get_headers(headers, content_type) - data = base._get_data(data) - - client = self.logs_client - response, _ = client.send_single_log(data, headers, fields) - self.assertEqual(204, response.status) - - test_utils.call_until_true(wait, _RETRY_COUNT * _RETRY_WAIT, - _RETRY_WAIT) - response = self.logs_search_client.search_messages(key, headers) - self.assertEqual(1, len(response)) - - return response - - @decorators.attr(type="gate") - def test_unicode_message(self): - for m in _UNICODE_CASES: - self._run_and_wait(*base.generate_small_message(m['input']), headers={ - 'LA-Unicode-Case': m['case'] - }) diff --git a/playbooks/docker-publish.yml b/playbooks/docker-publish.yml deleted file mode 100644 index 72a1250..0000000 --- a/playbooks/docker-publish.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- hosts: all - tasks: - - name: Login to Dockerhub - command: "docker login -u {{ doker_hub_login_tempest.user }} -p {{ doker_hub_login_tempest.password }}" - no_log: true - - - name: List images - shell: "docker images --format '{% raw %}{{ .Repository }}:{{ .Tag }}{% endraw %}' | grep monasca" - - - name: Push to Docker Hub all tags - shell: "docker push monasca/tempest-tests:{{ zuul.tag if zuul.pipeline == 'release' else zuul.branch }}" diff --git a/releasenotes/notes/.placeholder b/releasenotes/notes/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/releasenotes/notes/drop-py-2-7-e5ad0bf8a877580b.yaml b/releasenotes/notes/drop-py-2-7-e5ad0bf8a877580b.yaml deleted file mode 100644 index 73358a0..0000000 --- a/releasenotes/notes/drop-py-2-7-e5ad0bf8a877580b.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -upgrade: - - | - Python 2.7 support has been dropped. Last release of monasca-tempest-plugin - to support py2.7 is OpenStack Train. The minimum version of Python now - supported by monasca-tempest-plugin is Python 3.5. diff --git a/releasenotes/notes/story-2005311-bc67654cb58c9562.yaml b/releasenotes/notes/story-2005311-bc67654cb58c9562.yaml deleted file mode 100644 index aa40400..0000000 --- a/releasenotes/notes/story-2005311-bc67654cb58c9562.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -other: - - | - Update alarms count tests to test a query string with multiple - metric_dimension values. diff --git a/releasenotes/source/_static/.placeholder b/releasenotes/source/_static/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/releasenotes/source/_templates/.placeholder b/releasenotes/source/_templates/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py deleted file mode 100644 index 11f2e86..0000000 --- a/releasenotes/source/conf.py +++ /dev/null @@ -1,268 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# 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. -# 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 = [ - 'openstackdocstheme', - 'reno.sphinxext', -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -copyright = u'2017, OpenStack Developers' - -# openstackdocstheme options -openstackdocs_repo_name = 'openstack/openstack' -openstackdocs_bug_project = 'monasca_tempest_plugin' -openstackdocs_bug_tag = '' - -# 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. -# The full version, including alpha/beta/rc tags. -release = '' -# The short X.Y version. -version = '' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'native' - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = 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 = 'openstackdocs' - -# 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 themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# 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'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'monasca_tempest_pluginReleaseNotesdoc' - - -# -- Options for LaTeX output --------------------------------------------- - -# 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 = [ - ('index', 'monasca_tempest_pluginReleaseNotes.tex', - u'monasca_tempest_plugin Release Notes Documentation', - u'OpenStack Foundation', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'monasca_tempest_pluginrereleasenotes', - u'monasca_tempest_plugin Release Notes Documentation', - [u'OpenStack Foundation'], 1) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- 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 = [ - ('index', 'monasca_tempest_plugin ReleaseNotes', - u'monasca_tempest_plugin Release Notes Documentation', - u'OpenStack Foundation', 'monasca_tempest_pluginReleaseNotes', - 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False - -# -- Options for Internationalization output ------------------------------ -locale_dirs = ['locale/'] diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst deleted file mode 100644 index 4422cbb..0000000 --- a/releasenotes/source/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -============================================ - monasca_tempest_plugin Release Notes -============================================ - -.. toctree:: - :maxdepth: 1 - - unreleased diff --git a/releasenotes/source/unreleased.rst b/releasenotes/source/unreleased.rst deleted file mode 100644 index cd22aab..0000000 --- a/releasenotes/source/unreleased.rst +++ /dev/null @@ -1,5 +0,0 @@ -============================== - Current Series Release Notes -============================== - -.. release-notes:: diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index de63b91..0000000 --- a/requirements.txt +++ /dev/null @@ -1,13 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. - -pbr!=2.1.0,>=2.0.0 # Apache-2.0 -oslo.config>=5.2.0 # Apache-2.0 -oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 -oslo.utils>=3.33.0 # Apache-2.0 -tempest>=17.1.0 # Apache-2.0 -oslotest>=3.2.0 # Apache-2.0 -mock>=2.0.0 # BSD -monasca-common>=2.8.0 # Apache-2.0 -pytz>=2013.6 # MIT diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 9af321d..0000000 --- a/setup.cfg +++ /dev/null @@ -1,29 +0,0 @@ -[metadata] -name = monasca-tempest-plugin -summary = Tempest plugin for Monasca project -description-file = - README.rst -author = OpenStack -author-email = openstack-discuss@lists.openstack.org -home-page = https://docs.openstack.org/monasca-api/latest/ -classifier = - Environment :: OpenStack - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.5 - Programming Language :: Python :: 3.6 - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 - Topic :: System :: Monitoring - -[files] -packages = - monasca_tempest_tests - -[entry_points] -tempest.test_plugins = - monasca_tests = monasca_tempest_tests.plugin:MonascaTempestPlugin diff --git a/setup.py b/setup.py deleted file mode 100644 index 566d844..0000000 --- a/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT -import setuptools - -# In python < 2.7.4, a lazy loading of package `pbr` will break -# setuptools if some other modules registered functions in `atexit`. -# solution from: http://bugs.python.org/issue15881#msg170215 -try: - import multiprocessing # noqa -except ImportError: - pass - -setuptools.setup( - setup_requires=['pbr>=2.0.0'], - pbr=True) diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index bc343e1..0000000 --- a/test-requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. - -hacking>=3.0.1,<3.1.0;python_version>='3.5' # Apache-2.0 diff --git a/tox.ini b/tox.ini deleted file mode 100644 index ffe0a35..0000000 --- a/tox.ini +++ /dev/null @@ -1,58 +0,0 @@ -[tox] -minversion = 3.1.1 -envlist = py3,pypy,pep8 -skipsdist = True -ignore_basepython_conflict = True - -[testenv] -basepython = python3 -usedevelop = True -setenv = - VIRTUAL_ENV={envdir} - PYTHONWARNINGS=default::DeprecationWarning - OS_STDOUT_CAPTURE=1 - OS_STDERR_CAPTURE=1 - OS_TEST_TIMEOUT=60 -deps = - -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} - -r{toxinidir}/test-requirements.txt -commands = stestr run {posargs} - -[testenv:pep8] -commands = flake8 {posargs} - -[testenv:venv] -commands = {posargs} - -[testenv:cover] -setenv = - VIRTUAL_ENV={envdir} - PYTHON=coverage run --source monasca_tempest_plugin --parallel-mode -commands = - stestr run {posargs} - coverage combine - coverage html -d cover - coverage xml -o cover/coverage.xml - -[testenv:docs] -deps = -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} - -r{toxinidir}/doc/requirements.txt -commands = sphinx-build -W -b html doc/source doc/build/html - -[testenv:releasenotes] -deps = {[testenv:docs]deps} -commands = - sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html - -[testenv:debug] -commands = oslo_debug_helper {posargs} - -[flake8] -# H106: Don't put vim configuration in source files -# H203: Use assertIs(Not)None to check for None -enable-extensions=H106,H203 -max-complexity = 50 -max-line-length = 100 -builtins = _ -exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,tools,build -show-source = True