summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--testapi/opnfv_testapi/handlers/base_handlers.py2
-rw-r--r--testapi/opnfv_testapi/handlers/result_handlers.py24
-rw-r--r--testapi/opnfv_testapi/models/result_models.py67
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/projectsControllerSpec.js20
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/resultsControllerSpec.js3
-rw-r--r--testapi/opnfv_testapi/tests/UI/e2e/scenariosControllerSpec.js347
-rw-r--r--testapi/opnfv_testapi/tests/unit/handlers/test_result.py41
-rw-r--r--testapi/opnfv_testapi/tests/unit/templates/test_result.json4
-rw-r--r--testapi/opnfv_testapi/ui/components/results/result/result.html22
-rw-r--r--testapi/opnfv_testapi/ui/components/results/result/resultController.js8
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenarios.html9
-rw-r--r--testapi/opnfv_testapi/ui/components/scenarios/scenariosController.js13
-rw-r--r--testapi/setup.cfg2
-rw-r--r--testapi/testapi-client/testapiclient/cli/auth.py14
-rw-r--r--testapi/testapi-client/testapiclient/cli/pods.py21
-rw-r--r--testapi/testapi-client/testapiclient/cli/projects.py37
-rw-r--r--testapi/testapi-client/testapiclient/main.py25
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/fakes.py72
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_pods.py111
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/test_projects.py140
-rw-r--r--testapi/testapi-client/testapiclient/tests/unit/utils.py20
-rw-r--r--testapi/testapi-client/testapiclient/utils/clientmanager.py (renamed from testapi/testapi-client/testapiclient/utils/http_client.py)78
-rw-r--r--testapi/testapi-client/testapiclient/utils/command.py11
-rw-r--r--testapi/testapi-client/testapiclient/utils/identity.py38
-rw-r--r--testapi/testapi-client/testapiclient/utils/urlparse.py (renamed from testapi/testapi-client/testapiclient/utils/url_parse.py)0
-rw-r--r--testapi/testapi-client/testapiclient/utils/user.py2
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&nbsp;Indicator&nbsp;:</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&nbsp;:</td>
- <td width="90%" class="podsTableLeftTd">{{ctrl.data.trust_indicator.current}}</td>
- </tr>
- <tr style="padding:9px" >
- <td class="podsTableTd">Histories&nbsp;:</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&nbsp;:</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&nbsp;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