From c53fc432fc7ddf004d4e1eea9bd407f3c548908d Mon Sep 17 00:00:00 2001 From: thuva4 Date: Tue, 30 Jan 2018 19:50:33 +0530 Subject: create Testapi client implement auth in testapi client implement pods in testapi client Change-Id: Idd5c9dcf938ad5994e655b55d49625ab462ab710 Signed-off-by: thuva4 --- testapi/.gitignore | 3 +- testapi/testapi-client/etc/config.ini | 6 ++ testapi/testapi-client/requirements.txt | 8 ++ testapi/testapi-client/setup.cfg | 59 +++++++++++++++ testapi/testapi-client/setup.py | 11 +++ testapi/testapi-client/testapiclient/__init__.py | 8 ++ testapi/testapi-client/testapiclient/auth.py | 22 ++++++ .../testapi-client/testapiclient/authHandler.py | 16 ++++ testapi/testapi-client/testapiclient/config.py | 14 ++++ testapi/testapi-client/testapiclient/httpClient.py | 44 +++++++++++ testapi/testapi-client/testapiclient/main.py | 40 ++++++++++ testapi/testapi-client/testapiclient/pods.py | 87 ++++++++++++++++++++++ testapi/testapi-client/testapiclient/user.py | 2 + testapi/testapi-client/tox.ini | 32 ++++++++ 14 files changed, 351 insertions(+), 1 deletion(-) create mode 100644 testapi/testapi-client/etc/config.ini create mode 100644 testapi/testapi-client/requirements.txt create mode 100644 testapi/testapi-client/setup.cfg create mode 100644 testapi/testapi-client/setup.py create mode 100644 testapi/testapi-client/testapiclient/__init__.py create mode 100644 testapi/testapi-client/testapiclient/auth.py create mode 100644 testapi/testapi-client/testapiclient/authHandler.py create mode 100644 testapi/testapi-client/testapiclient/config.py create mode 100644 testapi/testapi-client/testapiclient/httpClient.py create mode 100644 testapi/testapi-client/testapiclient/main.py create mode 100644 testapi/testapi-client/testapiclient/pods.py create mode 100644 testapi/testapi-client/testapiclient/user.py create mode 100644 testapi/testapi-client/tox.ini (limited to 'testapi') diff --git a/testapi/.gitignore b/testapi/.gitignore index e34365e..5be8583 100644 --- a/testapi/.gitignore +++ b/testapi/.gitignore @@ -12,4 +12,5 @@ build .ven docs/_build opnfv_testapi/tests/UI/coverage -3rd_party/static/testapi-ui/testapi-ui \ No newline at end of file +3rd_party/static/testapi-ui/testapi-ui + diff --git a/testapi/testapi-client/etc/config.ini b/testapi/testapi-client/etc/config.ini new file mode 100644 index 0000000..dde4bdd --- /dev/null +++ b/testapi/testapi-client/etc/config.ini @@ -0,0 +1,6 @@ +[api] +url = http://localhost:8000/api/v1 + +[cas] +signin_return = /auth/signin_return +auth_url = https://identity.linuxfoundation.org/user/login?destination=cas/login%3Fservice%3D \ No newline at end of file diff --git a/testapi/testapi-client/requirements.txt b/testapi/testapi-client/requirements.txt new file mode 100644 index 0000000..0c6ef77 --- /dev/null +++ b/testapi/testapi-client/requirements.txt @@ -0,0 +1,8 @@ +setuptools>=16.0,!=24.0.0,!=34.0.0,!=34.0.1,!=34.0.2,!=34.0.3,!=34.1.0,!=34.1.1,!=34.2.0,!=34.3.0,!=34.3.1,!=34.3.2 # PSF/ZPL + +pbr>=2.0.0,!=2.1.0 # Apache-2.0 +cmd2>=0.6.7 # MIT +PrettyTable<0.8,>=0.7.1 # BSD +pyparsing>=2.1.0 # MIT +six>=1.10.0 # MIT +cliff \ No newline at end of file diff --git a/testapi/testapi-client/setup.cfg b/testapi/testapi-client/setup.cfg new file mode 100644 index 0000000..1e25b73 --- /dev/null +++ b/testapi/testapi-client/setup.cfg @@ -0,0 +1,59 @@ +[metadata] +name = testapi-client + +[global] +setup-hooks = + pbr.hooks.setup_hook + +[files] +packages = + testapiclient + +data_files = + /etc/testapiclient = etc/config.ini + +[entry_points] +console_scripts = + testapi = testapiclient.main:main + +testapi = + auth = testapiclient.auth:Auth + pod create = testapiclient.pods:PodCreate + pod get = testapiclient.pods:PodGet + pod delete = testapiclient.pods:PodDelete + pod getone = testapiclient.pods:PodGetOne + + project create = testapiclient.projects:ProjectCreate + project get = testapiclient.projects:ProjectGet + project delete = testapiclient.projects:ProjectDelete + project put = testapiclient.projects:ProjectPut + + testcase create = testapiclient.testcase:TestCaseCreate + testcase get = testapiclient.testcase:TestCaseGet + testcase delete = testapiclient.testcase:TestCaseDelete + testcase put = testapiclient.testcase:TestCasePut + + scenario create = testapiclient.scenario:ScenarioCreate + scenario get = testapiclient.scenario:ScenarioGet + scenario delete = testapiclient.scenario:ScenarioDelete + scenario put = testapiclient.scenario:ScenarioPut + + scenario addscore = testapiclient.scenario:ScenarioAddScore + + scenario addyi = testapiclient.scenario:ScenarioAddTI + + scenario addcustom = testapiclient.scenario:ScenarioAddCustom + scenario updatecustom = testapiclient.scenario:ScenarioUpdateCustom + scenario deletecustom = testapiclient.scenario:ScenarioDeleteCustom + + scenario addproject = testapiclient.scenario:ScenarioAddProject + scenario deleteproject = testapiclient.scenario:ScenarioDeleteProject + + scenario addversion = testapiclient.scenario:ScenarioAddVersion + scenario deleteversion = testapiclient.scenario:ScenarioDeleteVersion + + result get = testapiclient.results:ResultGet +[egg_info] +tag_build = +tag_date = 0 +tag_svn_revision = 0 diff --git a/testapi/testapi-client/setup.py b/testapi/testapi-client/setup.py new file mode 100644 index 0000000..96b6dbf --- /dev/null +++ b/testapi/testapi-client/setup.py @@ -0,0 +1,11 @@ + +import setuptools + +try: + import multiprocessing # noqa +except ImportError: + pass + +setuptools.setup( + setup_requires=['pbr>=2.0.0'], + pbr=True) diff --git a/testapi/testapi-client/testapiclient/__init__.py b/testapi/testapi-client/testapiclient/__init__.py new file mode 100644 index 0000000..363bc38 --- /dev/null +++ b/testapi/testapi-client/testapiclient/__init__.py @@ -0,0 +1,8 @@ +############################################################################## +# Copyright (c) 2016 ZTE Corporation +# feng.xiaowei@zte.com.cn +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## diff --git a/testapi/testapi-client/testapiclient/auth.py b/testapi/testapi-client/testapiclient/auth.py new file mode 100644 index 0000000..7799d60 --- /dev/null +++ b/testapi/testapi-client/testapiclient/auth.py @@ -0,0 +1,22 @@ +import logging +from cliff.command import Command +from authHandler import AuthHandler + + +class Auth(Command): + "Handle Authentication for users" + + log = logging.getLogger(__name__) + + def get_parser(self, prog_name): + parser = super(Auth, self).get_parser(prog_name) + parser.add_argument('-u', type=str, required=True, help='Username for authentication') + parser.add_argument('-p', type=str, required=True, help='Password for authentication') + return parser + + def take_action(self, parsed_args): + response = AuthHandler.authenticate(parsed_args.u, parsed_args.p) + if "login" in response.text: + print "Authentication has failed. Please check your username and password." + else: + print "Authentication has been successful!" diff --git a/testapi/testapi-client/testapiclient/authHandler.py b/testapi/testapi-client/testapiclient/authHandler.py new file mode 100644 index 0000000..a421cf8 --- /dev/null +++ b/testapi/testapi-client/testapiclient/authHandler.py @@ -0,0 +1,16 @@ +import requests +from user import User +from config import Config +import urllib + + +class AuthHandler: + + @staticmethod + def authenticate(username, password): + session = requests.Session() + hostname = Config.config.get("cas", "auth_url") + urllib.quote(Config.config.get("api", "url")) + Config.config.get("cas", "signin_return") + data = {'name': username, 'pass': password, 'form_id': 'user_login'} + response = session.post(hostname, data) + User.session = session + return response diff --git a/testapi/testapi-client/testapiclient/config.py b/testapi/testapi-client/testapiclient/config.py new file mode 100644 index 0000000..7bc165f --- /dev/null +++ b/testapi/testapi-client/testapiclient/config.py @@ -0,0 +1,14 @@ +import ConfigParser +import io + + +class Config: + # Load the configuration file + config = '' + + @staticmethod + def parse_conf(): + with open("/etc/testapiclient/config.ini") as f: + sample_config = f.read() + Config.config = ConfigParser.RawConfigParser(allow_no_value=True) + Config.config.readfp(io.BytesIO(sample_config)) diff --git a/testapi/testapi-client/testapiclient/httpClient.py b/testapi/testapi-client/testapiclient/httpClient.py new file mode 100644 index 0000000..bc45f36 --- /dev/null +++ b/testapi/testapi-client/testapiclient/httpClient.py @@ -0,0 +1,44 @@ +import json +import requests + + +class HTTPClient(): + + __instance = None + headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} + + @staticmethod + def get_Instance(): + """ Static access method. """ + if HTTPClient.__instance is None: + HTTPClient() + return HTTPClient.__instance + + def __init__(self): + """ Virtually private constructor. """ + if HTTPClient.__instance is not None: + raise Exception("This class is a singleton!") + else: + HTTPClient.__instance = self + + def get(self, url): + r = requests.get(url) + if r.status_code == 200: + return r.json() + else: + return r.text + + def post(self, url, session, data): + r = session.post(url, data=json.dumps(data), headers=HTTPClient.headers) + return r + + def put(self, url, session, data): + r = session.put(url, data=json.dumps(data), headers=HTTPClient.headers) + return r.text + + def delete(self, url, session, *args): + if(args.__len__ > 0): + r = session.delete(url, data=json.dumps(args[0]), headers=HTTPClient.headers) + else: + r = session.delete(url) + return r.text diff --git a/testapi/testapi-client/testapiclient/main.py b/testapi/testapi-client/testapiclient/main.py new file mode 100644 index 0000000..07dbeb8 --- /dev/null +++ b/testapi/testapi-client/testapiclient/main.py @@ -0,0 +1,40 @@ +import sys +import requests +from user import User +from config import Config +from cliff.app import App +from cliff.commandmanager import CommandManager + + +class TestAPIClient(App): + + def __init__(self): + super(TestAPIClient, self).__init__( + description='TestAPI Client', + version='0.1', + command_manager=CommandManager('testapi'), + deferred_help=True, + ) + User.session = requests.Session() + # Configure development or Production mode + Config.parse_conf() + + def initialize_app(self, argv): + self.LOG.debug('initialize_app') + + def prepare_to_run_command(self, cmd): + self.LOG.debug('prepare_to_run_command %s', cmd.__class__.__name__) + + def clean_up(self, cmd, result, err): + self.LOG.debug('clean_up %s', cmd.__class__.__name__) + if err: + self.LOG.debug('got an error: %s', err) + + +def main(argv=sys.argv[1:]): + myapp = TestAPIClient() + return myapp.run(argv) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/testapi/testapi-client/testapiclient/pods.py b/testapi/testapi-client/testapiclient/pods.py new file mode 100644 index 0000000..f5e2fe9 --- /dev/null +++ b/testapi/testapi-client/testapiclient/pods.py @@ -0,0 +1,87 @@ +import json + +from user import User +from cliff.command import Command +from httpClient import HTTPClient +from authHandler import AuthHandler +from config import Config + + +class PodBase(Command): + pods_url = Config.config.get("api", "url") + "/pods" + + +class PodGet(PodBase): + "Handle get request for pods" + + def get_parser(self, prog_name): + parser = super(PodGet, self).get_parser(prog_name) + parser.add_argument('-name', default='', help='Search pods using name') + return parser + + def take_action(self, parsed_args): + http_client = HTTPClient.get_Instance() + url = PodGet.pods_url + if(parsed_args.name): + url = PodGet.pods_url + "?name=" + parsed_args.name + pods = http_client.get(url) + print pods + + +class PodGetOne(PodBase): + "Handle get request for pod by name" + + def get_parser(self, prog_name): + parser = super(PodGetOne, self).get_parser(prog_name) + parser.add_argument('-name', default='', help='Find pod using name', required=True) + return parser + + def take_action(self, parsed_args): + http_client = HTTPClient.get_Instance() + pods = http_client.get(PodGetOne.pods_url + "/" + parsed_args.name) + print pods + + +class PodCreate(PodBase): + "Handle post request for pods" + + def get_parser(self, prog_name): + parser = super(PodCreate, self).get_parser(prog_name) + parser.add_argument('-u', type=str, help='Username for authentication') + parser.add_argument('-p', type=str, help='Password for authentication') + parser.add_argument('pod', type=json.loads, help='Pod create request format :\n\'{ "role": "", "name": "", "details": "", "mode": ""}\',\n role should be either "community-ci" or "production-ci", and mode should be either "metal" or "virtual.') + return parser + + def take_action(self, parsed_args): + http_client = HTTPClient.get_Instance() + if(parsed_args.u and parsed_args.p): + response = AuthHandler.authenticate(parsed_args.u, parsed_args.p) + if "login" in response.text: + print "Authentication has failed. Please check your username and password." + return + response = http_client.post(PodCreate.pods_url, User.session, parsed_args.pod) + if response.status_code == 200: + print "Pod has been successfully created!" + else: + print response.text + + +class PodDelete(PodBase): + "Handle delete request for pods" + + def get_parser(self, prog_name): + parser = super(PodDelete, self).get_parser(prog_name) + parser.add_argument('-u', type=str, help='Username for authentication') + parser.add_argument('-p', type=str, help='Password for authentication') + parser.add_argument('-name', type=str, required=True, help='Delete pods using name') + return parser + + def take_action(self, parsed_args): + http_client = HTTPClient.get_Instance() + if(parsed_args.u and parsed_args.p): + response = AuthHandler.authenticate(parsed_args.u, parsed_args.p) + if "login" in response.text: + print "Authentication has failed. Please check your username and password." + return + pods = http_client.delete(PodDelete.pods_url + "/" + parsed_args.name, User.session) + print pods diff --git a/testapi/testapi-client/testapiclient/user.py b/testapi/testapi-client/testapiclient/user.py new file mode 100644 index 0000000..7e72163 --- /dev/null +++ b/testapi/testapi-client/testapiclient/user.py @@ -0,0 +1,2 @@ +class User(): + session = None diff --git a/testapi/testapi-client/tox.ini b/testapi/testapi-client/tox.ini new file mode 100644 index 0000000..cf73b91 --- /dev/null +++ b/testapi/testapi-client/tox.ini @@ -0,0 +1,32 @@ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = pep8,py27 +skipsdist = True +sitepackages = True + +[testenv] +usedevelop = True +install_command = pip install -U {opts} {packages} +deps = + -rrequirements.txt +setenv= + HOME = {envtmpdir} + PYTHONPATH = {toxinidir} + + +[testenv:pep8] +deps = flake8 +commands = flake8 {toxinidir} + +[flake8] +# H803 skipped on purpose per list discussion. +# E123, E125 skipped as they are invalid PEP-8. + +show-source = True +ignore = E123,E125,H803,E501 +builtins = _ +exclude = bin, build, dist, lib, local, .git, .eggs, .tox, .venv, venv, testapi_client.egg-info \ No newline at end of file -- cgit 1.2.3-korg