mirror of
https://github.com/goharbor/harbor.git
synced 2025-02-16 20:01:35 +01:00
add api test case for robot user, and modify swagger.yaml for wrong type of return value. (#6900)
Signed-off-by: danfengliu <danfengl@vmware.com>
This commit is contained in:
parent
9b9fa4fc83
commit
eaedd89c25
@ -3266,7 +3266,9 @@ paths:
|
||||
description: The ID of robot account.
|
||||
responses:
|
||||
'200':
|
||||
description: '#/definitions/RobotAccount'
|
||||
description: Robot account information.
|
||||
schema:
|
||||
$ref: '#/definitions/RobotAccount'
|
||||
'401':
|
||||
description: User need to log in first.
|
||||
'403':
|
||||
|
@ -24,15 +24,27 @@ class DockerAPI(object):
|
||||
_tag = tag
|
||||
else:
|
||||
_tag = "latest"
|
||||
if expected_error_message is "":
|
||||
expected_error_message = None
|
||||
caught_err = False
|
||||
ret = ""
|
||||
try:
|
||||
base._get_string_from_unicode(self.DCLIENT.pull(r'{}:{}'.format(image, _tag)))
|
||||
ret = base._get_string_from_unicode(self.DCLIENT.pull(r'{}:{}'.format(image, _tag)))
|
||||
except Exception, err:
|
||||
caught_err = True
|
||||
if expected_error_message is not None:
|
||||
print "docker image pull error:", str(err)
|
||||
if str(err).lower().find(expected_error_message.lower()) < 0:
|
||||
raise Exception(r"Pull image: Return message {} is not as expected {}".format(return_message, expected_error_message))
|
||||
raise Exception(r"Pull image: Return message {} is not as expected {}".format(str(err), expected_error_message))
|
||||
else:
|
||||
raise Exception(r" Docker pull image {} failed, error is [{}]".format (image, e.message))
|
||||
raise Exception(r" Docker pull image {} failed, error is [{}]".format (image, err.message))
|
||||
if caught_err == False:
|
||||
if expected_error_message is not None:
|
||||
if str(ret).lower().find(expected_error_message.lower()) < 0:
|
||||
raise Exception(r" Failed to catch error [{}] when pull image {}".format (expected_error_message, image))
|
||||
else:
|
||||
if str(ret).lower().find("error".lower()) >= 0:
|
||||
raise Exception(r" It's was not suppose to catch error when pull image {}, return message is [{}]".format (image, ret))
|
||||
|
||||
def docker_image_tag(self, image, harbor_registry, tag = None):
|
||||
_tag = base._random_name("tag")
|
||||
@ -44,8 +56,25 @@ class DockerAPI(object):
|
||||
except docker.errors.APIError, e:
|
||||
raise Exception(r" Docker tag image {} failed, error is [{}]".format (image, e.message))
|
||||
|
||||
def docker_image_push(self, harbor_registry, tag):
|
||||
def docker_image_push(self, harbor_registry, tag, expected_error_message = None):
|
||||
caught_err = False
|
||||
ret = ""
|
||||
if expected_error_message is "":
|
||||
expected_error_message = None
|
||||
try:
|
||||
base._get_string_from_unicode(self.DCLIENT.push(harbor_registry, tag, stream=True))
|
||||
except docker.errors.APIError, e:
|
||||
raise Exception(r" Docker tag image {} failed, error is [{}]".format (image, e.message))
|
||||
ret = base._get_string_from_unicode(self.DCLIENT.push(harbor_registry, tag, stream=True))
|
||||
except Exception, err:
|
||||
caught_err = True
|
||||
if expected_error_message is not None:
|
||||
print "docker image push error:", str(err)
|
||||
if str(err).lower().find(expected_error_message.lower()) < 0:
|
||||
raise Exception(r"Push image: Return message {} is not as expected {}".format(str(err), expected_error_message))
|
||||
else:
|
||||
raise Exception(r" Docker push image {} failed, error is [{}]".format (harbor_registry, err.message))
|
||||
if caught_err == False:
|
||||
if expected_error_message is not None:
|
||||
if str(ret).lower().find(expected_error_message.lower()) < 0:
|
||||
raise Exception(r" Failed to catch error [{}] when push image {}".format (expected_error_message, harbor_registry))
|
||||
else:
|
||||
if str(ret).lower().find("errorDetail".lower()) >= 0:
|
||||
raise Exception(r" It's was not suppose to catch error when push image {}, return message is [{}]".format (harbor_registry, ret))
|
@ -34,7 +34,6 @@ class Project(base.Base):
|
||||
base._assert_status_code(201, status_code)
|
||||
return base._get_id_from_header(header), name
|
||||
|
||||
|
||||
def get_projects(self, params, **kwargs):
|
||||
client = self._get_client(**kwargs)
|
||||
data = []
|
||||
@ -150,12 +149,14 @@ class Project(base.Base):
|
||||
data = []
|
||||
data, status_code, _ = client.projects_project_id_members_mid_put_with_http_info(project_id, member_id, role = role)
|
||||
base._assert_status_code(expect_status_code, status_code)
|
||||
base._assert_status_code(200, status_code)
|
||||
return data
|
||||
|
||||
def delete_project_member(self, project_id, member_id, expect_status_code = 200, **kwargs):
|
||||
client = self._get_client(**kwargs)
|
||||
_, status_code, _ = client.projects_project_id_members_mid_delete_with_http_info(project_id, member_id)
|
||||
base._assert_status_code(expect_status_code, status_code)
|
||||
base._assert_status_code(200, status_code)
|
||||
|
||||
def add_project_members(self, project_id, user_id, member_role_id = None, expect_status_code = 201, **kwargs):
|
||||
if member_role_id is None:
|
||||
@ -165,6 +166,53 @@ class Project(base.Base):
|
||||
client = self._get_client(**kwargs)
|
||||
data = []
|
||||
data, status_code, header = client.projects_project_id_members_post_with_http_info(project_id, project_member = projectMember)
|
||||
base._assert_status_code(201, status_code)
|
||||
base._assert_status_code(expect_status_code, status_code)
|
||||
return base._get_id_from_header(header)
|
||||
|
||||
def add_project_robot_account(self, project_id, project_name, robot_name = None, robot_desc = None, has_pull_right = True, has_push_right = True, expect_status_code = 201, **kwargs):
|
||||
if robot_name is None:
|
||||
robot_name = base._random_name("robot")
|
||||
if robot_desc is None:
|
||||
robot_desc = base._random_name("robot_desc")
|
||||
if has_pull_right is False and has_push_right is False:
|
||||
has_pull_right = True
|
||||
access_list = []
|
||||
resource_by_project_id = "/project/"+str(project_id)+"/repository"
|
||||
resource_by_project_name = "/project/"+project_name+"/repository"
|
||||
action_pull = "pull"
|
||||
action_push = "push"
|
||||
if has_pull_right is True:
|
||||
robotAccountAccess = swagger_client.RobotAccountAccess(resource = resource_by_project_id, action = action_pull)
|
||||
access_list.append(robotAccountAccess)
|
||||
robotAccountAccess = swagger_client.RobotAccountAccess(resource = resource_by_project_name, action = action_pull)
|
||||
access_list.append(robotAccountAccess)
|
||||
if has_push_right is True:
|
||||
robotAccountAccess = swagger_client.RobotAccountAccess(resource = resource_by_project_id, action = action_push)
|
||||
access_list.append(robotAccountAccess)
|
||||
robotAccountAccess = swagger_client.RobotAccountAccess(resource = resource_by_project_name, action = action_push)
|
||||
access_list.append(robotAccountAccess)
|
||||
robotAccountCreate = swagger_client.RobotAccountCreate(robot_name, robot_desc, access_list)
|
||||
client = self._get_client(**kwargs)
|
||||
data = []
|
||||
data, status_code, header = client.projects_project_id_robots_post_with_http_info(project_id, robotAccountCreate)
|
||||
base._assert_status_code(expect_status_code, status_code)
|
||||
base._assert_status_code(201, status_code)
|
||||
return base._get_id_from_header(header), data
|
||||
|
||||
def get_project_robot_account_by_id(self, project_id, robot_id, **kwargs):
|
||||
client = self._get_client(**kwargs)
|
||||
data, status_code, _ = client.projects_project_id_robots_robot_id_get_with_http_info(project_id, robot_id)
|
||||
return data
|
||||
|
||||
def disable_project_robot_account(self, project_id, robot_id, disable, expect_status_code = 200, **kwargs):
|
||||
client = self._get_client(**kwargs)
|
||||
robotAccountUpdate = swagger_client.RobotAccountUpdate(disable)
|
||||
_, status_code, _ = client.projects_project_id_robots_robot_id_put_with_http_info(project_id, robot_id, robotAccountUpdate)
|
||||
base._assert_status_code(expect_status_code, status_code)
|
||||
base._assert_status_code(200, status_code)
|
||||
|
||||
def delete_project_robot_account(self, project_id, robot_id, expect_status_code = 200, **kwargs):
|
||||
client = self._get_client(**kwargs)
|
||||
_, status_code, _ = client.projects_project_id_robots_robot_id_delete_with_http_info(project_id, robot_id)
|
||||
base._assert_status_code(expect_status_code, status_code)
|
||||
base._assert_status_code(200, status_code)
|
@ -11,7 +11,7 @@ def pull_harbor_image(registry, username, password, image, tag, expected_error_m
|
||||
time.sleep(2)
|
||||
_docker_api.docker_image_pull(r'{}/{}'.format(registry, image), tag = tag, expected_error_message = expected_error_message)
|
||||
|
||||
def push_image_to_project(project_name, registry, username, password, image, tag):
|
||||
def push_image_to_project(project_name, registry, username, password, image, tag, expected_error_message = None):
|
||||
_docker_api = DockerAPI()
|
||||
_docker_api.docker_login(registry, username, password)
|
||||
time.sleep(2)
|
||||
@ -22,7 +22,7 @@ def push_image_to_project(project_name, registry, username, password, image, tag
|
||||
new_harbor_registry, new_tag = _docker_api.docker_image_tag(r'{}:{}'.format(image, tag), r'{}/{}/{}'.format(registry, project_name, image))
|
||||
time.sleep(2)
|
||||
|
||||
_docker_api.docker_image_push(new_harbor_registry, new_tag)
|
||||
_docker_api.docker_image_push(new_harbor_registry, new_tag, expected_error_message = expected_error_message)
|
||||
|
||||
return r'{}/{}'.format(project_name, image), new_tag
|
||||
|
||||
|
135
tests/apitests/python/test_robot_account.py
Normal file
135
tests/apitests/python/test_robot_account.py
Normal file
@ -0,0 +1,135 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import unittest
|
||||
|
||||
from testutils import ADMIN_CLIENT
|
||||
from testutils import TEARDOWN
|
||||
from library.user import User
|
||||
from library.project import Project
|
||||
from library.repository import Repository
|
||||
from library.repository import pull_harbor_image
|
||||
from library.repository import push_image_to_project
|
||||
from testutils import harbor_server
|
||||
from library.base import _assert_status_code
|
||||
|
||||
class TestProjects(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUp(self):
|
||||
project = Project()
|
||||
self.project= project
|
||||
|
||||
user = User()
|
||||
self.user= user
|
||||
|
||||
repo = Repository()
|
||||
self.repo= repo
|
||||
|
||||
@classmethod
|
||||
def tearDown(self):
|
||||
print "Case completed"
|
||||
|
||||
@unittest.skipIf(TEARDOWN == False, "Test data won't be erased.")
|
||||
def test_ClearData(self):
|
||||
#1. Delete repository(RA) by user(UA);
|
||||
self.repo.delete_repoitory(TestProjects.repo_name_in_project_a, **TestProjects.USER_RA_CLIENT)
|
||||
self.repo.delete_repoitory(TestProjects.repo_name_in_project_b, **TestProjects.USER_RA_CLIENT)
|
||||
self.repo.delete_repoitory(TestProjects.repo_name_in_project_c, **TestProjects.USER_RA_CLIENT)
|
||||
self.repo.delete_repoitory(TestProjects.repo_name_pa, **TestProjects.USER_RA_CLIENT)
|
||||
|
||||
#2. Delete project(PA);
|
||||
self.project.delete_project(TestProjects.project_ra_id_a, **TestProjects.USER_RA_CLIENT)
|
||||
self.project.delete_project(TestProjects.project_ra_id_b, **TestProjects.USER_RA_CLIENT)
|
||||
self.project.delete_project(TestProjects.project_ra_id_c, **TestProjects.USER_RA_CLIENT)
|
||||
|
||||
#3. Delete user(UA);
|
||||
self.user.delete_user(TestProjects.user_ra_id, **ADMIN_CLIENT)
|
||||
|
||||
def testRobotAccount(self):
|
||||
"""
|
||||
Test case:
|
||||
Robot Account
|
||||
Test step and expected result:
|
||||
1. Create user(UA);
|
||||
2. Create private project(PA), private project(PB) and public project(PC) by user(UA);
|
||||
3. Push image(ImagePA) to project(PA), image(ImagePB) to project(PB) and image(ImagePC) to project(PC) by user(UA);
|
||||
4. Create a new robot account(RA) with pull and push privilige in project(PA) by user(UA);
|
||||
5. Check robot account info, it should has both pull and push priviliges;
|
||||
6. Pull image(ImagePA) from project(PA) by robot account(RA), it must be successful;
|
||||
7. Push image(ImageRA) to project(PA) by robot account(RA), it must be successful;
|
||||
8. Push image(ImageRA) to project(PB) by robot account(RA), it must be not successful;
|
||||
9. Pull image(ImagePB) from project(PB) by robot account(RA), it must be not successful;
|
||||
10. Pull image from project(PC), it must be successful;
|
||||
11. Push image(ImageRA) to project(PC) by robot account(RA), it must be not successful;
|
||||
12. Update action property of robot account(RA);
|
||||
13. Pull image(ImagePA) from project(PA) by robot account(RA), it must be not successful;
|
||||
14. Push image(ImageRA) to project(PA) by robot account(RA), it must be not successful;
|
||||
15. Push image(ImageRA) to project(PA) by robot account(RA), it must be not successful;
|
||||
Tear down:
|
||||
1. Delete project(PA) (PB) (PC);
|
||||
2. Delete user(UA).
|
||||
"""
|
||||
url = ADMIN_CLIENT["endpoint"]
|
||||
admin_name = ADMIN_CLIENT["username"]
|
||||
admin_password = ADMIN_CLIENT["password"]
|
||||
user_ra_password = "Aa123456"
|
||||
image_project_a = "tomcat"
|
||||
image_project_b = "hello-world"
|
||||
image_project_c = "mysql"
|
||||
image_robot_account = "mariadb"
|
||||
tag = "latest"
|
||||
|
||||
print "#1. Create user(UA);"
|
||||
TestProjects.user_ra_id, user_ra_name = self.user.create_user(user_password = user_ra_password, **ADMIN_CLIENT)
|
||||
TestProjects.USER_RA_CLIENT=dict(endpoint = url, username = user_ra_name, password = user_ra_password)
|
||||
|
||||
print "#2. Create private project(PA), private project(PB) and public project(PC) by user(UA);"
|
||||
TestProjects.project_ra_id_a, project_ra_name_a = self.project.create_project(metadata = {"public": "false"}, **TestProjects.USER_RA_CLIENT)
|
||||
TestProjects.project_ra_id_b, project_ra_name_b = self.project.create_project(metadata = {"public": "false"}, **TestProjects.USER_RA_CLIENT)
|
||||
TestProjects.project_ra_id_c, project_ra_name_c = self.project.create_project(metadata = {"public": "true"}, **TestProjects.USER_RA_CLIENT)
|
||||
|
||||
print "#3. Push image(ImagePA) to project(PA), image(ImagePB) to project(PB) and image(ImagePC) to project(PC) by user(UA);"
|
||||
TestProjects.repo_name_in_project_a, tag_a = push_image_to_project(project_ra_name_a, harbor_server, user_ra_name, user_ra_password, image_project_a, tag)
|
||||
TestProjects.repo_name_in_project_b, tag_b = push_image_to_project(project_ra_name_b, harbor_server, user_ra_name, user_ra_password, image_project_b, tag)
|
||||
TestProjects.repo_name_in_project_c, tag_c = push_image_to_project(project_ra_name_c, harbor_server, user_ra_name, user_ra_password, image_project_c, tag)
|
||||
|
||||
print "#4. Create a new robot account(RA) with pull and push privilige in project(PA) by user(UA);"
|
||||
robot_id, robot_account = self.project.add_project_robot_account(TestProjects.project_ra_id_a, project_ra_name_a, **TestProjects.USER_RA_CLIENT)
|
||||
print robot_account.name
|
||||
print robot_account.token
|
||||
|
||||
print "#5. Check robot account info, it should has both pull and push priviliges;"
|
||||
data = self.project.get_project_robot_account_by_id(TestProjects.project_ra_id_a, robot_id, **TestProjects.USER_RA_CLIENT)
|
||||
_assert_status_code(robot_account.name, data.name)
|
||||
|
||||
print "#6. Pull image(ImagePA) from project(PA) by robot account(RA), it must be successful;"
|
||||
pull_harbor_image(harbor_server, robot_account.name, robot_account.token, TestProjects.repo_name_in_project_a, tag_a)
|
||||
|
||||
print "#7. Push image(ImageRA) to project(PA) by robot account(RA), it must be successful;"
|
||||
TestProjects.repo_name_pa, _ = push_image_to_project(project_ra_name_a, harbor_server, robot_account.name, robot_account.token, image_robot_account, tag)
|
||||
|
||||
print "#8. Push image(ImageRA) to project(PB) by robot account(RA), it must be not successful;"
|
||||
push_image_to_project(project_ra_name_b, harbor_server, robot_account.name, robot_account.token, image_robot_account, tag, expected_error_message = "denied: requested access to the resource is denied")
|
||||
|
||||
print "#9. Pull image(ImagePB) from project(PB) by robot account(RA), it must be not successful;"
|
||||
pull_harbor_image(harbor_server, robot_account.name, robot_account.token, TestProjects.repo_name_in_project_b, tag_b, expected_error_message = r"pull access denied for " + harbor_server + "/" + TestProjects.repo_name_in_project_b)
|
||||
|
||||
print "#10. Pull image from project(PC), it must be successful;"
|
||||
pull_harbor_image(harbor_server, robot_account.name, robot_account.token, TestProjects.repo_name_in_project_c, tag_c)
|
||||
|
||||
print "#11. Push image(ImageRA) to project(PC) by robot account(RA), it must be not successful;"
|
||||
push_image_to_project(project_ra_name_c, harbor_server, robot_account.name, robot_account.token, image_robot_account, tag, expected_error_message = "denied: requested access to the resource is denied")
|
||||
|
||||
print "#12. Update action property of robot account(RA);"
|
||||
#self.project.disable_project_robot_account(TestProjects.project_ra_id_a, robot_id, True, **TestProjects.USER_RA_CLIENT)
|
||||
|
||||
print "#13. Pull image(ImagePA) from project(PA) by robot account(RA), it must be not successful;"
|
||||
#pull_harbor_image(harbor_server, robot_account.name, robot_account.token, TestProjects.repo_name_in_project_a, tag_a, expected_error_message = "")
|
||||
|
||||
print "#14. Push image(ImageRA) to project(PA) by robot account(RA), it must be not successful;"
|
||||
#push_image_to_project(project_ra_name_a, harbor_server, robot_account.name, robot_account.token, image_robot_account, tag, expected_error_message = "")
|
||||
|
||||
print "#15. Push image(ImageRA) to project(PA) by robot account(RA), it must be not successful;"
|
||||
self.project.delete_project_robot_account(TestProjects.project_ra_id_a, robot_id, **TestProjects.USER_RA_CLIENT)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user