diff options
26 files changed, 418 insertions, 713 deletions
diff --git a/testapi/opnfv_testapi/handlers/base_handlers.py b/testapi/opnfv_testapi/handlers/base_handlers.py index 350c38d..3dbd53a 100644 --- a/testapi/opnfv_testapi/handlers/base_handlers.py +++ b/testapi/opnfv_testapi/handlers/base_handlers.py @@ -79,8 +79,8 @@ class GenericApiHandler(web.RequestHandler): @check.valid_token @check.no_body @check.miss_fields - @check.new_not_exists @check.is_authorized + @check.new_not_exists @check.values_check @check.carriers_exist def _create(self, **kwargs): diff --git a/testapi/opnfv_testapi/handlers/result_handlers.py b/testapi/opnfv_testapi/handlers/result_handlers.py index 74acb2e..edcac6e 100644 --- a/testapi/opnfv_testapi/handlers/result_handlers.py +++ b/testapi/opnfv_testapi/handlers/result_handlers.py @@ -48,8 +48,6 @@ class GenericResultHandler(base_handlers.GenericApiHandler): period = datetime.now() - timedelta(days=v) obj = {"$gte": str(period)} query['start_date'] = obj - elif k == 'trust_indicator': - query[k + '.current'] = float(v) elif k == 'from': date_range.update({'$gte': str(v)}) elif k == 'to': @@ -108,8 +106,6 @@ class ResultsCLHandler(GenericResultHandler): - to : ending time in 2016-01-01 or 2016-01-01 00:01:23 - scenario : the test scenario (previously version) - criteria : the global criteria status passed or failed - - trust_indicator : evaluate the stability of the test case - to avoid running systematically long and stable test case GET /results/project=functest&case=vPing&version=Arno-R1 \ &pod=pod_name&period=15 @@ -168,10 +164,6 @@ class ResultsCLHandler(GenericResultHandler): @type page: L{int} @in page: query @required page: False - @param trust_indicator: must be float - @type trust_indicator: L{float} - @in trust_indicator: query - @required trust_indicator: False @param descend: true, newest2oldest; false, oldest2newest @type descend: L{string} @in descend: query @@ -228,19 +220,3 @@ class ResultsGURHandler(GenericResultHandler): query = dict() query["_id"] = objectid.ObjectId(result_id) self._get_one(query=query) - - @swagger.operation(nickname="updateTestResultById") - def put(self, result_id): - """ - @description: update a single result by _id - @param body: fields to be updated - @type body: L{ResultUpdateRequest} - @in body: body - @rtype: L{Result} - @return 200: update success - @raise 404: result not exist - @raise 403: nothing to update - """ - query = {'_id': objectid.ObjectId(result_id)} - db_keys = [] - self._update(query=query, db_keys=db_keys) diff --git a/testapi/opnfv_testapi/models/result_models.py b/testapi/opnfv_testapi/models/result_models.py index f8379d8..602318a 100644 --- a/testapi/opnfv_testapi/models/result_models.py +++ b/testapi/opnfv_testapi/models/result_models.py @@ -11,45 +11,7 @@ from opnfv_testapi.tornado_swagger import swagger @swagger.model() -class TIHistory(base_models.ModelBase): - """ - @ptype step: L{float} - """ - def __init__(self, date=None, step=0): - self.date = date - self.step = step - - -@swagger.model() -class TI(base_models.ModelBase): - """ - @property histories: trust_indicator update histories - @ptype histories: C{list} of L{TIHistory} - @ptype current: L{float} - """ - def __init__(self, current=0): - self.current = current - self.histories = list() - - def __eq__(self, other): - return (self.current == other.current and self._histories_eq(other)) - - def _histories_eq(self, other): - hs_equal = all(self.histories[i] == other.histories[i] - for i in range(len(self.histories))) - return len(self.histories) == len(other.histories) and hs_equal - - @staticmethod - def attr_parser(): - return {'histories': TIHistory} - - -@swagger.model() class ResultCreateRequest(base_models.ModelBase): - """ - @property trust_indicator: - @ptype trust_indicator: L{TI} - """ def __init__(self, pod_name=None, project_name=None, @@ -61,8 +23,7 @@ class ResultCreateRequest(base_models.ModelBase): details=None, build_tag=None, scenario=None, - criteria=None, - trust_indicator=None): + criteria=None): self.pod_name = pod_name self.project_name = project_name self.case_name = case_name @@ -74,35 +35,15 @@ class ResultCreateRequest(base_models.ModelBase): self.build_tag = build_tag self.scenario = scenario self.criteria = criteria - self.trust_indicator = trust_indicator if trust_indicator else TI(0) def __eq__(self, other): - simple_equal = all(getattr(self, k) == getattr(other, k) - for k in self.format().keys() - if k not in ['_id', 'trust_indicator']) - return simple_equal and self.trust_indicator == other.trust_indicator - - @staticmethod - def attr_parser(): - return {'trust_indicator': TI} - - -@swagger.model() -class ResultUpdateRequest(base_models.ModelBase): - """ - @property trust_indicator: - @ptype trust_indicator: L{TI} - """ - def __init__(self, trust_indicator=None): - self.trust_indicator = trust_indicator + return all(getattr(self, k) == getattr(other, k) + for k in self.format().keys() + if k not in ['_id']) @swagger.model() class TestResult(ResultCreateRequest): - """ - @property trust_indicator: used for long duration test case - @ptype trust_indicator: L{TI} - """ def __init__(self, _id=None, **kwargs): super(TestResult, self).__init__(**kwargs) self._id = _id diff --git a/testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js index ed5fe9f..1117ef5 100644 --- a/testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js +++ b/testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js @@ -63,12 +63,6 @@ describe('testing the Projects Link for anonymous user', function () { expect(cells.get(1).getText()).toContain("testproject"); }); - // it('redirect to project page when user clicks a project',function(){ - // var projectlink = element(by.linkText('testproject')).click(); - // var EC = browser.ExpectedConditions; - // browser.wait(EC.urlContains(baseURL+ '/#/projects/testproject'), 10000); - // }); - it('delete Operation is not visible for anonymous user ', function () { browser.get(baseURL+'#/projects'); var deleteOperation = element(by.css('a[title=Delete]')); @@ -158,10 +152,10 @@ describe('testing the Project Link for user who is not in submitter group', func expect(buttonCreate.isDisplayed()).toBeFalsy(); }); - it('Delete button is not visible for user ', function () { + it('Delete button is not visible for user ', function () { browser.get(baseURL+'#/projects'); - var buttonCreate = element(by.buttonText('Create')); - expect(buttonCreate.isDisplayed()).toBeFalsy(); + var buttonDelete = element(by.buttonText('Delete')); + expect(buttonDelete.isDisplayed()).toBeFalsy(); }); it('delete Operation is not visible for user ', function () { @@ -302,13 +296,13 @@ describe('testing the Project Link for user who is in submitter group', function expect(buttonCreate.isDisplayed()).toBe(true); }); - it('Delete button is not visible for anonymous user ', function () { + it('Delete button is visible for user ', function () { browser.get(baseURL+'#/projects'); - var buttonCreate = element(by.buttonText('Create')); - expect(buttonCreate.isDisplayed()).toBe(true); + var buttonDelete = element(by.buttonText('Delete')); + expect(buttonDelete.isDisplayed()).toBe(true); }); - it('delete Operation is not visible for user ', function () { + it('delete Operation is visible for user ', function () { browser.get(baseURL+'#/projects'); var deleteOperation = element(by.css('a[title=Delete]')); expect(deleteOperation.isDisplayed()).toBe(true); diff --git a/testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js index 132f77d..d091a38 100644 --- a/testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js +++ b/testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js @@ -30,7 +30,6 @@ describe('testing the result page for anonymous user', function () { "user": null, "installer": "fuel", "scenario": "test-scenario", - "trust_indicator": null, "public": "true", "version": "euphrates", "details": "", @@ -107,7 +106,6 @@ describe('testing the result page for anonymous user', function () { "user": null, "installer": "fuel", "scenario": "test-scenario", - "trust_indicator": null, "public": "true", "version": "euphrates", "details": "", @@ -254,7 +252,6 @@ describe('testing the result page for user', function () { "user": null, "installer": "fuel", "scenario": "test-scenario", - "trust_indicator": null, "public": "true", "version": "euphrates", "details": "", diff --git a/testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js b/testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js index bed80dd..e7c5fb0 100644 --- a/testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js +++ b/testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js @@ -32,154 +32,6 @@ describe('testing the scenarios page for anonymous user', function () { { "date": "2016-12-11 01:45", "score": "14/24" - }, - { - "date": "2016-12-15 05:28", - "score": "17/24" - }, - { - "date": "2016-12-17 03:41", - "score": "16/24" - }, - { - "date": "2018-01-22T18:30:00.000Z", - "score": "10/13" - } - ], - "trust_indicators": [ - { - "date": "2016-12-09 11:38", - "status": "silver" - }, - { - "date": "2016-12-25 08:22", - "status": "gold" - }, - { - "date": "2018-01-22T18:30:00.000Z", - "status": "sf" - }, - { - "date": "2018-01-17T18:30:00.000Z", - "status": "df" - } - ] - }, - { - "project": "functest", - "customs": [ - "vping_ssh", - "vping_userdata", - ], - "scores": [ - { - "date": "2016-12-09 11:28", - "score": "6/8" - }, - { - "date": "2016-12-14 15:34", - "score": "8/8" - }, - { - "date": "2016-12-19 13:22", - "score": "8/8" - }, - { - "date": "2016-12-22 18:17", - "score": "8/8" - }, - { - "date": "2016-12-25 08:22", - "score": "8/8" - } - ], - "trust_indicators": [ - { - "date": "2016-12-09 11:38", - "status": "silver" - } - ] - }, - { - "project": "sla", - "customs": [], - "scores": [ - { - "date": "2018-01-16T18:30:00.000Z", - "score": "sdS" - } - ], - "trust_indicators": [] - }, - { - "project": "dvsd", - "customs": [], - "scores": [], - "trust_indicators": [] - } - ] - }, - { - "owner": "dfgvds", - "version": "df", - "projects": [] - } - ] - }, - { - "installer": "fuel2", - "versions": [ - { - "owner": "testUser", - "version": "colorado", - "projects": [ - { - "project": "yardstick", - "customs": [ - "tc002", - "tc005", - "tc010", - "tc011" - ], - "scores": [ - { - "date": "2016-12-11 01:45", - "score": "14/24" - }, - { - "date": "2016-12-15 05:28", - "score": "17/24" - }, - { - "date": "2016-12-17 03:41", - "score": "16/24" - } - ], - "trust_indicators": [ - { - "date": "2016-12-09 11:38", - "status": "silver" - }, - { - "date": "2016-12-25 08:22", - "status": "gold" - } - ] - }, - { - "project": "functest", - "customs": [ - "vping_ssh", - "vping_userdata" - ], - "scores": [ - { - "date": "2016-12-09 11:28", - "score": "6/8" - }, - { - "date": "2016-12-14 15:34", - "score": "8/8" } ], "trust_indicators": [ @@ -197,7 +49,43 @@ describe('testing the scenarios page for anonymous user', function () { "_id": "5a50fcacsdgdsgdasgfvb861c", "name": "test-scenario", "creation_date": "2018-01-06 22:13:24.160407" - } + }, + { + "installers": [ + { + "installer": "fuel", + "versions": [ + { + "owner": "testUser", + "version": "colorado", + "projects": [ + { + "project": "yardstick", + "customs": [ + "dvs" + ], + "scores": [ + { + "date": "2016-12-11 01:45", + "score": "14/24" + } + ], + "trust_indicators": [ + { + "date": "2016-12-09 11:38", + "status": "silver" + } + ] + } + ] + } + ] + } + ], + "_id": "5a50fcacsdgdsgdasgfvb861d", + "name": "z-test-scenario", + "creation_date": "2018-01-06 22:13:24.160407" + } ] } } @@ -229,6 +117,15 @@ describe('testing the scenarios page for anonymous user', function () { expect(cells.get(1).getText()).toContain("test-scenario"); }); + it('Sort scenarios', function () { + browser.get(baseURL+"#/scenarios"); + var sort = element(by.xpath('//*[@id="ng-app"]/body/div/div[4]/div/table/thead/tr/th[2]/a[2]/span')) + sort.click(); + var row = element.all(by.repeater('(index, scenario) in ctrl.data.scenarios')).first(); + var cells = row.all(by.tagName('td')); + expect(cells.get(1).getText()).toContain("z-test-scenario"); + }); + it('create button is not visible for anonymous user ', function () { browser.get(baseURL+'#/scenarios'); var buttonCreate = element(by.buttonText('Create')); @@ -271,154 +168,6 @@ describe('testing the scenarios page for user', function () { { "date": "2016-12-11 01:45", "score": "14/24" - }, - { - "date": "2016-12-15 05:28", - "score": "17/24" - }, - { - "date": "2016-12-17 03:41", - "score": "16/24" - }, - { - "date": "2018-01-22T18:30:00.000Z", - "score": "10/13" - } - ], - "trust_indicators": [ - { - "date": "2016-12-09 11:38", - "status": "silver" - }, - { - "date": "2016-12-25 08:22", - "status": "gold" - }, - { - "date": "2018-01-22T18:30:00.000Z", - "status": "sf" - }, - { - "date": "2018-01-17T18:30:00.000Z", - "status": "df" - } - ] - }, - { - "project": "functest", - "customs": [ - "vping_ssh", - "vping_userdata", - ], - "scores": [ - { - "date": "2016-12-09 11:28", - "score": "6/8" - }, - { - "date": "2016-12-14 15:34", - "score": "8/8" - }, - { - "date": "2016-12-19 13:22", - "score": "8/8" - }, - { - "date": "2016-12-22 18:17", - "score": "8/8" - }, - { - "date": "2016-12-25 08:22", - "score": "8/8" - } - ], - "trust_indicators": [ - { - "date": "2016-12-09 11:38", - "status": "silver" - } - ] - }, - { - "project": "sla", - "customs": [], - "scores": [ - { - "date": "2018-01-16T18:30:00.000Z", - "score": "sdS" - } - ], - "trust_indicators": [] - }, - { - "project": "dvsd", - "customs": [], - "scores": [], - "trust_indicators": [] - } - ] - }, - { - "owner": "dfgvds", - "version": "df", - "projects": [] - } - ] - }, - { - "installer": "fuel2", - "versions": [ - { - "owner": "testUser", - "version": "colorado", - "projects": [ - { - "project": "yardstick", - "customs": [ - "tc002", - "tc005", - "tc010", - "tc011" - ], - "scores": [ - { - "date": "2016-12-11 01:45", - "score": "14/24" - }, - { - "date": "2016-12-15 05:28", - "score": "17/24" - }, - { - "date": "2016-12-17 03:41", - "score": "16/24" - } - ], - "trust_indicators": [ - { - "date": "2016-12-09 11:38", - "status": "silver" - }, - { - "date": "2016-12-25 08:22", - "status": "gold" - } - ] - }, - { - "project": "functest", - "customs": [ - "vping_ssh", - "vping_userdata" - ], - "scores": [ - { - "date": "2016-12-09 11:28", - "score": "6/8" - }, - { - "date": "2016-12-14 15:34", - "score": "8/8" } ], "trust_indicators": [ @@ -514,13 +263,13 @@ describe('testing the scenarios page for user', function () { expect(cells.get(1).getText()).toContain("test-scenario"); }); - it('create button is not visible for user ', function () { + it('create button is visible for user ', function () { browser.get(baseURL+'#/scenarios'); var buttonCreate = element(by.buttonText('Create')); expect(buttonCreate.isDisplayed()).toBe(true); }); - it('delete button is not visible for user ', function () { + it('delete button is visible for user ', function () { browser.get(baseURL+'#/scenarios'); var buttonDelete = element(by.buttonText('Delete')); expect(buttonDelete.isDisplayed()).toBe(true); diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_result.py b/testapi/opnfv_testapi/tests/unit/handlers/test_result.py index 892256a..6435367 100644 --- a/testapi/opnfv_testapi/tests/unit/handlers/test_result.py +++ b/testapi/opnfv_testapi/tests/unit/handlers/test_result.py @@ -105,18 +105,6 @@ class TestResultCreate(TestResultBase): req.details = {'1.name': 'dot_name'} return req - @executor.create(httplib.OK, '_assert_no_ti') - def test_no_ti(self): - req = copy.deepcopy(self.req_d) - req.trust_indicator = rm.TI(0) - self.actual_req = req - return req - - def _assert_no_ti(self, body): - _id = body.href.split('/')[-1] - code, body = self.get(_id) - self.assert_res(body, self.actual_req) - class TestResultGet(TestResultBase): def setUp(self): @@ -158,10 +146,6 @@ class TestResultGet(TestResultBase): return self._set_query('scenario') @executor.query(httplib.OK, '_query_success', 3) - def test_queryTrustIndicator(self): - return self._set_query('trust_indicator') - - @executor.query(httplib.OK, '_query_success', 3) def test_queryCriteria(self): return self._set_query('criteria') @@ -190,7 +174,6 @@ class TestResultGet(TestResultBase): 'installer', 'build_tag', 'scenario', - 'trust_indicator', 'criteria', period=5) @@ -202,7 +185,6 @@ class TestResultGet(TestResultBase): 'installer', 'build_tag', 'scenario', - 'trust_indicator', 'criteria', pod='notExistPod', period=1) @@ -244,8 +226,6 @@ class TestResultGet(TestResultBase): def get_value(arg): if arg in ['pod', 'project', 'case']: return getattr(self.req_d, arg + '_name') - elif arg == 'trust_indicator': - return self.req_d.trust_indicator.current else: return getattr(self.req_d, arg) @@ -255,24 +235,3 @@ class TestResultGet(TestResultBase): for k, v in kwargs.iteritems(): query.append((k, v)) return urllib.urlencode(query) - - -class TestResultUpdate(TestResultBase): - def setUp(self): - super(TestResultUpdate, self).setUp() - self.req_d_id = self._create_d() - - @executor.update(httplib.OK, '_assert_update_ti') - def test_success(self): - update_date = str(datetime.now() + timedelta(days=1)) - update_step = -0.05 - self.after_update = copy.deepcopy(self.req_d) - self.after_update.trust_indicator.current += update_step - self.after_update.trust_indicator.histories.append( - rm.TIHistory(update_date, update_step)) - update = rm.ResultUpdateRequest( - trust_indicator=self.after_update.trust_indicator) - return update, self.req_d_id - - def _assert_update_ti(self, request, body): - self.assert_res(body, self.after_update) diff --git a/testapi/opnfv_testapi/tests/unit/templates/test_result.json b/testapi/opnfv_testapi/tests/unit/templates/test_result.json index b7cb910..8f1d5fa 100644 --- a/testapi/opnfv_testapi/tests/unit/templates/test_result.json +++ b/testapi/opnfv_testapi/tests/unit/templates/test_result.json @@ -1,10 +1,6 @@ { "project_name": "functest", "scenario": "odl-l2", - "trust_indicator": { - "current": 0.7, - "histories": [] - }, "case_name": "vPing", "build_tag": "v3.0", "public": "true", diff --git a/testapi/opnfv_testapi/ui/components/results/result/result.html b/testapi/opnfv_testapi/ui/components/results/result/result.html index b435dce..52d794e 100644 --- a/testapi/opnfv_testapi/ui/components/results/result/result.html +++ b/testapi/opnfv_testapi/ui/components/results/result/result.html @@ -48,28 +48,6 @@ <td width="90%" class="podsTableLeftTd">{{ctrl.data.stop_date}}</td> </tr> <tr style="padding:9px"> - <td class="podsTableTd">Trust Indicator :</td> - <td width="90%" class="podsTableLeftTd"> - <a ng-click="ctrl.showTrustIndicator()"> - <p ng-if="ctrl.trust_indicator">Hide</p> - <p ng-if="!ctrl.trust_indicator">Show</p> - </a> - <table class="table" ng-class="{'hidden' : !ctrl.trust_indicator}" style="margin:10px"> - <tbody> - <tr style="padding:9px"></tr> - <tr style="padding:9px" > - <td class="podsTableTd">Current :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.trust_indicator.current}}</td> - </tr> - <tr style="padding:9px" > - <td class="podsTableTd">Histories :</td> - <td width="90%" class="podsTableLeftTd">{{ctrl.data.trust_indicator.histories}}</td> - </tr> - </tbody> - </table> - </td> - </tr> - <tr style="padding:9px"> <td class="podsTableTd">Details :</td> <td width="90%" class="podsTableLeftTd"> <a ng-click="ctrl.showDetails()"> diff --git a/testapi/opnfv_testapi/ui/components/results/result/resultController.js b/testapi/opnfv_testapi/ui/components/results/result/resultController.js index 028e5d8..cb5dd28 100644 --- a/testapi/opnfv_testapi/ui/components/results/result/resultController.js +++ b/testapi/opnfv_testapi/ui/components/results/result/resultController.js @@ -54,14 +54,6 @@ }); } - function showTrustIndicator(){ - if(ctrl.trust_indicator){ - ctrl.trust_indicator = false - }else{ - ctrl.trust_indicator = true - } - } - function showDetails(){ if(ctrl.details){ ctrl.details = false diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html b/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html index 9057b0f..bde946c 100644 --- a/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html +++ b/testapi/opnfv_testapi/ui/components/scenarios/scenarios.html @@ -27,7 +27,14 @@ <tr style=" text-align: center;"> <th style="width: 1%;">Bulk Select</th> - <th style="width: 80%;">Name</th> + <th style="width: 80%;">Name + <a class="text-danger" ng-click="ctrl.sortBy()" ng-class="{ 'hidden': ctrl.sortName }" > + <span class="glyphicon glyphicon-sort-by-alphabet pull-right" aria-hidden="true"></span> + </a> + <a class="text-danger" ng-click="ctrl.sortBy()" ng-class="{ 'hidden': !ctrl.sortName}" > + <span class="glyphicon glyphicon-sort-by-alphabet-alt pull-right" aria-hidden="true"></span> + </a> + </th> <th style="width: 19%;" ng-class="{'hidden': !auth.isAuthenticated}">Operations</th> </tr> </thead> diff --git a/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js b/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js index 98e4089..240287c 100644 --- a/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js +++ b/testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js @@ -21,7 +21,7 @@ ScenariosController.$inject = [ '$scope', '$http', '$filter', '$state', '$window', '$uibModal', 'testapiApiUrl', - 'raiseAlert', 'confirmModal' + 'raiseAlert', 'confirmModal', 'sortService' ]; /** @@ -30,7 +30,7 @@ * through projects declared in TestAPI. */ function ScenariosController($scope, $http, $filter, $state, $window, $uibModal, testapiApiUrl, - raiseAlert, confirmModal) { + raiseAlert, confirmModal, sortService) { var ctrl = this; ctrl.url = testapiApiUrl + '/scenarios'; @@ -44,8 +44,9 @@ ctrl.deleteScenario = deleteScenario; ctrl.openBatchDeleteModal = openBatchDeleteModal; ctrl.deleteBatchScenario = deleteBatchScenario - + ctrl.sortBy = sortBy ctrl.checkBox = []; + ctrl.sortName = false function openUpdateModal(name){ $uibModal.open({ @@ -68,6 +69,11 @@ confirmModal("Delete", 'scenarios', ctrl.deleteScenario,name); } + function sortBy(){ + ctrl.data.scenarios = sortService.sortFunction(ctrl.data.scenarios, 'name' , ctrl.sortName) + ctrl.sortName=!ctrl.sortName + } + function deleteScenario(name){ var scenarioURL = ctrl.url+"/"+name; ctrl.scenarioRequest = @@ -142,6 +148,7 @@ ctrl.resultsRequest = $http.get(ctrl.url).success(function (data) { ctrl.data = data; + ctrl.sortBy() }).catch(function (data) { ctrl.data = null; ctrl.showError = true; diff --git a/testapi/setup.cfg b/testapi/setup.cfg index 570d138..e83da5e 100644 --- a/testapi/setup.cfg +++ b/testapi/setup.cfg @@ -24,7 +24,7 @@ packages = opnfv_testapi data_files = -# /etc/opnfv_testapi = etc/config.ini + /etc/opnfv_testapi = etc/config.ini /usr/local/share/opnfv_testapi = 3rd_party/static/* /usr/local/share/opnfv_testapi/testapi-ui = opnfv_testapi/ui/* diff --git a/testapi/testapi-client/testapiclient/cli/auth.py b/testapi/testapi-client/testapiclient/cli/auth.py deleted file mode 100644 index 434c55a..0000000 --- a/testapi/testapi-client/testapiclient/cli/auth.py +++ /dev/null @@ -1,14 +0,0 @@ -from testapiclient.utils import command -from testapiclient.utils import identity - - -class Auth(command.Command): - "Handle Authentication for users" - - def get_parser(self, prog_name): - parser = super(Auth, self).get_parser(prog_name) - return parser - - @identity.authenticate - def take_action(self, parsed_args): - print "Authentication has been successful!" diff --git a/testapi/testapi-client/testapiclient/cli/pods.py b/testapi/testapi-client/testapiclient/cli/pods.py index 9cadee7..8d0970b 100644 --- a/testapi/testapi-client/testapiclient/cli/pods.py +++ b/testapi/testapi-client/testapiclient/cli/pods.py @@ -1,17 +1,15 @@ import json from testapiclient.utils import command -from testapiclient.utils import http_client as client -from testapiclient.utils import identity -from testapiclient.utils import url_parse as up +from testapiclient.utils import urlparse def pods_url(): - return up.resource_join('pods') + return urlparse.resource_join('pods') def pod_url(parsed_args): - return up.path_join(pods_url(), parsed_args.name) + return urlparse.path_join(pods_url(), parsed_args.name) class PodGet(command.Lister): @@ -34,7 +32,8 @@ class PodGet(command.Lister): "creation_date", ) - data = client.get(up.query_by(pods_url(), 'name', parsed_args)) + data = self.app.client_manager.get( + urlparse.query_by(pods_url(), 'name', parsed_args)) return self.format_output(columns, data.get('pods', [])) @@ -49,7 +48,8 @@ class PodGetOne(command.ShowOne): return parser def take_action(self, parsed_args): - return self.format_output(client.get(pod_url(parsed_args))) + return self.format_output( + self.app.client_manager.get(pod_url(parsed_args))) class PodCreate(command.ShowOne): @@ -66,9 +66,9 @@ class PodCreate(command.ShowOne): 'mode should be either "metal" or "virtual.') return parser - @identity.authenticate def take_action(self, parsed_args): - return self.format_output(client.post(pods_url(), parsed_args.pod)) + return self.format_output( + self.app.client_manager.post(pods_url(), parsed_args.pod)) class PodDelete(command.Command): @@ -81,6 +81,5 @@ class PodDelete(command.Command): help='Delete pods using name') return parser - @identity.authenticate def take_action(self, parsed_args): - return client.delete(pod_url(parsed_args)) + return self.app.client_manager.delete(pod_url(parsed_args)) diff --git a/testapi/testapi-client/testapiclient/cli/projects.py b/testapi/testapi-client/testapiclient/cli/projects.py index 5fa6894..510acc8 100644 --- a/testapi/testapi-client/testapiclient/cli/projects.py +++ b/testapi/testapi-client/testapiclient/cli/projects.py @@ -1,17 +1,15 @@ import json from testapiclient.utils import command -from testapiclient.utils import http_client as client -from testapiclient.utils import identity -from testapiclient.utils import url_parse as up +from testapiclient.utils import urlparse def projects_url(): - return up.resource_join('projects') + return urlparse.resource_join('projects') def project_url(parsed_args): - return up.path_join(projects_url(), parsed_args.name) + return urlparse.path_join(projects_url(), parsed_args.name) class ProjectGet(command.Lister): @@ -19,7 +17,6 @@ class ProjectGet(command.Lister): def get_parser(self, prog_name): parser = super(ProjectGet, self).get_parser(prog_name) parser.add_argument('-name', - default='', help='Search projects by name') return parser @@ -30,22 +27,22 @@ class ProjectGet(command.Lister): 'creator', 'creation_date' ) - data = client.get(up.query_by(projects_url(), 'name', parsed_args)) - return self.format_output(columns, data.get('project', [])) + data = self.app.client_manager.get( + urlparse.query_by(projects_url(), 'name', parsed_args)) + return self.format_output(columns, data.get('projects', [])) class ProjectGetOne(command.ShowOne): def get_parser(self, prog_name): parser = super(ProjectGetOne, self).get_parser(prog_name) - parser.add_argument('-name', - default='', - required=True, + parser.add_argument('name', help='Search project by name') return parser def take_action(self, parsed_args): - return self.format_output(client.get(project_url(parsed_args))) + return self.format_output( + self.app.client_manager.get(project_url(parsed_args))) class ProjectCreate(command.ShowOne): @@ -59,34 +56,30 @@ class ProjectCreate(command.ShowOne): '"description": (optional)""}') return parser - @identity.authenticate def take_action(self, parsed_args): return self.format_output( - client.post(projects_url(), parsed_args.project)) + self.app.client_manager.post(projects_url(), parsed_args.project)) class ProjectDelete(command.Command): def get_parser(self, prog_name): parser = super(ProjectDelete, self).get_parser(prog_name) - parser.add_argument('-name', + parser.add_argument('name', type=str, - required=True, help='Delete project by name') return parser - @identity.authenticate def take_action(self, parsed_args): - return client.delete(project_url(parsed_args)) + return self.app.client_manager.delete(project_url(parsed_args)) class ProjectPut(command.ShowOne): def get_parser(self, prog_name): parser = super(ProjectPut, self).get_parser(prog_name) - parser.add_argument('-name', + parser.add_argument('name', type=str, - required=True, help='Update project by name') parser.add_argument('project', type=json.loads, @@ -95,7 +88,7 @@ class ProjectPut(command.ShowOne): '"description": (optional)""}') return parser - @identity.authenticate def take_action(self, parsed_args): return self.format_output( - client.put(project_url(parsed_args), parsed_args.project)) + self.app.client_manager.put( + project_url(parsed_args), parsed_args.project)) diff --git a/testapi/testapi-client/testapiclient/main.py b/testapi/testapi-client/testapiclient/main.py index dfa6284..a448146 100644 --- a/testapi/testapi-client/testapiclient/main.py +++ b/testapi/testapi-client/testapiclient/main.py @@ -2,9 +2,8 @@ import sys from cliff import app from cliff import commandmanager -import requests -from testapiclient.utils import user +from testapiclient.utils import clientmanager class TestAPIClient(app.App): @@ -16,13 +15,29 @@ class TestAPIClient(app.App): command_manager=commandmanager.CommandManager('testapi'), deferred_help=True, ) - user.User.session = requests.Session() + + def build_option_parser(self, description, version, argparse_kwargs=None): + self.LOG.debug('build_option_parser') + parser = super(TestAPIClient, self).build_option_parser( + description, + version, + argparse_kwargs) + parser.add_argument('-u', + type=str, + help='Username for authentication') + parser.add_argument('-p', + type=str, + help='Password for authentication') + return parser def initialize_app(self, argv): self.LOG.debug('initialize_app') + self.client_manager = clientmanager.ClientManager(self.options) def prepare_to_run_command(self, cmd): self.LOG.debug('prepare_to_run_command %s', cmd.__class__.__name__) + if self.client_manager.auth_required: + self.client_manager.auth() def clean_up(self, cmd, result, err): self.LOG.debug('clean_up %s', cmd.__class__.__name__) @@ -31,8 +46,8 @@ class TestAPIClient(app.App): def main(argv=sys.argv[1:]): - myapp = TestAPIClient() - return myapp.run(argv) + client = TestAPIClient() + return client.run(argv) if __name__ == '__main__': diff --git a/testapi/testapi-client/testapiclient/tests/unit/fakes.py b/testapi/testapi-client/testapiclient/tests/unit/fakes.py new file mode 100644 index 0000000..8424745 --- /dev/null +++ b/testapi/testapi-client/testapiclient/tests/unit/fakes.py @@ -0,0 +1,72 @@ +import json +import sys + +import requests +import six +import httplib + + +class FakeResponse(requests.Response): + + def __init__(self, headers=None, status_code=httplib.OK, + data=None, encoding=None): + super(FakeResponse, self).__init__() + + headers = headers or {} + + self.status_code = status_code + + self.headers.update(headers) + if status_code != httplib.OK: + self.reason = data + + self._content = json.dumps(data) + if not isinstance(self._content, six.binary_type): + self._content = self._content.encode() + + +class FakeApp(object): + + def __init__(self, _stdout, _log): + self.stdout = _stdout + self.client_manager = None + self.stdin = sys.stdin + self.stdout = _stdout or sys.stdout + self.stderr = sys.stderr + self.log = _log + + +class FakeLog(object): + + def __init__(self): + self.messages = {} + + def debug(self, msg): + self.messages['debug'] = msg + + def info(self, msg): + self.messages['info'] = msg + + def warning(self, msg): + self.messages['warning'] = msg + + def error(self, msg): + self.messages['error'] = msg + + def critical(self, msg): + self.messages['critical'] = msg + + +class FakeStdout(object): + + def __init__(self): + self.content = [] + + def write(self, text): + self.content.append(text) + + def make_string(self): + result = '' + for line in self.content: + result = result + line + return result diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_pods.py b/testapi/testapi-client/testapiclient/tests/unit/test_pods.py index f531f9f..5d44d4c 100644 --- a/testapi/testapi-client/testapiclient/tests/unit/test_pods.py +++ b/testapi/testapi-client/testapiclient/tests/unit/test_pods.py @@ -1,22 +1,18 @@ -import StringIO -import httplib import json from mock import mock -import requests from six.moves.urllib import parse import testtools from testapiclient.cli import pods +from testapiclient.tests.unit import fakes from testapiclient.tests.unit import utils -from testapiclient.utils import http_client -from testapiclient.utils import user +from testapiclient.utils import clientmanager class PodTest(utils.TestCommand): def setUp(self): super(PodTest, self).setUp() - user.User.session = requests.session() self.base_url = parse.urljoin(self.api_url, 'pods') self.pod_json = { 'role': 'community-ci', @@ -31,47 +27,53 @@ class PodGetTest(PodTest): def setUp(self): super(PodGetTest, self).setUp() - self.get_mock = mock.patch('requests.get').start() - self.get_mock.return_value.status_code = httplib.OK + self.pods_rsp = {'pods': [self.pod_json]} def test_get(self): - pod_get = pods.PodGet(mock.Mock(), mock.Mock()) + self.get_mock.return_value = fakes.FakeResponse(data=self.pods_rsp) + pod_get = pods.PodGet(self.app, mock.Mock()) args = ['-name', 'dfs'] verifies = [('name', 'dfs')] parsed_args = self.check_parser(pod_get, args, verifies) pod_get.take_action(parsed_args) self.get_mock.assert_called_once_with( - self.base_url + '?name=dfs') + self.base_url + '?name=dfs', + headers=clientmanager.ClientManager.headers) def test_get_all(self): - pod_get = pods.PodGet(mock.Mock(), mock.Mock()) + self.get_mock.return_value = fakes.FakeResponse(data=self.pods_rsp) + pod_get = pods.PodGet(self.app, mock.Mock()) args = [] verifies = [] parsed_args = self.check_parser(pod_get, args, verifies) pod_get.take_action(parsed_args) self.get_mock.assert_called_once_with( - self.base_url) + self.base_url, + headers=clientmanager.ClientManager.headers) def test_get_one(self): - pod_get_one = pods.PodGetOne(mock.Mock(), mock.Mock()) + self.get_mock.return_value = fakes.FakeResponse(data=self.pod_json) + pod_get_one = pods.PodGetOne(self.app, mock.Mock()) args = ['def'] verifies = [('name', 'def')] parsed_args = self.check_parser(pod_get_one, args, verifies) pod_get_one.take_action(parsed_args) self.get_mock.assert_called_once_with( - self.base_url + '/def') + self.base_url + '/def', + headers=clientmanager.ClientManager.headers) class PodCreateTest(PodTest): def setUp(self): super(PodCreateTest, self).setUp() - self.post_mock = mock.patch( - 'testapiclient.utils.user.User.session.post').start() - self.post_mock.return_value.status_code = httplib.OK + self.succ_rsp = { + 'href': '{}/{}'.format(self.base_url, self.pod_json.get('name')) + } def test_create_success(self): - pod_create = pods.PodCreate(mock.Mock(), mock.Mock()) + self.post_mock.return_value = fakes.FakeResponse(data=self.succ_rsp) + pod_create = pods.PodCreate(self.app, mock.Mock()) args = [self.pod_string] verifies = [('pod', self.pod_json)] parsed_args = self.check_parser(pod_create, args, verifies) @@ -80,93 +82,36 @@ class PodCreateTest(PodTest): def test_create_failure(self): with testtools.ExpectedException(Exception, 'Create failed: Error'): - pod_create = pods.PodCreate(mock.Mock(), mock.Mock()) - self.post_mock.return_value.status_code = httplib.BAD_REQUEST - self.post_mock.return_value.reason = "Error" + self.post_mock.return_value = utils.FAKE_FAILURE + pod_create = pods.PodCreate(self.app, mock.Mock()) args = [self.pod_string] verifies = [('pod', self.pod_json)] parsed_args = self.check_parser(pod_create, args, verifies) pod_create.take_action(parsed_args) - def test_create_unauthorized(self): - self.mock_unautherized() - with mock.patch('sys.stdout', new=StringIO.StringIO()) as mock_stdout: - with mock.patch('requests.Session') as mock_sessions: - mock_sessions().post.return_value.text = "login" - pod_create = pods.PodCreate(mock.Mock(), mock.Mock()) - args = ['-u', 'user', '-p', 'password', self.pod_string] - verifies = [ - ('u', 'user'), - ('p', 'password'), - ('pod', self.pod_json)] - parsed_args = self.check_parser(pod_create, args, verifies) - pod_create.take_action(parsed_args) - self.assertEqual(mock_stdout.getvalue(), - "Authentication has failed.\n") - - def test_create_authorized(self): - pod_create = pods.PodCreate(mock.Mock(), mock.Mock()) - args = ['-u', 'user', '-p', 'password', self.pod_string] - verifies = [ - ('u', 'user'), - ('p', 'password'), - ('pod', self.pod_json) - ] - parsed_args = self.check_parser(pod_create, args, verifies) - pod_create.take_action(parsed_args) - self.post_mock.assert_called_once() - class PodDeleteTest(PodTest): def setUp(self): super(PodDeleteTest, self).setUp() - self.delete_mock = mock.patch( - 'testapiclient.utils.user.User.session.delete').start() - self.delete_mock.return_value.status_code = httplib.OK def test_delete_success(self): - pod_delete = pods.PodDelete(mock.Mock(), mock.Mock()) + self.delete_mock.return_value = fakes.FakeResponse() + pod_delete = pods.PodDelete(self.app, mock.Mock()) args = ['def'] verifies = [('name', 'def')] parsed_args = self.check_parser(pod_delete, args, verifies) pod_delete.take_action(parsed_args) self.delete_mock.assert_called_once_with( self.base_url + '/def', - data='null', - headers=http_client.HTTPClient.headers) + data=None, + headers=clientmanager.ClientManager.headers) def test_delete_failure(self): with testtools.ExpectedException(Exception, 'Delete failed: Error'): - pod_delete = pods.PodDelete(mock.Mock(), mock.Mock()) - self.delete_mock.return_value.status_code = httplib.FORBIDDEN - self.delete_mock.return_value.reason = "Error" + self.delete_mock.return_value = utils.FAKE_FAILURE + pod_delete = pods.PodDelete(self.app, mock.Mock()) args = ['def'] verifies = [('name', 'def')] parsed_args = self.check_parser(pod_delete, args, verifies) pod_delete.take_action(parsed_args) - - def test_delete_authorized(self): - pod_delete = pods.PodDelete(mock.Mock(), mock.Mock()) - args = ['-u', 'user', '-p', 'password', 'def'] - verifies = [('u', 'user'), ('p', 'password'), ('name', 'def')] - - parsed_args = self.check_parser(pod_delete, args, verifies) - pod_delete.take_action(parsed_args) - self.delete_mock.assert_called_once_with( - self.base_url + '/def', - data='null', - headers=http_client.HTTPClient.headers) - - def test_create_unauthorized(self): - self.mock_unautherized() - with mock.patch('sys.stdout', new=StringIO.StringIO()) as mock_stdout: - with mock.patch('requests.Session') as mock_sessions: - mock_sessions().post.return_value.text = "login" - pod_delete = pods.PodDelete(mock.Mock(), mock.Mock()) - args = ['-u', 'user', '-p', 'password', 'def'] - verifies = [('u', 'user'), ('p', 'password'), ('name', 'def')] - parsed_args = self.check_parser(pod_delete, args, verifies) - pod_delete.take_action(parsed_args) - self.assertEqual(mock_stdout.getvalue(), - "Authentication has failed.\n") diff --git a/testapi/testapi-client/testapiclient/tests/unit/test_projects.py b/testapi/testapi-client/testapiclient/tests/unit/test_projects.py new file mode 100644 index 0000000..86486ce --- /dev/null +++ b/testapi/testapi-client/testapiclient/tests/unit/test_projects.py @@ -0,0 +1,140 @@ +import json + +from mock import mock +from six.moves.urllib import parse +import testtools + +from testapiclient.cli import projects +from testapiclient.tests.unit import fakes +from testapiclient.tests.unit import utils +from testapiclient.utils import clientmanager + + +class ProjectTest(utils.TestCommand): + def setUp(self): + super(ProjectTest, self).setUp() + self.base_url = parse.urljoin(self.api_url, 'projects') + self.project_json = { + 'name': 'test_project', + 'description': '' + } + self.project_string = json.dumps(self.project_json) + + +class ProjectGetTest(ProjectTest): + + def setUp(self): + super(ProjectGetTest, self).setUp() + self.projects_rsp = {'projects': [self.project_json]} + + def test_get(self): + self.get_mock.return_value = fakes.FakeResponse(data=self.projects_rsp) + project_get = projects.ProjectGet(self.app, mock.Mock()) + args = ['-name', 'dfs'] + verifies = [('name', 'dfs')] + parsed_args = self.check_parser(project_get, args, verifies) + project_get.take_action(parsed_args) + self.get_mock.assert_called_once_with( + self.base_url + '?name=dfs', + headers=clientmanager.ClientManager.headers) + + def test_get_all(self): + self.get_mock.return_value = fakes.FakeResponse(data=self.projects_rsp) + project_get = projects.ProjectGet(self.app, mock.Mock()) + args = [] + verifies = [] + parsed_args = self.check_parser(project_get, args, verifies) + project_get.take_action(parsed_args) + self.get_mock.assert_called_once_with( + self.base_url, + headers=clientmanager.ClientManager.headers) + + def test_get_one(self): + self.get_mock.return_value = fakes.FakeResponse(data=self.project_json) + project_get_one = projects.ProjectGetOne(self.app, mock.Mock()) + args = ['def'] + verifies = [('name', 'def')] + parsed_args = self.check_parser(project_get_one, args, verifies) + project_get_one.take_action(parsed_args) + self.get_mock.assert_called_once_with( + self.base_url + '/def', + headers=clientmanager.ClientManager.headers) + + +class ProjectCreateTest(ProjectTest): + + def setUp(self): + super(ProjectCreateTest, self).setUp() + + def test_create_success(self): + succ_rsp = { + 'href': '{}/{}'.format(self.base_url, + self.project_json.get('name')) + } + self.post_mock.return_value = fakes.FakeResponse(data=succ_rsp) + project_create = projects.ProjectCreate(self.app, mock.Mock()) + args = [self.project_string] + verifies = [('project', self.project_json)] + parsed_args = self.check_parser(project_create, args, verifies) + project_create.take_action(parsed_args) + self.post_mock.assert_called_once() + + def test_create_failure(self): + with testtools.ExpectedException(Exception, 'Create failed: Error'): + self.post_mock.return_value = utils.FAKE_FAILURE + project_create = projects.ProjectCreate(self.app, mock.Mock()) + args = [self.project_string] + verifies = [('project', self.project_json)] + parsed_args = self.check_parser(project_create, args, verifies) + project_create.take_action(parsed_args) + + +class ProjectDeleteTest(ProjectTest): + + def setUp(self): + super(ProjectDeleteTest, self).setUp() + + def test_delete_success(self): + self.delete_mock.return_value = fakes.FakeResponse() + project_delete = projects.ProjectDelete(self.app, mock.Mock()) + args = ['def'] + verifies = [('name', 'def')] + parsed_args = self.check_parser(project_delete, args, verifies) + project_delete.take_action(parsed_args) + self.delete_mock.assert_called_once_with( + self.base_url + '/def', + data=None, + headers=clientmanager.ClientManager.headers) + + def test_delete_failure(self): + with testtools.ExpectedException(Exception, 'Delete failed: Error'): + self.delete_mock.return_value = utils.FAKE_FAILURE + project_delete = projects.ProjectDelete(self.app, mock.Mock()) + args = ['def'] + verifies = [('name', 'def')] + parsed_args = self.check_parser(project_delete, args, verifies) + project_delete.take_action(parsed_args) + + +class ProjectPutTest(ProjectTest): + + def setUp(self): + super(ProjectPutTest, self).setUp() + + def test_put_success(self): + self.put_mock.return_value = fakes.FakeResponse(data=self.project_json) + project_put = projects.ProjectPut(self.app, mock.Mock()) + args = ['def', self.project_string] + verifies = [('name', 'def'), ('project', self.project_json)] + parsed_args = self.check_parser(project_put, args, verifies) + project_put.take_action(parsed_args) + self.put_mock.assert_called_once() + + def test_put_failure(self): + with testtools.ExpectedException(Exception, 'Update failed: Error'): + self.put_mock.return_value = utils.FAKE_FAILURE + project_put = projects.ProjectPut(self.app, mock.Mock()) + args = ['def', self.project_string] + verifies = [('name', 'def'), ('project', self.project_json)] + parsed_args = self.check_parser(project_put, args, verifies) + project_put.take_action(parsed_args) diff --git a/testapi/testapi-client/testapiclient/tests/unit/utils.py b/testapi/testapi-client/testapiclient/tests/unit/utils.py index 596b7e4..20f9a47 100644 --- a/testapi/testapi-client/testapiclient/tests/unit/utils.py +++ b/testapi/testapi-client/testapiclient/tests/unit/utils.py @@ -1,7 +1,12 @@ -import testtools +import httplib + from mock import mock +import testtools -from testapiclient.utils.user import User +from testapiclient.tests.unit import fakes +from testapiclient.utils import clientmanager + +FAKE_FAILURE = fakes.FakeResponse(status_code=httplib.FORBIDDEN, data='Error') class ParserException(Exception): @@ -24,6 +29,14 @@ class TestCommand(testtools.TestCase): } self.config_mock = mock.patch.dict( 'os.environ', env_variables).start() + self.fake_stdout = fakes.FakeStdout() + self.fake_log = fakes.FakeLog() + self.app = fakes.FakeApp(self.fake_stdout, self.fake_log) + self.app.client_manager = clientmanager.ClientManager() + self.get_mock = mock.patch('requests.Session.get').start() + self.post_mock = mock.patch('requests.Session.post').start() + self.delete_mock = mock.patch('requests.Session.delete').start() + self.put_mock = mock.patch('requests.Session.put').start() def check_parser(self, cmd, args, verify_args): cmd_parser = cmd.get_parser('check_parser') @@ -37,6 +50,3 @@ class TestCommand(testtools.TestCase): self.assertIn(attr, parsed_args) self.assertEqual(value, getattr(parsed_args, attr)) return parsed_args - - def mock_unautherized(self): - User.session = None diff --git a/testapi/testapi-client/testapiclient/utils/http_client.py b/testapi/testapi-client/testapiclient/utils/clientmanager.py index 359dd14..4401231 100644 --- a/testapi/testapi-client/testapiclient/utils/http_client.py +++ b/testapi/testapi-client/testapiclient/utils/clientmanager.py @@ -1,32 +1,52 @@ import httplib import json +import os +import urllib +import logging import requests -from testapiclient.utils import user +LOG = logging.getLogger(__name__) -class HTTPClient(object): - - __instance = None +class ClientManager(object): 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 __init__(self, cli_options=None): + self.cli_options = cli_options + self.session = requests.Session() + self._auth_completed = False + + @property + def auth_required(self): + return self._auth() + + def _auth(self): + return { + 'name': self.cli_options.u, + 'pass': self.cli_options.p + } if self.cli_options.u else None + + def auth(self): + + if self._auth_completed: + return + + hostname = '{}{}{}'.format(os.environ.get('testapi_cas_auth_url'), + urllib.quote(os.environ.get('testapi_url')), + os.environ.get('testapi_cas_signin_return')) + data = self._auth() + data.update({'form_id': 'user_login'}) + LOG.debug('authenticating.....') + response = self.session.post(hostname, data) + if "login" in response.text: + raise Exception('Authenticate failed') + self._auth_completed = True def get(self, url): - return self._parse_response('Get', requests.get(url)) + return self._parse_response('Get', + self._request('get', url, + headers=self.headers)) def post(self, url, data): return self._parse_response('Create', @@ -48,7 +68,7 @@ class HTTPClient(object): headers=self.headers)) def _request(self, method, *args, **kwargs): - return getattr(user.User.session, method)(*args, **kwargs) + return getattr(self.session, method)(*args, **kwargs) def _raise_failure(self, op, response): raise Exception('{} failed: {}'.format(op, response.reason)) @@ -58,23 +78,3 @@ class HTTPClient(object): return response.json() if op != 'Delete' else None else: self._raise_failure(op, response) - - -def _request(method, *args, **kwargs): - return getattr(HTTPClient.get_Instance(), method)(*args, **kwargs) - - -def get(url): - return _request('get', url) - - -def post(url, data): - return _request('post', url, data) - - -def put(url, data): - return _request('put', url, data) - - -def delete(url, data=None): - return _request('delete', url, data) diff --git a/testapi/testapi-client/testapiclient/utils/command.py b/testapi/testapi-client/testapiclient/utils/command.py index 9614acf..b9d1ce8 100644 --- a/testapi/testapi-client/testapiclient/utils/command.py +++ b/testapi/testapi-client/testapiclient/utils/command.py @@ -20,17 +20,6 @@ class CommandMeta(abc.ABCMeta): @six.add_metaclass(CommandMeta) class Command(command.Command): - - def get_parser(self, prog_name): - parser = super(Command, 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') - return parser - def run(self, parsed_args): self.log.debug('run(%s)', parsed_args) return super(Command, self).run(parsed_args) diff --git a/testapi/testapi-client/testapiclient/utils/identity.py b/testapi/testapi-client/testapiclient/utils/identity.py deleted file mode 100644 index a00dd87..0000000 --- a/testapi/testapi-client/testapiclient/utils/identity.py +++ /dev/null @@ -1,38 +0,0 @@ -import functools -import os -import urllib - -import requests - -from testapiclient.utils import user - - -def _authenticate(username, password): - session = requests.Session() - hostname = '{}{}{}'.format(os.environ.get('testapi_cas_auth_url'), - urllib.quote(os.environ.get('testapi_url')), - os.environ.get('testapi_cas_signin_return')) - data = { - 'name': username, - 'pass': password, - 'form_id': 'user_login' - } - response = session.post(hostname, data) - if "login" not in response.text: - user.User.session = session - return response - - -def authenticate(xstep): - @functools.wraps(xstep) - def wrapper(self, parsed_args): - if(user.User.session is None): - username = parsed_args.u - password = parsed_args.p - if(username and password): - response = _authenticate(username, password) - if "login" in response.text: - print "Authentication has failed." - return - return xstep(self, parsed_args) - return wrapper diff --git a/testapi/testapi-client/testapiclient/utils/url_parse.py b/testapi/testapi-client/testapiclient/utils/urlparse.py index 9f99a46..9f99a46 100644 --- a/testapi/testapi-client/testapiclient/utils/url_parse.py +++ b/testapi/testapi-client/testapiclient/utils/urlparse.py diff --git a/testapi/testapi-client/testapiclient/utils/user.py b/testapi/testapi-client/testapiclient/utils/user.py deleted file mode 100644 index 7e72163..0000000 --- a/testapi/testapi-client/testapiclient/utils/user.py +++ /dev/null @@ -1,2 +0,0 @@ -class User(): - session = None |