Commit edcb2fbf authored by stonezdj's avatar stonezdj
Browse files

Add Harbor API Test based on python API

Correct swagger.yaml format
Add make task swagger_client to gen and install python client.
Add LDAP related Test
parent 3c0bd20d
......@@ -455,6 +455,16 @@ down:
@$(DOCKERCOMPOSECMD) $(DOCKERCOMPOSE_LIST) down -v
@echo "Done."
swagger_client:
@echo "Generate swagger client"
wget -q http://central.maven.org/maven2/io/swagger/swagger-codegen-cli/2.3.1/swagger-codegen-cli-2.3.1.jar -O swagger-codegen-cli.jar
rm -rf harborclient
mkdir harborclient
java -jar swagger-codegen-cli.jar generate -i docs/swagger.yaml -l python -o harborclient
python ./harborclient/setup.py -q install --user --prefix= || true
pip install docker -q
pip freeze
cleanbinary:
@echo "cleaning binary..."
@if [ -f $(ADMINSERVERBINARYPATH)/$(ADMINSERVERBINARYNAME) ] ; then rm $(ADMINSERVERBINARYPATH)/$(ADMINSERVERBINARYNAME) ; fi
......
......@@ -2,16 +2,22 @@ swagger: '2.0'
info:
title: Harbor API
description: These APIs provide services for manipulating Harbor project.
version: 1.4.0
version: 1.6.0
host: localhost
schemes:
- http
- https
basePath: /api
produces:
- application/json
- text/plain
consumes:
- application/json
securityDefinitions:
basicAuth:
type: basic
security:
- basicAuth: []
paths:
/search:
get:
......@@ -2244,9 +2250,7 @@ paths:
'200':
description: Get general info successfully.
schema:
type: object
items:
$ref: '#/definitions/GeneralInfo'
$ref: '#/definitions/GeneralInfo'
'500':
description: Unexpected internal error.
/systeminfo/volumes:
......@@ -2261,9 +2265,7 @@ paths:
'200':
description: Get system volumes successfully.
schema:
type: object
items:
$ref: '#/definitions/SystemInfo'
$ref: '#/definitions/SystemInfo'
'401':
description: User need to log in first.
'403':
......@@ -2554,9 +2556,9 @@ paths:
'200':
description: Get system configurations successfully. The response body is a map.
schema:
$ref: '#/definitions/Configurations'
$ref: '#/definitions/ConfigurationsResponse'
'401':
description: User need to log in first.
description: User need to log in first.ß
'403':
description: User does not have permission of admin role.
'500':
......@@ -2662,7 +2664,7 @@ definitions:
type: string
description: The name of the project that the repository belongs to
project_public:
type: integer
type: boolean
description: >-
The flag to indicate the publicity of the project that the repository
belongs to (1 is public, 0 is not)
......@@ -2705,9 +2707,8 @@ definitions:
type: string
description: The update time of the project.
deleted:
type: integer
format: int32
description: 'A deletion mark of the project (1 means it''s deleted, 0 is not)'
type: boolean
description: A deletion mark of the project.
owner_name:
type: string
description: The owner name of the project.
......@@ -2774,8 +2775,7 @@ definitions:
comment:
type: string
deleted:
type: integer
format: int32
type: boolean
role_name:
type: string
role_id:
......@@ -3436,6 +3436,7 @@ definitions:
description: >-
The version which the vulnerability is fixed, this is an optional
property.
Configurations:
type: object
properties:
......@@ -3547,6 +3548,141 @@ definitions:
description: >-
The parameters of the policy, the values are dependant on the type
of the policy.
ConfigurationsResponse:
type: object
properties:
auth_mode:
schema:
$ref: '#/definitions/StringConfigItem'
description: 'The auth mode of current system, such as "db_auth", "ldap_auth"'
email_from:
schema:
$ref: '#/definitions/StringConfigItem'
description: The sender name for Email notification.
email_host:
schema:
$ref: '#/definitions/StringConfigItem'
description: The hostname of SMTP server that sends Email notification.
email_port:
schema:
$ref: '#/definitions/IntegerConfigItem'
description: The port of SMTP server.
email_identity:
schema:
$ref: '#/definitions/StringConfigItem'
description: By default it's empty so the email_username is picked.
email_username:
schema:
$ref: '#/definitions/StringConfigItem'
description: The username for authenticate against SMTP server.
email_ssl:
schema:
$ref: '#/definitions/BoolConfigItem'
description: >-
When it's set to true the system will access Email server via TLS by
default. If it's set to false, it still will handle "STARTTLS" from
server side.
email_insecure:
schema:
$ref: '#/definitions/BoolConfigItem'
description: >-
Whether or not the certificate will be verified when Harbor tries to
access the email server.
ldap_url:
schema:
$ref: '#/definitions/StringConfigItem'
description: The URL of LDAP server.
ldap_base_dn:
schema:
$ref: '#/definitions/StringConfigItem'
description: The Base DN for LDAP binding.
ldap_filter:
schema:
$ref: '#/definitions/StringConfigItem'
description: The filter for LDAP binding.
ldap_scope:
type: integer
description: '0-LDAP_SCOPE_BASE, 1-LDAP_SCOPE_ONELEVEL, 2-LDAP_SCOPE_SUBTREE'
ldap_uid:
schema:
$ref: '#/definitions/StringConfigItem'
description: >-
The attribute which is used as identity for the LDAP binding, such as
"CN" or "SAMAccountname"
ldap_search_dn:
type: string
description: The DN of the user to do the search.
ldap_timeout:
schema:
$ref: '#/definitions/IntegerConfigItem'
description: timeout in seconds for connection to LDAP server.
ldap_group_attribute_name:
schema:
$ref: '#/definitions/StringConfigItem'
description: The attribute which is used as identity of the LDAP group, default is cn.
ldap_group_base_dn:
schema:
$ref: '#/definitions/StringConfigItem'
description: The base DN to search LDAP group.
ldap_group_search_filter:
schema:
$ref: '#/definitions/StringConfigItem'
description: The filter to search the ldap group.
ldap_group_search_scope:
schema:
$ref: '#/definitions/IntegerConfigItem'
description: The scope to search ldap. '0-LDAP_SCOPE_BASE, 1-LDAP_SCOPE_ONELEVEL, 2-LDAP_SCOPE_SUBTREE'
ldap_group_admin_dn:
schema:
$ref: '#/definitions/StringConfigItem'
description: Specify the ldap group which have the same privilege with Harbor admin.
project_creation_restriction:
schema:
$ref: '#/definitions/StringConfigItem'
description: >-
This attribute restricts what users have the permission to create
project. It can be "everyone" or "adminonly".
read_only:
schema:
$ref: '#/definitions/BoolConfigItem'
description: >-
'docker push' is prohibited by Harbor if you set it to true.
self_registration:
schema:
$ref: '#/definitions/BoolConfigItem'
description: >-
Whether the Harbor instance supports self-registration. If it's set
to false, admin need to add user to the instance.
token_expiration:
schema:
$ref: '#/definitions/IntegerConfigItem'
description: 'The expiration time of the token for internal Registry, in minutes.'
verify_remote_cert:
schema:
$ref: '#/definitions/BoolConfigItem'
description: >-
Whether or not the certificate will be verified when Harbor tries to
access a remote Harbor instance for replication.
scan_all_policy:
type: object
properties:
type:
type: string
description: >-
The type of scan all policy, currently the valid values are "none"
and "daily"
parameter:
type: object
properties:
daily_time:
type: integer
description: >-
The offest in seconds of UTC 0 o'clock, only valid when the
policy type is "daily"
description: >-
The parameters of the policy, the values are dependant on the type
of the policy.
Replication:
type: object
properties:
......@@ -3672,4 +3808,33 @@ definitions:
items:
$ref: '#/definitions/RepPolicy'
StringConfigItem:
type: object
properties:
value:
type: string
description: the string value of current config item
editable:
type: boolean
description: The configure item can be updated or not
BoolConfigItem:
type: object
properties:
value:
type: boolean
description: the boolean value of current config item
editable:
type: boolean
description: The configure item can be updated or not
IntegerConfigItem:
type: object
properties:
value:
type: int64
description: the integer value of current config item
editable:
type: boolean
description: The configure item can be updated or not
# coding: utf-8
"""
Harbor API
These APIs provide services for manipulating Harbor project.
OpenAPI spec version: 1.4.0
Generated by: https://github.com/swagger-api/swagger-codegen.git
"""
from __future__ import absolute_import
import os
import sys
sys.path.append(os.environ["SWAGGER_CLIENT_PATH"])
import unittest
import testutils
import docker
import swagger_client
from swagger_client.models.project import Project
from swagger_client.models.project_req import ProjectReq
from swagger_client.models.project_metadata import ProjectMetadata
from swagger_client.models.project_member import ProjectMember
from swagger_client.models.user_group import UserGroup
from swagger_client.models.configurations import Configurations
from swagger_client.rest import ApiException
from pprint import pprint
#Testcase
#3-07-LDAP usergroup manage project group members
class TestAssignRoleToLdapGroup(unittest.TestCase):
harbor_host = os.environ["HARBOR_HOST"]
"""AssignRoleToLdapGroup unit test stubs"""
product_api = testutils.GetProductApi("admin", "Harbor12345")
project_id = 0
docker_client = docker.from_env()
def setUp(self):
#login with admin, create a project and assign role to ldap group
result = self.product_api.configurations_put(configurations=Configurations(ldap_filter="", ldap_group_attribute_name="cn", ldap_group_base_dn="ou=groups,dc=example,dc=com", ldap_group_search_filter="objectclass=groupOfNames", ldap_group_search_scope=2))
pprint(result)
cfgs = self.product_api.configurations_get()
pprint(cfgs)
req = ProjectReq()
req.project_name = "ldap_group_test_prj"
req.metadata = ProjectMetadata(public="false")
result = self.product_api.projects_post(req)
pprint(result)
projs = self.product_api.projects_get(name="ldap_group_test_prj")
if projs.count>0 :
project = projs[0]
self.project_id = project.project_id
# asign role to project with dn
group_dn = "cn=harbor_admin,ou=groups,dc=example,dc=com"
projectmember = ProjectMember()
projectmember.role_id = 1
projectmember.member_group = UserGroup(ldap_group_dn=group_dn)
result = self.product_api.projects_project_id_members_post( project_id=self.project_id, project_member=projectmember )
pprint(result)
group_dn = "cn=harbor_dev,ou=groups,dc=example,dc=com"
projectmember = ProjectMember()
projectmember.role_id = 2
projectmember.member_group = UserGroup(ldap_group_dn=group_dn)
result = self.product_api.projects_project_id_members_post( project_id=self.project_id, project_member=projectmember )
pprint(result)
group_dn = "cn=harbor_guest,ou=groups,dc=example,dc=com"
projectmember = ProjectMember()
projectmember.role_id = 3
projectmember.member_group = UserGroup(ldap_group_dn=group_dn)
result = self.product_api.projects_project_id_members_post( project_id=self.project_id, project_member=projectmember )
pprint(result)
pass
def tearDown(self):
#delete images in project
result = self.product_api.repositories_repo_name_delete(repo_name="ldap_group_test_prj/busybox")
pprint(result)
result = self.product_api.repositories_repo_name_delete(repo_name="ldap_group_test_prj/busyboxdev")
pprint(result)
if self.project_id > 0 :
self.product_api.projects_project_id_delete(self.project_id)
pass
def testAssignRoleToLdapGroup(self):
"""Test AssignRoleToLdapGroup"""
admin_product_api = testutils.GetProductApi(username="admin_user", password="zhu88jie")
projects = admin_product_api.projects_get(name="ldap_group_test_prj")
self.assertTrue(projects.count > 1)
self.assertEqual(1, projects[0].current_user_role_id)
dev_product_api = testutils.GetProductApi("dev_user", "zhu88jie")
projects = dev_product_api.projects_get(name="ldap_group_test_prj")
self.assertTrue(projects.count > 1)
self.assertEqual(2, projects[0].current_user_role_id)
guest_product_api = testutils.GetProductApi("guest_user", "zhu88jie")
projects = guest_product_api.projects_get(name="ldap_group_test_prj")
self.assertTrue(projects.count > 1)
self.assertEqual(3, projects[0].current_user_role_id)
self.dockerCmdLoginAdmin(username="admin_user", password="zhu88jie")
self.dockerCmdLoginDev(username="dev_user", password="zhu88jie")
self.dockerCmdLoginGuest(username="guest_user", password="zhu88jie")
self.assertTrue(self.queryUserLogs(username="admin_user", password="zhu88jie")>0, "admin user can see logs")
self.assertTrue(self.queryUserLogs(username="dev_user", password="zhu88jie")>0, "dev user can see logs")
self.assertTrue(self.queryUserLogs(username="guest_user", password="zhu88jie")>0, "guest user can see logs")
self.assertTrue(self.queryUserLogs(username="user001", password="zhu88jie")==0, "user001 can not see any logs")
pass
# admin user can push, pull images
def dockerCmdLoginAdmin(self, username, password):
pprint(self.docker_client.info())
self.docker_client.login(username=username, password=password, registry=self.harbor_host)
self.docker_client.images.pull("busybox:latest")
image = self.docker_client.images.get("busybox:latest")
image.tag(repository=self.harbor_host+"/ldap_group_test_prj/busybox", tag="latest")
output = self.docker_client.images.push(repository=self.harbor_host+"/ldap_group_test_prj/busybox", tag="latest")
if output.find("error")>0 :
self.fail("Should not fail to push image for admin_user")
self.docker_client.images.pull(repository=self.harbor_host+"/ldap_group_test_prj/busybox", tag="latest")
pass
# dev user can push, pull images
def dockerCmdLoginDev(self, username, password, harbor_server=harbor_host):
self.docker_client.login(username=username, password=password, registry=self.harbor_host)
self.docker_client.images.pull("busybox:latest")
image = self.docker_client.images.get("busybox:latest")
image.tag(repository=self.harbor_host+"/ldap_group_test_prj/busyboxdev", tag="latest")
output = self.docker_client.images.push(repository=self.harbor_host+"/ldap_group_test_prj/busyboxdev", tag="latest")
if output.find("error") >0 :
self.fail("Should not fail to push images for dev_user")
pass
# guest user can pull images
def dockerCmdLoginGuest(self, username, password, harbor_server=harbor_host):
self.docker_client.login(username=username, password=password, registry=self.harbor_host)
self.docker_client.images.pull("busybox:latest")
image = self.docker_client.images.get("busybox:latest")
image.tag(repository=self.harbor_host+"/ldap_group_test_prj/busyboxguest", tag="latest")
output = self.docker_client.images.push(repository=self.harbor_host+"1/ldap_group_test_prj/busyboxguest", tag="latest")
if output.find("error")<0 :
self.fail("Should failed to push image for guest user")
self.docker_client.images.pull(repository=self.harbor_host+"/ldap_group_test_prj/busybox", tag="latest")
pass
# check can see his log in current project
def queryUserLogs(self, username, password, harbor_host=harbor_host):
client_product_api = testutils.GetProductApi(username=username, password=password)
logs = client_product_api.logs_get(repository="ldap_group_test_prj", username=username)
if logs == None:
return 0
else:
return logs.count
if __name__ == '__main__':
unittest.main()
# coding: utf-8
"""
Harbor API
These APIs provide services for manipulating Harbor project.
OpenAPI spec version: 1.4.0
Generated by: https://github.com/swagger-api/swagger-codegen.git
"""
from __future__ import absolute_import
import os
import sys
sys.path.append(os.environ["SWAGGER_CLIENT_PATH"])
import unittest
import testutils
import swagger_client
from swagger_client.models.project_req import ProjectReq
from swagger_client.models.access_log import AccessLog
from swagger_client.models.configurations import Configurations
from swagger_client.rest import ApiException
from swagger_client.models.configurations import Configurations
from pprint import pprint
#Testcase
# Define a LDAP group with harbor admin
class TestLdapAdminRole(unittest.TestCase):
"""AccessLog unit test stubs"""
product_api = testutils.GetProductApi("admin", "Harbor12345")
mike_product_api = testutils.GetProductApi("mike", "zhu88jie")
project_id = 0
def setUp(self):
pass
def tearDown(self):
if self.project_id > 0 :
self.mike_product_api.projects_project_id_delete(project_id=self.project_id)
pass
def testLdapAdminRole(self):
"""Test LdapAdminRole"""
result = self.product_api.configurations_put(configurations=Configurations(ldap_group_admin_dn="cn=harbor_users,ou=groups,dc=example,dc=com"))
pprint(result)
# Create a private project
result = self.product_api.projects_post(project=ProjectReq(project_name="test_private"))
pprint(result)
# query project with ldap user mike
projects = self.mike_product_api.projects_get(name="test_private")
self.assertTrue(projects.count>1)
self.project_id = projects[0].project_id
pass
if __name__ == '__main__':
unittest.main()
# coding: utf-8
"""
Harbor API
These APIs provide services for manipulating Harbor project.
OpenAPI spec version: 1.4.0
Generated by: https://github.com/swagger-api/swagger-codegen.git
"""
from __future__ import absolute_import
import os
import sys
sys.path.append(os.environ["SWAGGER_CLIENT_PATH"])
import unittest
import testutils
import swagger_client
from swagger_client.rest import ApiException
from swagger_client.models.user_group import UserGroup
from swagger_client.models.configurations import Configurations
from pprint import pprint
#Testcase
#12-01-LDAP-usergroup-add
#12-02-LDAP-usergroup-update
#12-03-LDAP-usergroup-delete
class TestUserGroup(unittest.TestCase):
"""UserGroup unit test stubs"""
product_api = testutils.GetProductApi("admin", "Harbor12345")
groupId = 0
def setUp(self):
result = self.product_api.configurations_put(configurations=Configurations(ldap_group_attribute_name="cn", ldap_group_base_dn="ou=groups,dc=example,dc=com", ldap_group_search_filter="objectclass=groupOfNames", ldap_group_search_scope=2))
pprint(result)
pass
def tearDown(self):
if self.groupId > 0 :
self.product_api.usergroups_group_id_delete(group_id=self.groupId)
pass
def testAddUpdateUserGroup(self):
"""Test UserGroup"""
user_group = UserGroup(group_name="harbor_group123", group_type=1, ldap_group_dn="cn=harbor_group,ou=groups,dc=example,dc=com")
result = self.product_api.usergroups_post(usergroup=user_group)
pprint(result)
user_groups = self.product_api.usergroups_get()
found = False
for ug in user_groups :
if ug.group_name == "harbor_group123" :
found = True
print("Found usergroup")
pprint(ug)
self.groupId = ug.id
self.assertTrue(found)
result = self.product_api.usergroups_group_id_put(self.groupId, usergroup = UserGroup(group_name = "newharbor_group"))
new_user_group = self.product_api.usergroups_group_id_get(group_id=self.groupId)
self.assertEqual("newharbor_group", new_user_group.group_name)
pass
if __name__ == '__main__':
unittest.main()
import time
import os
import sys
sys.path.append(os.environ["SWAGGER_CLIENT_PATH"])
from swagger_client.rest import ApiException
import swagger_client.models
from pprint import pprint
def GetProductApi(username, password, harbor_server= os.environ["HARBOR_HOST"]):