create Testapi client 55/51355/13
authorthuva4 <tharma.thuva@gmail.com>
Tue, 30 Jan 2018 14:20:33 +0000 (19:50 +0530)
committerthuva4 <tharma.thuva@gmail.com>
Thu, 8 Feb 2018 09:25:43 +0000 (14:55 +0530)
implement auth in testapi client
implement pods in testapi client

Change-Id: Idd5c9dcf938ad5994e655b55d49625ab462ab710
Signed-off-by: thuva4 <tharma.thuva@gmail.com>
15 files changed:
.gitignore
testapi/.gitignore
testapi/testapi-client/etc/config.ini [new file with mode: 0644]
testapi/testapi-client/requirements.txt [new file with mode: 0644]
testapi/testapi-client/setup.cfg [new file with mode: 0644]
testapi/testapi-client/setup.py [new file with mode: 0644]
testapi/testapi-client/testapiclient/__init__.py [new file with mode: 0644]
testapi/testapi-client/testapiclient/auth.py [new file with mode: 0644]
testapi/testapi-client/testapiclient/authHandler.py [new file with mode: 0644]
testapi/testapi-client/testapiclient/config.py [new file with mode: 0644]
testapi/testapi-client/testapiclient/httpClient.py [new file with mode: 0644]
testapi/testapi-client/testapiclient/main.py [new file with mode: 0644]
testapi/testapi-client/testapiclient/pods.py [new file with mode: 0644]
testapi/testapi-client/testapiclient/user.py [new file with mode: 0644]
testapi/testapi-client/tox.ini [new file with mode: 0644]

index 8cf2a3b..5881045 100644 (file)
@@ -25,3 +25,5 @@ nosetests.xml
 .tox
 *.retry
 job_output/
+.vscode
+testapi/testapi-client/pip-selfcheck.json
index e34365e..5be8583 100644 (file)
@@ -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 (file)
index 0000000..dde4bdd
--- /dev/null
@@ -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 (file)
index 0000000..0c6ef77
--- /dev/null
@@ -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 (file)
index 0000000..1e25b73
--- /dev/null
@@ -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 (file)
index 0000000..96b6dbf
--- /dev/null
@@ -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 (file)
index 0000000..363bc38
--- /dev/null
@@ -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 (file)
index 0000000..7799d60
--- /dev/null
@@ -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 (file)
index 0000000..a421cf8
--- /dev/null
@@ -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 (file)
index 0000000..7bc165f
--- /dev/null
@@ -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 (file)
index 0000000..bc45f36
--- /dev/null
@@ -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 (file)
index 0000000..07dbeb8
--- /dev/null
@@ -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 (file)
index 0000000..f5e2fe9
--- /dev/null
@@ -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 (file)
index 0000000..7e72163
--- /dev/null
@@ -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 (file)
index 0000000..cf73b91
--- /dev/null
@@ -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