diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 36907b656..a34b90479 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -166,6 +166,14 @@ jobs: ./mconfig && \ make -C builddir && \ sudo make -C builddir install + python -V + sudo apt-get update -y && sudo apt-get install -y zbar-tools libzbar-dev python-zbar + sudo apt-get update -y + sudo apt-get install -y python3.6 + sudo rm /usr/bin/python + sudo ln -s /usr/bin/python3.6 /usr/bin/python + sudo apt-get install -y python3-pip + python -V - name: install run: | cd src/github.com/goharbor/harbor @@ -228,6 +236,14 @@ jobs: sudo cp ./tests/harbor_ca.crt /usr/local/share/ca-certificates/ sudo update-ca-certificates sudo service docker restart + python -V + sudo apt-get update -y && sudo apt-get install -y zbar-tools libzbar-dev python-zbar + sudo apt-get update -y + sudo apt-get install -y python3.6 + sudo rm /usr/bin/python + sudo ln -s /usr/bin/python3.6 /usr/bin/python + sudo apt-get install -y python3-pip + python -V - name: install run: | cd src/github.com/goharbor/harbor diff --git a/Makefile b/Makefile index 3adf2eb46..b8905abf5 100644 --- a/Makefile +++ b/Makefile @@ -513,14 +513,14 @@ down: swagger_client: @echo "Generate swagger client" - wget -q https://repo1.maven.org/maven2/io/swagger/swagger-codegen-cli/2.3.1/swagger-codegen-cli-2.3.1.jar -O swagger-codegen-cli.jar + wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/4.3.1/openapi-generator-cli-4.3.1.jar -O openapi-generator-cli.jar rm -rf harborclient mkdir -p harborclient/harbor_client mkdir -p harborclient/harbor_swagger_client mkdir -p harborclient/harbor_v2_swagger_client - java -jar swagger-codegen-cli.jar generate -i api/swagger.yaml -l python -o harborclient/harbor_client -DpackageName=client - java -jar swagger-codegen-cli.jar generate -i api/v2.0/legacy_swagger.yaml -l python -o harborclient/harbor_swagger_client -DpackageName=swagger_client - java -jar swagger-codegen-cli.jar generate -i api/v2.0/swagger.yaml -l python -o harborclient/harbor_v2_swagger_client -DpackageName=v2_swagger_client + java -jar openapi-generator-cli.jar generate -i api/swagger.yaml -g python -o harborclient/harbor_client --package-name client + java -jar openapi-generator-cli.jar generate -i api/v2.0/legacy_swagger.yaml -g python -o harborclient/harbor_swagger_client --package-name swagger_client + java -jar openapi-generator-cli.jar generate -i api/v2.0/swagger.yaml -g python -o harborclient/harbor_v2_swagger_client --package-name v2_swagger_client cd harborclient/harbor_client; python ./setup.py install cd harborclient/harbor_swagger_client; python ./setup.py install cd harborclient/harbor_v2_swagger_client; python ./setup.py install diff --git a/tests/apitests/python/library/Harbor.py b/tests/apitests/python/library/Harbor.py index 096f9f782..d46fbf4f5 100644 --- a/tests/apitests/python/library/Harbor.py +++ b/tests/apitests/python/library/Harbor.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -import site -reload(site) import project import label import registry @@ -8,7 +6,5 @@ import replication import repository import swagger_client -class Harbor(project.Project, label.Label, - registry.Registry, replication.Replication, - repository.Repository): +class Harbor(project.Project): pass \ No newline at end of file diff --git a/tests/apitests/python/library/artifact.py b/tests/apitests/python/library/artifact.py index 5713d1274..db6730dfe 100644 --- a/tests/apitests/python/library/artifact.py +++ b/tests/apitests/python/library/artifact.py @@ -13,7 +13,7 @@ class Artifact(base.Base, object): client = self._get_client(**kwargs) return client.list_artifacts(project_name, repo_name) - def get_reference_info(self, project_name, repo_name, reference, **kwargs): + def get_reference_info(self, project_name, repo_name, reference, ignore_not_found = False,**kwargs): client = self._get_client(**kwargs) params = {} if "with_signature" in kwargs: @@ -22,7 +22,12 @@ class Artifact(base.Base, object): params["with_tag"] = kwargs["with_tag"] if "with_scan_overview" in kwargs: params["with_scan_overview"] = kwargs["with_scan_overview"] - return client.get_artifact_with_http_info(project_name, repo_name, reference, **params) + + try: + return client.get_artifact_with_http_info(project_name, repo_name, reference, **params) + except ApiException as e: + if e.status == 404 and ignore_not_found == True: + return [] def delete_artifact(self, project_name, repo_name, reference, expect_status_code = 200, expect_response_body = None, **kwargs): client = self._get_client(**kwargs) @@ -62,10 +67,14 @@ class Artifact(base.Base, object): base._assert_status_code(201, status_code) return data - def create_tag(self, project_name, repo_name, reference, tag_name, expect_status_code = 201, **kwargs): + def create_tag(self, project_name, repo_name, reference, tag_name, expect_status_code = 201, ignore_conflict = False, **kwargs): client = self._get_client(**kwargs) tag = v2_swagger_client.Tag(name = tag_name) - _, status_code, _ = client.create_tag_with_http_info(project_name, repo_name, reference, tag) + try: + _, status_code, _ = client.create_tag_with_http_info(project_name, repo_name, reference, tag) + except ApiException as e: + if e.status == 409 and ignore_conflict == True: + return base._assert_status_code(expect_status_code, status_code) def delete_tag(self, project_name, repo_name, reference, tag_name, expect_status_code = 200, **kwargs): @@ -82,11 +91,13 @@ class Artifact(base.Base, object): if (timeout_count == 0): break artifact = self.get_reference_info(project_name, repo_name, reference, **kwargs) - print "artifact", artifact - print "artifact[0]", artifact[0] - print "artifact[0].scan_overview", artifact[0].scan_overview - print "artifact[0].scan_overview['application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0']", artifact[0].scan_overview['application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0'] - scan_status = artifact[0].scan_overview['application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0']["scan_status"] + scan_status = artifact[0].scan_overview['application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0'].scan_status if scan_status == expected_scan_status: return raise Exception("Scan image result is {}, not as expected {}.".format(scan_status, expected_scan_status)) + + def check_reference_exist(self, project_name, repo_name, reference, ignore_not_found = False, **kwargs): + artifact = self.get_reference_info( project_name, repo_name, reference, ignore_not_found=ignore_not_found, **kwargs) + return { + 0: False, + }.get(len(artifact), True) diff --git a/tests/apitests/python/library/base.py b/tests/apitests/python/library/base.py index 0df5a6179..475187322 100644 --- a/tests/apitests/python/library/base.py +++ b/tests/apitests/python/library/base.py @@ -1,134 +1,133 @@ -# -*- coding: utf-8 -*- -import os -import sys -import time -import subprocess -import client -import swagger_client -import v2_swagger_client -try: - from urllib import getproxies -except ImportError: - from urllib.request import getproxies - -class Server: - def __init__(self, endpoint, verify_ssl): - self.endpoint = endpoint - self.verify_ssl = verify_ssl - -class Credential: - def __init__(self, type, username, password): - self.type = type - self.username = username - self.password = password - -def get_endpoint(): - harbor_server = os.environ.get("HARBOR_HOST", "localhost:8080") - return os.environ.get("HARBOR_HOST_SCHEMA", "https")+ "://"+harbor_server+"/api/v2.0" - -def _create_client(server, credential, debug, api_type="products"): - cfg = None - if api_type in ('projectv2', 'artifact', 'repository', 'scan'): - cfg = v2_swagger_client.Configuration() - else: - cfg = swagger_client.Configuration() - - cfg.host = server.endpoint - cfg.verify_ssl = server.verify_ssl - # support basic auth only for now - cfg.username = credential.username - cfg.password = credential.password - cfg.debug = debug - - proxies = getproxies() - proxy = proxies.get('http', proxies.get('all', None)) - if proxy: - cfg.proxy = proxy - - if cfg.username is None and cfg.password is None: - # returns {} for auth_settings for anonymous access - import types - cfg.auth_settings = types.MethodType(lambda self: {}, cfg) - - return { - "chart": client.ChartRepositoryApi(client.ApiClient(cfg)), - "products": swagger_client.ProductsApi(swagger_client.ApiClient(cfg)), - "projectv2": v2_swagger_client.ProjectApi(v2_swagger_client.ApiClient(cfg)), - "artifact": v2_swagger_client.ArtifactApi(v2_swagger_client.ApiClient(cfg)), - "repository": v2_swagger_client.RepositoryApi(v2_swagger_client.ApiClient(cfg)), - "scan": v2_swagger_client.ScanApi(v2_swagger_client.ApiClient(cfg)), - "scanner": swagger_client.ScannersApi(swagger_client.ApiClient(cfg)), - }.get(api_type,'Error: Wrong API type') - -def _assert_status_code(expect_code, return_code): - if str(return_code) != str(expect_code): - raise Exception(r"HTTPS status code s not as we expected. Expected {}, while actual HTTPS status code is {}.".format(expect_code, return_code)) - -def _assert_status_body(expect_status_body, returned_status_body): - if expect_status_body.strip() != returned_status_body.strip(): - raise Exception(r"HTTPS status body s not as we expected. Expected {}, while actual HTTPS status body is {}.".format(expect_status_body, returned_status_body)) - -def _random_name(prefix): - return "%s-%d" % (prefix, int(round(time.time() * 1000))) - -def _get_id_from_header(header): - try: - location = header["Location"] - return int(location.split("/")[-1]) - except Exception: - return None - -def _get_string_from_unicode(udata): - result='' - for u in udata: - tmp = u.encode('utf8') - result = result + tmp.strip('\n\r\t') - return result - -def run_command(command): - print "Command: ", subprocess.list2cmdline(command) - try: - output = subprocess.check_output(command, - stderr=subprocess.STDOUT, - universal_newlines=True) - except subprocess.CalledProcessError as e: - raise Exception('Error: Exited with error code: %s. Output:%s'% (e.returncode, e.output)) - return output - -class Base: - def __init__(self, server=None, credential=None, debug=True, api_type="products"): - if server is None: - server = Server(endpoint=get_endpoint(), verify_ssl=False) - if not isinstance(server.verify_ssl, bool): - server.verify_ssl = server.verify_ssl == "True" - - if credential is None: - credential = Credential(type="basic_auth", username="admin", password="Harbor12345") # nosec - - self.server = server - self.credential = credential - self.debug = debug - self.api_type = api_type - self.client = _create_client(server, credential, debug, api_type=api_type) - - def _get_client(self, **kwargs): - if len(kwargs) == 0: - return self.client - server = self.server - if "api_type" in kwargs: - server.api_type = kwargs.get("api_type") - if "endpoint" in kwargs: - server.endpoint = kwargs.get("endpoint") - if "verify_ssl" in kwargs: - if not isinstance(kwargs.get("verify_ssl"), bool): - server.verify_ssl = kwargs.get("verify_ssl") == "True" - else: - server.verify_ssl = kwargs.get("verify_ssl") - - credential = Credential( - kwargs.get("type", self.credential.type), - kwargs.get("username", self.credential.username), - kwargs.get("password", self.credential.password), - ) - - return _create_client(server, credential, self.debug, self.api_type) \ No newline at end of file +# -*- coding: utf-8 -*- +import os +import sys +import time +import subprocess +import client +import swagger_client +import v2_swagger_client +try: + from urllib import getproxies +except ImportError: + from urllib.request import getproxies + +class Server: + def __init__(self, endpoint, verify_ssl): + self.endpoint = endpoint + self.verify_ssl = verify_ssl + +class Credential: + def __init__(self, type, username, password): + self.type = type + self.username = username + self.password = password + +def get_endpoint(): + harbor_server = os.environ.get("HARBOR_HOST", "localhost:8080") + return os.environ.get("HARBOR_HOST_SCHEMA", "https")+ "://"+harbor_server+"/api/v2.0" + +def _create_client(server, credential, debug, api_type="products"): + cfg = None + if api_type in ('projectv2', 'artifact', 'repository', 'scan'): + cfg = v2_swagger_client.Configuration() + else: + cfg = swagger_client.Configuration() + + cfg.host = server.endpoint + cfg.verify_ssl = server.verify_ssl + # support basic auth only for now + cfg.username = credential.username + cfg.password = credential.password + cfg.debug = debug + + proxies = getproxies() + proxy = proxies.get('http', proxies.get('all', None)) + if proxy: + cfg.proxy = proxy + + if cfg.username is None and cfg.password is None: + # returns {} for auth_settings for anonymous access + import types + cfg.auth_settings = types.MethodType(lambda self: {}, cfg) + + return { + "chart": client.ChartRepositoryApi(client.ApiClient(cfg)), + "products": swagger_client.ProductsApi(swagger_client.ApiClient(cfg)), + "projectv2": v2_swagger_client.ProjectApi(v2_swagger_client.ApiClient(cfg)), + "artifact": v2_swagger_client.ArtifactApi(v2_swagger_client.ApiClient(cfg)), + "repository": v2_swagger_client.RepositoryApi(v2_swagger_client.ApiClient(cfg)), + "scan": v2_swagger_client.ScanApi(v2_swagger_client.ApiClient(cfg)), + "scanner": swagger_client.ScannersApi(swagger_client.ApiClient(cfg)), + }.get(api_type,'Error: Wrong API type') + +def _assert_status_code(expect_code, return_code): + if str(return_code) != str(expect_code): + raise Exception(r"HTTPS status code s not as we expected. Expected {}, while actual HTTPS status code is {}.".format(expect_code, return_code)) + +def _assert_status_body(expect_status_body, returned_status_body): + if expect_status_body.strip() != returned_status_body.strip(): + raise Exception(r"HTTPS status body s not as we expected. Expected {}, while actual HTTPS status body is {}.".format(expect_status_body, returned_status_body)) + +def _random_name(prefix): + return "%s-%d" % (prefix, int(round(time.time() * 1000))) + +def _get_id_from_header(header): + try: + location = header["Location"] + return int(location.split("/")[-1]) + except Exception: + return None + +def _get_string_from_unicode(udata): + result='' + for u in udata: + tmp = u.encode('utf8') + result = result + tmp.strip('\n\r\t') + return result + +def run_command(command): + print("Command: ", subprocess.list2cmdline(command)) + try: + output = subprocess.check_output(command, + stderr=subprocess.STDOUT, + universal_newlines=True) + except subprocess.CalledProcessError as e: + raise Exception('Error: Exited with error code: %s. Output:%s'% (e.returncode, e.output)) + return output + +class Base(object): + def __init__(self, server=None, credential=None, debug=True, api_type="products"): + if server is None: + server = Server(endpoint=get_endpoint(), verify_ssl=False) + if not isinstance(server.verify_ssl, bool): + server.verify_ssl = server.verify_ssl == "True" + + if credential is None: + credential = Credential(type="basic_auth", username="admin", password="Harbor12345") + + self.server = server + self.credential = credential + self.debug = debug + self.api_type = api_type + self.client = _create_client(server, credential, debug, api_type=api_type) + + def _get_client(self, **kwargs): + if len(kwargs) == 0: + return self.client + + server = self.server + if "endpoint" in kwargs: + server.endpoint = kwargs.get("endpoint") + if "verify_ssl" in kwargs: + if not isinstance(kwargs.get("verify_ssl"), bool): + server.verify_ssl = kwargs.get("verify_ssl") == "True" + else: + server.verify_ssl = kwargs.get("verify_ssl") + + credential = Credential( + kwargs.get("type", self.credential.type), + kwargs.get("username", self.credential.username), + kwargs.get("password", self.credential.password), + ) + + return _create_client(server, credential, self.debug, kwargs.get('api_type', self.api_type)) diff --git a/tests/apitests/python/library/chart.py b/tests/apitests/python/library/chart.py index 3d0fef853..d5bb6b64a 100644 --- a/tests/apitests/python/library/chart.py +++ b/tests/apitests/python/library/chart.py @@ -17,7 +17,6 @@ class Chart(base.Base, object): def chart_should_exist(self, repository, chart_name, **kwargs): charts_data = self.get_charts(repository, **kwargs) - print "charts_data:", charts_data for chart in charts_data: if chart.name == chart_name: return True diff --git a/tests/apitests/python/library/cnab.py b/tests/apitests/python/library/cnab.py index 835d002a8..f0b7231dc 100644 --- a/tests/apitests/python/library/cnab.py +++ b/tests/apitests/python/library/cnab.py @@ -9,12 +9,9 @@ def load_bundle(service_image, invocation_image): bundle_tmpl_file = "./tests/apitests/python/bundle_data/bundle.json.tmpl" with open(bundle_tmpl_file,'r') as load_f: load_dict = json.load(load_f) - print "load_dict:", load_dict - print "load_dict-invocationImages:", load_dict["invocationImages"][0]["contentDigest"] load_dict["images"]["hello"]["image"] = service_image load_dict["invocationImages"][0]["image"] = invocation_image bundle_str = json.dumps(load_dict) - print "bundle_str:", bundle_str with open(bundle_file,'w') as dump_f: dump_f.write(bundle_str) dump_f.close() @@ -26,16 +23,16 @@ def cnab_fixup_bundle(bundle_file, target, auto_update_bundle = True): if auto_update_bundle == True: command.append("--auto-update-bundle") #fixed_bundle_file = bundle_file - print "Command: ", command + print("Command: ", command) ret = base.run_command(command) - print "Command return: ", ret + print("Command return: ", ret) return fixed_bundle_file def cnab_push_bundle(bundle_file, target): command = ["cnab-to-oci", "push", bundle_file, "--target", target, "--auto-update-bundle"] - print "Command: ", command + print("Command: ", command) ret = base.run_command(command) - print "Command return: ", ret + print("Command return: ", ret) for line in ret.split("\n"): line = line.replace('\"', '') if line.find('sha256') >= 0: @@ -48,5 +45,4 @@ def push_cnab_bundle(harbor_server, user, password, service_image, invocation_im bundle_file = load_bundle(service_image, invocation_image) fixed_bundle_file = cnab_fixup_bundle(bundle_file, target, auto_update_bundle = auto_update_bundle) sha256 = cnab_push_bundle(fixed_bundle_file, target) - print "sha256:", sha256 return sha256 diff --git a/tests/apitests/python/library/configurations.py b/tests/apitests/python/library/configurations.py index 44c321d80..196d0940a 100644 --- a/tests/apitests/python/library/configurations.py +++ b/tests/apitests/python/library/configurations.py @@ -11,6 +11,16 @@ def set_configurations(client, expect_status_code = 200, expect_response_body = conf.project_creation_restriction = config.get("project_creation_restriction") if "token_expiration" in config: conf.token_expiration = config.get("token_expiration") + if "ldap_filter" in config: + conf.ldap_filter = config.get("ldap_filter") + if "ldap_group_attribute_name" in config: + conf.ldap_group_attribute_name = config.get("ldap_group_attribute_name") + if "ldap_group_base_dn" in config: + conf.ldap_group_base_dn = config.get("ldap_group_base_dn") + if "ldap_group_search_filter" in config: + conf.ldap_group_search_filter = config.get("ldap_group_search_filter") + if "ldap_group_search_scope" in config: + conf.ldap_group_search_scope = config.get("ldap_group_search_scope") try: _, status_code, _ = client.configurations_put_with_http_info(conf) @@ -56,3 +66,11 @@ class Configurations(base.Base): config=dict(token_expiration=token_expiration) set_configurations(client, expect_status_code = expect_status_code, **config) + + def set_configurations_of_ldap(self, ldap_filter=None, ldap_group_attribute_name=None, + ldap_group_base_dn=None, ldap_group_search_filter=None, ldap_group_search_scope=None, expect_status_code = 200, **kwargs): + client = self._get_client(**kwargs) + config=dict(ldap_filter=ldap_filter, ldap_group_attribute_name=ldap_group_attribute_name, + ldap_group_base_dn=ldap_group_base_dn, ldap_group_search_filter=ldap_group_search_filter, ldap_group_search_scope=ldap_group_search_scope) + set_configurations(client, expect_status_code = expect_status_code, **config) + diff --git a/tests/apitests/python/library/containerd.py b/tests/apitests/python/library/containerd.py index 1517f169f..01ecc3cf7 100644 --- a/tests/apitests/python/library/containerd.py +++ b/tests/apitests/python/library/containerd.py @@ -6,15 +6,15 @@ import docker_api def ctr_images_pull(username, password, oci): command = ["sudo", "ctr", "images", "pull", "-u", username+":"+password, oci] - print "Command: ", command + print("Command: ", command) ret = base.run_command(command) - print "Command return: ", ret + print("Command return: ", ret) def ctr_images_list(oci_ref = None): command = ["sudo", "ctr", "images", "list", "--q"] - print "Command: ", command + print("Command: ", command) ret = base.run_command(command) - print "Command return: ", ret + print("Command return: ", ret) if oci_ref is not None and oci_ref not in ret.split("\n"): raise Exception(r" Get OCI ref failed, expected ref is [{}], but return ref list is [{}]".format (ret)) diff --git a/tests/apitests/python/library/docker_api.py b/tests/apitests/python/library/docker_api.py index 252791375..b745b8ef9 100644 --- a/tests/apitests/python/library/docker_api.py +++ b/tests/apitests/python/library/docker_api.py @@ -13,29 +13,29 @@ except ImportError: def docker_info_display(): command = ["docker", "info", "-f", "'{{.OSType}}/{{.Architecture}}'"] - print "Docker Info: ", command + print("Docker Info: ", command) ret = base.run_command(command) - print "Command return: ", ret + print("Command return: ", ret) def docker_login_cmd(harbor_host, user, password, enable_manifest = True): command = ["sudo", "docker", "login", harbor_host, "-u", user, "-p", password] - print "Docker Login Command: ", command + print( "Docker Login Command: ", command) base.run_command(command) if enable_manifest == True: try: ret = subprocess.check_output(["./tests/apitests/python/update_docker_cfg.sh"], shell=False) - except subprocess.CalledProcessError, exc: + except subprocess.CalledProcessError as exc: raise Exception("Failed to update docker config, error is {} {}.".format(exc.returncode, exc.output)) def docker_manifest_create(index, manifests): command = ["sudo", "docker","manifest","create",index] command.extend(manifests) - print "Docker Manifest Command: ", command + print( "Docker Manifest Command: ", command) base.run_command(command) def docker_manifest_push(index): command = ["sudo", "docker","manifest","push",index] - print "Docker Manifest Command: ", command + print( "Docker Manifest Command: ", command) ret = base.run_command(command) index_sha256="" manifest_list=[] @@ -58,7 +58,7 @@ def list_repositories(harbor_host, user, password, n = None, last = None): command = ["curl", "-s", "-u", user+":"+password, "https://"+harbor_host+"/v2/_catalog"+"?n=%d"%n, "--insecure"] else: command = ["curl", "-s", "-u", user+":"+password, "https://"+harbor_host+"/v2/_catalog", "--insecure"] - print "List Repositories Command: ", command + print( "List Repositories Command: ", command) ret = base.run_command(command) repos = json.loads(ret).get("repositories","") return repos @@ -70,7 +70,7 @@ def list_image_tags(harbor_host, repository, user, password, n = None, last = No command = ["curl", "-s", "-u", user+":"+password, "https://"+harbor_host+"/v2/"+repository+"/tags/list"+"?n=%d"%n, "--insecure"] else: command = ["curl", "-s", "-u", user+":"+password, "https://"+harbor_host+"/v2/"+repository+"/tags/list", "--insecure"] - print "List Image Tags Command: ", command + print( "List Image Tags Command: ", command) ret = base.run_command(command) tags = json.loads(ret).get("tags","") return tags @@ -85,13 +85,13 @@ class DockerAPI(object): expected_error_message = None try: self.DCLIENT.login(registry = registry, username=username, password=password) - except docker.errors.APIError, err: + except docker.errors.APIError as err: if expected_error_message is not None: - print "docker login error:", str(err) + print( "docker login error:", str(err)) if str(err).lower().find(expected_error_message.lower()) < 0: raise Exception(r"Docker login: Return message {} is not as expected {}".format(str(err), expected_error_message)) else: - raise Exception(r" Docker login failed, error is [{}]".format (err.message)) + raise Exception(r" Docker login failed, error is [{}]".format (str(err))) def docker_image_pull(self, image, tag = None, expected_error_message = None): if tag is not None: @@ -103,16 +103,16 @@ class DockerAPI(object): caught_err = False ret = "" try: - ret = base._get_string_from_unicode(self.DCLIENT.pull(r'{}:{}'.format(image, _tag))) + self.DCLIENT.pull(r'{}:{}'.format(image, _tag)) return ret - except Exception, err: + except Exception as err: caught_err = True if expected_error_message is not None: - print "docker image pull error:", str(err) + 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(str(err), expected_error_message)) else: - raise Exception(r" Docker pull image {} failed, error is [{}]".format (image, err.message)) + raise Exception(r" Docker pull image {} failed, error is [{}]".format (image, message)) if caught_err == False: if expected_error_message is not None: if str(ret).lower().find(expected_error_message.lower()) < 0: @@ -128,8 +128,8 @@ class DockerAPI(object): try: self.DCLIENT.tag(image, harbor_registry, _tag, force=True) return harbor_registry, _tag - except docker.errors.APIError, e: - raise Exception(r" Docker tag image {} failed, error is [{}]".format (image, e.message)) + except docker.errors.APIError as err: + raise Exception(r" Docker tag image {} failed, error is [{}]".format (image, str(err))) def docker_image_push(self, harbor_registry, tag, expected_error_message = None): caught_err = False @@ -137,16 +137,16 @@ class DockerAPI(object): if expected_error_message is "": expected_error_message = None try: - ret = base._get_string_from_unicode(self.DCLIENT.push(harbor_registry, tag, stream=True)) + self.DCLIENT.push(harbor_registry, tag) return ret - except Exception, err: + except Exception as err: caught_err = True if expected_error_message is not None: - print "docker image push error:", str(err) + 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)) + raise Exception(r" Docker push image {} failed, error is [{}]".format (harbor_registry, message)) if caught_err == False: if expected_error_message is not None: if str(ret).lower().find(expected_error_message.lower()) < 0: @@ -184,14 +184,14 @@ class DockerAPI(object): self.DCLIENT.pull(repo) image = self.DCLIENT2.images.get(repo) return repo, image.id - except Exception, err: + except Exception as err: caught_err = True if expected_error_message is not None: - print "docker image build error:", str(err) + print( "docker image build 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 build image {} failed, error is [{}]".format (harbor_registry, err.message)) + raise Exception(r" Docker build image {} failed, error is [{}]".format (harbor_registry, str(err))) if caught_err == False: if expected_error_message is not None: if str(ret).lower().find(expected_error_message.lower()) < 0: diff --git a/tests/apitests/python/library/helm.py b/tests/apitests/python/library/helm.py index 19002cfd7..5345ff10e 100644 --- a/tests/apitests/python/library/helm.py +++ b/tests/apitests/python/library/helm.py @@ -6,26 +6,26 @@ import base def get_chart_file(file_name): command = ["wget", file_name] ret = base.run_command(command) - print "Command Return: ", ret + print("Command return: ", ret) command = ["tar", "xvf", file_name.split('/')[-1]] ret = base.run_command(command) - print "Command Return: ", ret + print("Command return: ", ret) def helm_login(harbor_server, user, password): os.putenv("HELM_EXPERIMENTAL_OCI", "1") command = ["helm3", "registry", "login", harbor_server, "-u", user, "-p", password] - print "Command: ", command + print("Command: ", command) ret = base.run_command(command) - print "Command return: ", ret + print("Command return: ", ret) def helm_save(chart_archive, harbor_server, project, repo_name): command = ["helm3", "chart","save", chart_archive, harbor_server+"/"+project+"/"+repo_name] - print "Command: ", command + print("Command: ", command) base.run_command(command) def helm_push(harbor_server, project, repo_name, version): command = ["helm3", "chart","push", harbor_server+"/"+project+"/"+repo_name+":"+version] - print "Command: ", command + print("Command: ", command) ret = base.run_command(command) return ret @@ -37,11 +37,11 @@ def helm_chart_push_to_harbor(chart_file, archive, harbor_server, project, repo_ def helm2_add_repo(helm_repo_name, harbor_url, project, username, password): command = ["helm2", "repo", "add", "--username=" + username, "--password=" + password, helm_repo_name, harbor_url + "/chartrepo/" + project] - print "Command: ", command + print("Command: ", command) base.run_command(command) def helm2_push(helm_repo_name, chart_file, project, username, password): get_chart_file(chart_file) command = ["helm2", "push", "--username=" + username, "--password=" + password, chart_file.split('/')[-1], helm_repo_name] - print "Command: ", command + print("Command: ", command) base.run_command(command) \ No newline at end of file diff --git a/tests/apitests/python/library/oras.py b/tests/apitests/python/library/oras.py index 2e9751196..ce082984c 100644 --- a/tests/apitests/python/library/oras.py +++ b/tests/apitests/python/library/oras.py @@ -39,7 +39,6 @@ def oras_pull(harbor_server, user, password, project, repo, tag): os.rmdir(cwd) os.makedirs(cwd) os.chdir(cwd) - print "Tmp dir:", cwd except Exception as e: raise Exception('Error: Exited with error {}',format(e)) ret = base.run_command([oras_cmd, "pull", harbor_server + "/" + project + "/" + repo+":"+ tag, "-a"]) diff --git a/tests/apitests/python/library/project.py b/tests/apitests/python/library/project.py index aa8787d88..5cc76a2e4 100644 --- a/tests/apitests/python/library/project.py +++ b/tests/apitests/python/library/project.py @@ -47,6 +47,14 @@ class Project(base.Base): base._assert_status_code(200, status_code) return data + def get_project_id(self, project_name, **kwargs): + project_data = self.get_projects(dict(), **kwargs) + actual_count = len(project_data) + if actual_count == 1 and str(project_data[0].project_name) != str(project_name): + return project_data[0].project_id + else: + return None + def projects_should_exist(self, params, expected_count = None, expected_project_id = None, **kwargs): project_data = self.get_projects(params, **kwargs) actual_count = len(project_data) @@ -162,11 +170,16 @@ class Project(base.Base): 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): + def add_project_members(self, project_id, user_id = None, member_role_id = None, _ldap_group_dn=None,expect_status_code = 201, **kwargs): + projectMember = swagger_client.ProjectMember() + if user_id is not None: + projectMember.member_user = {"user_id": int(user_id)} if member_role_id is None: - member_role_id = 1 - _member_user = {"user_id": int(user_id)} - projectMember = swagger_client.ProjectMember(member_role_id, member_user = _member_user) + projectMember.role_id = 1 + else: + projectMember.role_id = member_role_id + if _ldap_group_dn is not None: + projectMember.member_group = swagger_client.UserGroup(ldap_group_dn=_ldap_group_dn) client = self._get_client(**kwargs) data = [] data, status_code, header = client.projects_project_id_members_post_with_http_info(project_id, project_member = projectMember) diff --git a/tests/apitests/python/library/projectV2.py b/tests/apitests/python/library/projectV2.py index de5a81a58..9c6cbecf9 100644 --- a/tests/apitests/python/library/projectV2.py +++ b/tests/apitests/python/library/projectV2.py @@ -4,6 +4,7 @@ import time import base import v2_swagger_client from v2_swagger_client.rest import ApiException +from library.base import _assert_status_code class ProjectV2(base.Base, object): def __init__(self): @@ -26,3 +27,14 @@ class ProjectV2(base.Base, object): count = count + 1 return count + def query_user_logs(self, project_name, status_code=200, **kwargs): + try: + logs = self.get_project_log(project_name, expect_status_code=status_code, **kwargs) + count = 0 + for log in list(logs): + count = count + 1 + return count + except ApiException as e: + _assert_status_code(status_code, e.status) + return 0 + diff --git a/tests/apitests/python/library/replication.py b/tests/apitests/python/library/replication.py index 172889b02..055e53843 100644 --- a/tests/apitests/python/library/replication.py +++ b/tests/apitests/python/library/replication.py @@ -38,7 +38,7 @@ class Replication(base.Base): if str(rule_data.name) != str(expect_rule_name): raise Exception(r"Check replication rule failed, expect <{}> actual <{}>.".format(expect_rule_name, str(rule_data.name))) else: - print r"Check Replication rule passed, rule name <{}>.".format(str(rule_data.name)) + print(r"Check Replication rule passed, rule name <{}>.".format(str(rule_data.name))) #get_trigger = str(rule_data.trigger.kind) #if expect_trigger is not None and get_trigger == str(expect_trigger): # print r"Check Replication rule trigger passed, trigger name <{}>.".format(get_trigger) diff --git a/tests/apitests/python/library/repository.py b/tests/apitests/python/library/repository.py index b0c119fb4..e3190558b 100644 --- a/tests/apitests/python/library/repository.py +++ b/tests/apitests/python/library/repository.py @@ -13,9 +13,8 @@ def pull_harbor_image(registry, username, password, image, tag, expected_login_e return time.sleep(2) ret = _docker_api.docker_image_pull(r'{}/{}'.format(registry, image), tag = tag, expected_error_message = expected_error_message) - print ret -def push_image_to_project(project_name, registry, username, password, image, tag, expected_login_error_message = None, expected_error_message = None, profix_for_image = None): +def push_image_to_project(project_name, registry, username, password, image, tag, expected_login_error_message = None, expected_error_message = None, profix_for_image = None, new_image=None): _docker_api = DockerAPI() _docker_api.docker_login(registry, username, password, expected_error_message = expected_login_error_message) time.sleep(2) @@ -24,6 +23,8 @@ def push_image_to_project(project_name, registry, username, password, image, tag _docker_api.docker_image_pull(image, tag = tag) time.sleep(2) + image = new_image or image + if profix_for_image == None: new_harbor_registry, new_tag = _docker_api.docker_image_tag(r'{}:{}'.format(image, tag), r'{}/{}/{}'.format(registry, project_name, image)) else: @@ -40,14 +41,8 @@ def push_special_image_to_project(project_name, registry, username, password, im time.sleep(2) if expected_login_error_message != None: return - return _docker_api.docker_image_build(r'{}/{}/{}'.format(registry, project_name, image), tags = tags, size=size, expected_error_message=expected_error_message) + return _docker_api.docker_image_build(r'{}/{}/{}'.format(registry, project_name, image), tags = tags, size=int(size), expected_error_message=expected_error_message) -def is_repo_exist_in_project(repositories, repo_name): - result = False - for reop in repositories: - if reop.name == repo_name: - return True - return result class Repository(base.Base, object): def __init__(self): @@ -118,16 +113,22 @@ class Repository(base.Base, object): if tag.scan_overview != None: raise Exception("Image should be state!") - def repository_should_exist(self, project_id, repo_name, **kwargs): - repositories = self.list_repositories(project_id, **kwargs) - if is_repo_exist_in_project(repositories, repo_name) == False: + def repository_should_exist(self, project_Name, repo_name, **kwargs): + repositories = self.list_repositories(project_Name, **kwargs) + if repo_name not in repositories: raise Exception("Repository {} is not exist.".format(repo_name)) + def check_repository_exist(self, project_Name, repo_name, **kwargs): + repositories = self.list_repositories(project_Name, **kwargs) + for repo in repositories: + if repo.name == project_Name+"/"+repo_name: + return True + return False + def signature_should_exist(self, repo_name, tag, **kwargs): signatures = self.get_repo_signatures(repo_name, **kwargs) for each_sign in signatures: if each_sign.tag == tag and len(each_sign.hashes["sha256"]) == 44: - print "sha256:", len(each_sign.hashes["sha256"]) return raise Exception(r"Signature of {}:{} is not exist!".format(repo_name, tag)) diff --git a/tests/apitests/python/library/sign.py b/tests/apitests/python/library/sign.py index 856b5bc58..679439dbb 100644 --- a/tests/apitests/python/library/sign.py +++ b/tests/apitests/python/library/sign.py @@ -5,7 +5,7 @@ from testutils import notary_url def sign_image(registry_ip, project_name, image, tag): try: ret = subprocess.check_output(["./tests/apitests/python/sign_image.sh", registry_ip, project_name, image, tag, notary_url], shell=False) - print "sign_image return: ", ret - except subprocess.CalledProcessError, exc: + print("sign_image return: ", ret) + except subprocess.CalledProcessError as exc: raise Exception("Failed to sign image error is {} {}.".format(exc.returncode, exc.output)) diff --git a/tests/apitests/python/library/system.py b/tests/apitests/python/library/system.py index d778255c1..a00d4bd7d 100644 --- a/tests/apitests/python/library/system.py +++ b/tests/apitests/python/library/system.py @@ -90,10 +90,10 @@ class System(base.Base): base._assert_status_code(expect_status_code, status_code) return data - def create_gc_schedule(self, schedule_type, cron = None, expect_status_code = 201, expect_response_body = None, **kwargs): + def create_gc_schedule(self, schedule_type, is_delete_untagged, cron = None, expect_status_code = 201, expect_response_body = None, **kwargs): client = self._get_client(**kwargs) - gc_parameters = {'delete_untagged':True} + gc_parameters = {'delete_untagged':is_delete_untagged} gc_schedule = swagger_client.AdminJobScheduleObj() gc_schedule.type = schedule_type @@ -142,8 +142,8 @@ class System(base.Base): scan_all_id = self.create_scan_all_schedule('Manual', **kwargs) return scan_all_id - def gc_now(self, **kwargs): - gc_id = self.create_gc_schedule('Manual', **kwargs) + def gc_now(self, is_delete_untagged=False, **kwargs): + gc_id = self.create_gc_schedule('Manual', is_delete_untagged, **kwargs) return gc_id def validate_gc_job_status(self, gc_id, expected_gc_status, **kwargs): @@ -177,13 +177,13 @@ class System(base.Base): def set_cve_whitelist(self, expires_at=None, expected_status_code=200, *cve_ids, **kwargs): client = self._get_client(**kwargs) cve_list = [swagger_client.CVEWhitelistItem(cve_id=c) for c in cve_ids] - whitelist = swagger_client.CVEWhitelist(expires_at=expires_at, items=cve_list) + whitelist = swagger_client.CVEWhitelist(expires_at=expires_at, items=cve_list) try: r = client.system_cve_whitelist_put_with_http_info(whitelist=whitelist, _preload_content=False) except Exception as e: base._assert_status_code(expected_status_code, e.status) else: - base._assert_status_code(expected_status_code, r[1]) + base._assert_status_code(expected_status_code, r.status) def get_cve_whitelist(self, **kwargs): client = self._get_client(**kwargs) diff --git a/tests/apitests/python/library/user.py b/tests/apitests/python/library/user.py index e577b4780..3be67cbf0 100644 --- a/tests/apitests/python/library/user.py +++ b/tests/apitests/python/library/user.py @@ -26,11 +26,11 @@ class User(base.Base): return base._get_id_from_header(header), name - def get_users(self, username=None, email=None, page=None, page_size=None, **kwargs): + def get_users(self, user_name=None, email=None, page=None, page_size=None, **kwargs): client = self._get_client(**kwargs) params={} - if username is not None: - params["username"] = username + if user_name is not None: + params["username"] = user_name if email is not None: params["email"] = email if page is not None: @@ -41,13 +41,19 @@ class User(base.Base): base._assert_status_code(200, status_code) return data - def get_user(self, user_id, **kwargs): + def get_user_by_id(self, user_id, **kwargs): client = self._get_client(**kwargs) data, status_code, _ = client.users_user_id_get_with_http_info(user_id) base._assert_status_code(200, status_code) - print "data in lib:", data return data + def get_user_by_name(self, name, **kwargs): + users = self.get_users(user_name=name, **kwargs) + for user in users: + if user.username == name: + return user + return None + def get_user_current(self, **kwargs): client = self._get_client(**kwargs) @@ -80,7 +86,6 @@ class User(base.Base): def update_user_role_as_sysadmin(self, user_id, IsAdmin, **kwargs): client = self._get_client(**kwargs) sysadmin_flag = swagger_client.SysAdminFlag(IsAdmin) - print "sysadmin_flag:", sysadmin_flag _, status_code, _ = client.users_user_id_sysadmin_put_with_http_info(user_id, sysadmin_flag) base._assert_status_code(200, status_code) return user_id diff --git a/tests/apitests/python/test_add_member_to_private_project.py b/tests/apitests/python/test_add_member_to_private_project.py index eb42a2c69..f33ce13a4 100644 --- a/tests/apitests/python/test_add_member_to_private_project.py +++ b/tests/apitests/python/test_add_member_to_private_project.py @@ -47,7 +47,7 @@ class TestProjects(unittest.TestCase): self.assertEqual(project_001_data, None, msg="user-001 should has no any private project, but we got {}".format(project_001_data)) #4. Add user-001 as a member of project-001 - result = self.project.add_project_members(project_001_id, user_001_id, **ADMIN_CLIENT) + result = self.project.add_project_members(project_001_id, user_id=user_001_id, **ADMIN_CLIENT) self.assertNotEqual(result, False, msg="Failed to add member user_001 to project_001, result is {}".format(result)) diff --git a/tests/apitests/python/test_add_replication_rule.py b/tests/apitests/python/test_add_replication_rule.py index 8ff14a8f3..eebe740cc 100644 --- a/tests/apitests/python/test_add_replication_rule.py +++ b/tests/apitests/python/test_add_replication_rule.py @@ -20,7 +20,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -69,7 +69,6 @@ class TestProjects(unittest.TestCase): #3. Create a new registry TestProjects.registry_id, _ = self.registry.create_registry("https://" + harbor_server,**ADMIN_CLIENT) - print "TestProjects.registry_id:", TestProjects.registry_id #4. Create a new rule for this registry; TestProjects.rule_id, rule_name = self.replication.create_replication_policy(dest_registry=swagger_client.Registry(id=int(TestProjects.registry_id)), **ADMIN_CLIENT) diff --git a/tests/apitests/python/test_add_sys_label_to_tag.py b/tests/apitests/python/test_add_sys_label_to_tag.py index f54a5804c..08d07a9f5 100644 --- a/tests/apitests/python/test_add_sys_label_to_tag.py +++ b/tests/apitests/python/test_add_sys_label_to_tag.py @@ -23,7 +23,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -69,7 +69,7 @@ class TestProjects(unittest.TestCase): TestProjects.project_add_g_lbl_id, TestProjects.project_add_g_lbl_name = self.project.create_project(metadata = {"public": "false"}, **ADMIN_CLIENT) #3. Add user-001 as a member of project-001 with project-admin role - self.project.add_project_members(TestProjects.project_add_g_lbl_id, TestProjects.user_add_g_lbl_id, **ADMIN_CLIENT) + self.project.add_project_members(TestProjects.project_add_g_lbl_id, user_id=TestProjects.user_add_g_lbl_id, **ADMIN_CLIENT) #4. Get private project of user(UA), user(UA) can see only one private project which is project(PA); self.project.projects_should_exist(dict(public=False), expected_count = 1, diff --git a/tests/apitests/python/test_assign_role_to_ldap_group.py b/tests/apitests/python/test_assign_role_to_ldap_group.py index 43cd1cc1f..c94d56823 100644 --- a/tests/apitests/python/test_assign_role_to_ldap_group.py +++ b/tests/apitests/python/test_assign_role_to_ldap_group.py @@ -1,180 +1,82 @@ -# 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 library.projectV2 import ProjectV2 -from testutils import ADMIN_CLIENT -from library.base import _assert_status_code - - -from v2_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") - repository_api = testutils.GetRepositoryApi("admin", "Harbor12345") - project_id = 0 - docker_client = docker.from_env() - - def setUp(self): - self.projectv2= ProjectV2() - - #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.repository_api.delete_repository("ldap_group_test_prj", "busybox") - pprint(result) - result = self.repository_api.delete_repository("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="test", password="123456", status_code=403)==0, "test user 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, status_code=200): - client=dict(endpoint = ADMIN_CLIENT["endpoint"], username = username, password = password) - try: - logs = self.projectv2.get_project_log("ldap_group_test_prj", status_code, **client) - count = 0 - for log in list(logs): - count = count + 1 - return count - except ApiException as e: - _assert_status_code(status_code, e.status) - return 0 - -if __name__ == '__main__': - unittest.main() +from __future__ import absolute_import +import unittest + +from testutils import harbor_server +from testutils import TEARDOWN +from testutils import ADMIN_CLIENT +from testutils import created_user, created_project +from library.project import Project +from library.user import User +from library.repository import Repository +from library.repository import push_image_to_project +from library.artifact import Artifact +from library.scanner import Scanner +from library.configurations import Configurations +from library.projectV2 import ProjectV2 + + +class TestAssignRoleToLdapGroup(unittest.TestCase): + @classmethod + def setUp(self): + self.conf= Configurations() + self.project = Project() + self.projectV2 = ProjectV2() + self.artifact = Artifact() + self.repo = Repository() + + @classmethod + def tearDown(self): + print("Case completed") + + def testAssignRoleToLdapGroup(self): + """ + Test case: + Assign Role To Ldap Group + Test step and expected result: + 1. Set LDAP Auth configurations; + 2. Create a new public project(PA) by Admin; + 3. Add 3 member groups to project(PA); + 4. Push image by each member role; + 5. Verfify that admin_user and dev_user can push image, guest_user can not push image; + 6. Verfify that admin_user, dev_user and guest_user can view logs, test user can not view logs. + 7. Delete repository(RA) by user(UA); + 8. Delete project(PA); + """ + url = ADMIN_CLIENT["endpoint"] + USER_ADMIN=dict(endpoint = url, username = "admin_user", password = "zhu88jie", repo = "hello-world") + USER_DEV=dict(endpoint = url, username = "dev_user", password = "zhu88jie", repo = "alpine") + USER_GUEST=dict(endpoint = url, username = "guest_user", password = "zhu88jie", repo = "busybox") + USER_TEST=dict(endpoint = url, username = "test", password = "123456") + + self.conf.set_configurations_of_ldap(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, **ADMIN_CLIENT) + + with created_project(metadata={"public": "false"}) as (project_id, project_name): + self.project.add_project_members(project_id, member_role_id = 1, _ldap_group_dn = "cn=harbor_admin,ou=groups,dc=example,dc=com", **ADMIN_CLIENT) + self.project.add_project_members(project_id, member_role_id = 2, _ldap_group_dn = "cn=harbor_dev,ou=groups,dc=example,dc=com", **ADMIN_CLIENT) + self.project.add_project_members(project_id, member_role_id = 3, _ldap_group_dn = "cn=harbor_guest,ou=groups,dc=example,dc=com", **ADMIN_CLIENT) + projects = self.project.get_projects(dict(name=project_name), **USER_ADMIN) + self.assertTrue(len(projects) == 1) + self.assertEqual(1, projects[0].current_user_role_id) + + repo_name_admin, _ = push_image_to_project(project_name, harbor_server, USER_ADMIN["username"], USER_ADMIN["password"], USER_ADMIN["repo"], "latest") + artifacts = self.artifact.list_artifacts(project_name, USER_ADMIN["repo"], **USER_ADMIN) + self.assertTrue(len(artifacts) == 1) + repo_name_dev, _ = push_image_to_project(project_name, harbor_server, USER_DEV["username"], USER_DEV["password"], USER_DEV["repo"], "latest") + artifacts = self.artifact.list_artifacts(project_name, USER_DEV["repo"], **USER_DEV) + self.assertTrue(len(artifacts) == 1) + push_image_to_project(project_name, harbor_server, USER_GUEST["username"], USER_GUEST["password"], USER_GUEST["repo"], "latest") + artifacts = self.artifact.list_artifacts(project_name, USER_GUEST["repo"], **USER_GUEST) + self.assertTrue(len(artifacts) == 0) + + + self.assertTrue(self.projectV2.query_user_logs(project_name, **USER_ADMIN)>0, "admin user can see logs") + self.assertTrue(self.projectV2.query_user_logs(project_name, **USER_DEV)>0, "dev user can see logs") + self.assertTrue(self.projectV2.query_user_logs(project_name, **USER_GUEST)>0, "guest user can see logs") + self.assertTrue(self.projectV2.query_user_logs(project_name, status_code=403, **USER_TEST)==0, "test user can not see any logs") + + self.repo.delete_repoitory(project_name, repo_name_admin.split('/')[1], **USER_ADMIN) + self.repo.delete_repoitory(project_name, repo_name_dev.split('/')[1], **USER_ADMIN) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/apitests/python/test_assign_sys_admin.py b/tests/apitests/python/test_assign_sys_admin.py index 431a66d63..7112ae20e 100644 --- a/tests/apitests/python/test_assign_sys_admin.py +++ b/tests/apitests/python/test_assign_sys_admin.py @@ -15,7 +15,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): diff --git a/tests/apitests/python/test_copy_artifact_outside_project.py b/tests/apitests/python/test_copy_artifact_outside_project.py index 7b481527a..ac061df6e 100644 --- a/tests/apitests/python/test_copy_artifact_outside_project.py +++ b/tests/apitests/python/test_copy_artifact_outside_project.py @@ -3,11 +3,10 @@ from __future__ import absolute_import import unittest -from library.base import _assert_status_code from testutils import ADMIN_CLIENT from testutils import harbor_server - from testutils import TEARDOWN +from library.base import _assert_status_code from library.artifact import Artifact from library.project import Project from library.user import User @@ -25,7 +24,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDownClass(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): diff --git a/tests/apitests/python/test_create_delete_tag.py b/tests/apitests/python/test_create_delete_tag.py index ca7624a17..40ced9e64 100644 --- a/tests/apitests/python/test_create_delete_tag.py +++ b/tests/apitests/python/test_create_delete_tag.py @@ -3,13 +3,12 @@ from __future__ import absolute_import import unittest +from testutils import ADMIN_CLIENT +from testutils import harbor_server +from testutils import TEARDOWN import library.repository import library.docker_api from library.base import _assert_status_code -from testutils import ADMIN_CLIENT -from testutils import harbor_server - -from testutils import TEARDOWN from library.project import Project from library.user import User from library.repository import Repository @@ -30,7 +29,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDownClass(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): diff --git a/tests/apitests/python/test_del_repo.py b/tests/apitests/python/test_del_repo.py index 6eed0af1a..dff8bf845 100644 --- a/tests/apitests/python/test_del_repo.py +++ b/tests/apitests/python/test_del_repo.py @@ -3,11 +3,10 @@ from __future__ import absolute_import import unittest -from library.base import _assert_status_code from testutils import ADMIN_CLIENT from testutils import harbor_server - from testutils import TEARDOWN +from library.base import _assert_status_code from library.project import Project from library.user import User from library.repository import Repository @@ -22,7 +21,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDownClass(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): diff --git a/tests/apitests/python/test_edit_project_creation.py b/tests/apitests/python/test_edit_project_creation.py index d15cda6eb..e4dc4e7f5 100644 --- a/tests/apitests/python/test_edit_project_creation.py +++ b/tests/apitests/python/test_edit_project_creation.py @@ -16,11 +16,10 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): - print "Clear trace" #1. Delete project(PA); self.project.delete_project(TestProjects.project_edit_project_creation_id, **TestProjects.USER_edit_project_creation_CLIENT) diff --git a/tests/apitests/python/test_garbage_collection.py b/tests/apitests/python/test_garbage_collection.py index 2ea0383aa..a453d80de 100644 --- a/tests/apitests/python/test_garbage_collection.py +++ b/tests/apitests/python/test_garbage_collection.py @@ -1,15 +1,16 @@ from __future__ import absolute_import import unittest +import time from testutils import ADMIN_CLIENT from testutils import TEARDOWN +from testutils import harbor_server from library.user import User from library.system import System from library.project import Project from library.repository import Repository from library.repository import push_image_to_project -from testutils import harbor_server from library.base import _assert_status_code from library.repository import push_special_image_to_project from library.artifact import Artifact @@ -28,7 +29,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == True, "Test data won't be erased.") def test_ClearData(self): @@ -81,6 +82,10 @@ class TestProjects(unittest.TestCase): repo_data = self.repo.list_repositories(TestProjects.project_gc_name, **TestProjects.USER_GC_CLIENT) _assert_status_code(len(repo_data), 0) + #8. Push a image in project(PB) by admin and delete the only tag; + push_special_image_to_project(TestProjects.project_gc_untag_name, harbor_server, admin_name, admin_password, self.repo_name_untag, [self.tag]) + self.artifact.delete_tag(TestProjects.project_gc_untag_name, self.repo_name_untag, self.tag, self.tag, **ADMIN_CLIENT) + #5. Tigger garbage collection operation; gc_id = self.system.gc_now(**ADMIN_CLIENT) @@ -90,19 +95,22 @@ class TestProjects(unittest.TestCase): #7. Get garbage collection log, check there is a number of files was deleted; self.system.validate_deletion_success(gc_id, **ADMIN_CLIENT) - #8. Push a image in project(PB) by admin and delete the only tag; - push_special_image_to_project(TestProjects.project_gc_untag_name, harbor_server, admin_name, admin_password, self.repo_name_untag, [self.tag]) - self.artifact.delete_tag(TestProjects.project_gc_untag_name, self.repo_name_untag, self.tag, self.tag, **ADMIN_CLIENT) + artifacts = self.artifact.list_artifacts(TestProjects.project_gc_untag_name, self.repo_name_untag, **TestProjects.USER_GC_CLIENT) + _assert_status_code(len(artifacts), 1) + + time.sleep(5) #9. Tigger garbage collection operation; - gc_id = self.system.gc_now(**ADMIN_CLIENT) + gc_id = self.system.gc_now(is_delete_untagged=True, **ADMIN_CLIENT) #10. Check garbage collection job was finished; self.system.validate_gc_job_status(gc_id, "finished", **ADMIN_CLIENT) + #7. Get garbage collection log, check there is a number of files was deleted; + self.system.validate_deletion_success(gc_id, **ADMIN_CLIENT) + #11. Repository with untag image should be still there; repo_data_untag = self.repo.list_repositories(TestProjects.project_gc_untag_name, **TestProjects.USER_GC_CLIENT) - print "repo_data_untag:", repo_data_untag _assert_status_code(len(repo_data_untag), 1) self.assertEqual(TestProjects.project_gc_untag_name + "/" + self.repo_name_untag , repo_data_untag[0].name) diff --git a/tests/apitests/python/test_ldap_admin_role.py b/tests/apitests/python/test_ldap_admin_role.py index 25b976828..f1ad2a4d9 100644 --- a/tests/apitests/python/test_ldap_admin_role.py +++ b/tests/apitests/python/test_ldap_admin_role.py @@ -1,68 +1,49 @@ -# 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.configurations import Configurations -from swagger_client.rest import ApiException -from swagger_client.models.configurations import Configurations -from pprint import pprint + +from testutils import harbor_server +from testutils import TEARDOWN +from testutils import ADMIN_CLIENT +from library.user import User +from library.project import Project +from library.configurations import Configurations -#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 + @classmethod def setUp(self): - pass + url = ADMIN_CLIENT["endpoint"] + self.conf= Configurations() + self.uesr = User() + self.project = Project() + self.USER_MIKE=dict(endpoint = url, username = "mike", password = "zhu88jie") + @classmethod def tearDown(self): - if self.project_id > 0 : - self.mike_product_api.projects_project_id_delete(project_id=self.project_id) - pass + self.project.delete_project(TestLdapAdminRole.project_id, **self.USER_MIKE) + print("Case completed") 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) + """ + Test case: + LDAP Admin Role + Test step and expected result: + 1. Set LDAP Auth configurations; + 2. Create a new public project(PA) by LDAP user mike; + 3. Check project is created successfully; + 4. Check mike is not admin; + 5. Delete project(PA); + """ - # 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 + self.conf.set_configurations_of_ldap(ldap_group_admin_dn="cn=harbor_users,ou=groups,dc=example,dc=com", **ADMIN_CLIENT) - # check the mike is not admin in Database - user_list = self.product_api.users_get(username="mike") - pprint(user_list[0]) - self.assertFalse(user_list[0].sysadmin_flag) + TestLdapAdminRole.project_id, project_name = self.project.create_project(metadata = {"public": "false"}, **self.USER_MIKE) + self.project.check_project_name_exist(name=project_name, **self.USER_MIKE) - pass + _user = self.uesr.get_user_by_name(self.USER_MIKE["username"], **ADMIN_CLIENT) + self.assertFalse(_user.sysadmin_flag) if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file diff --git a/tests/apitests/python/test_list_helm_charts.py b/tests/apitests/python/test_list_helm_charts.py index a8db08923..5b65226d5 100644 --- a/tests/apitests/python/test_list_helm_charts.py +++ b/tests/apitests/python/test_list_helm_charts.py @@ -17,7 +17,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): diff --git a/tests/apitests/python/test_manage_project_member.py b/tests/apitests/python/test_manage_project_member.py index 27bd25f01..0bde95351 100644 --- a/tests/apitests/python/test_manage_project_member.py +++ b/tests/apitests/python/test_manage_project_member.py @@ -19,7 +19,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -80,7 +80,7 @@ class TestProjects(unittest.TestCase): self.project.check_project_member_not_exist(TestProjects.project_alice_id, user_bob_name, **USER_ALICE_CLIENT) #4.1 Alice Add Bob as a guest member of project(PA) - member_id_bob = self.project.add_project_members(TestProjects.project_alice_id, TestProjects.user_bob_id, member_role_id = 3, **USER_ALICE_CLIENT) + member_id_bob = self.project.add_project_members(TestProjects.project_alice_id, user_id=TestProjects.user_bob_id, member_role_id = 3, **USER_ALICE_CLIENT) #4.2 Check Bob is a guest member of project(PA) self.project.check_project_members_exist(TestProjects.project_alice_id, user_bob_name, expected_member_role_id = 3, user_name = user_bob_name, user_password = user_bob_password, **USER_ALICE_CLIENT) diff --git a/tests/apitests/python/test_project_level_cve_whitelist.py b/tests/apitests/python/test_project_level_cve_whitelist.py index 64cdba696..17d56dc76 100644 --- a/tests/apitests/python/test_project_level_cve_whitelist.py +++ b/tests/apitests/python/test_project_level_cve_whitelist.py @@ -46,7 +46,7 @@ class TestProjectCVEWhitelist(unittest.TestCase): self.user_ra_id = int(user_ra_id) p_id, _ = self.project.create_project(metadata = {"public": "false"}, **ADMIN_CLIENT) self.project_pa_id = int(p_id) - m_id = self.project.add_project_members(self.project_pa_id, self.user_ra_id, member_role_id=3, **ADMIN_CLIENT) + m_id = self.project.add_project_members(self.project_pa_id, user_id=self.user_ra_id, member_role_id=3, **ADMIN_CLIENT) self.member_id = int(m_id) def tearDown(self): diff --git a/tests/apitests/python/test_project_level_policy_content_trust.py b/tests/apitests/python/test_project_level_policy_content_trust.py index d54574a1e..8de52e52a 100644 --- a/tests/apitests/python/test_project_level_policy_content_trust.py +++ b/tests/apitests/python/test_project_level_policy_content_trust.py @@ -4,7 +4,6 @@ import unittest from testutils import ADMIN_CLIENT from testutils import harbor_server - from testutils import TEARDOWN from library.artifact import Artifact from library.project import Project @@ -23,7 +22,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): diff --git a/tests/apitests/python/test_project_quota.py b/tests/apitests/python/test_project_quota.py index 508ba63cb..0cb4efea0 100644 --- a/tests/apitests/python/test_project_quota.py +++ b/tests/apitests/python/test_project_quota.py @@ -15,7 +15,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(cls): - print "Case completed" + print("Case completed") def testProjectQuota(self): """ diff --git a/tests/apitests/python/test_push_chart_by_helm2_helm3_with_robot_Account.py b/tests/apitests/python/test_push_chart_by_helm2_helm3_with_robot_Account.py index 0cb77f02b..a05c451aa 100644 --- a/tests/apitests/python/test_push_chart_by_helm2_helm3_with_robot_Account.py +++ b/tests/apitests/python/test_push_chart_by_helm2_helm3_with_robot_Account.py @@ -3,12 +3,11 @@ from __future__ import absolute_import import unittest -import library.repository -import library.helm from testutils import ADMIN_CLIENT, CHART_API_CLIENT from testutils import harbor_server - from testutils import TEARDOWN +import library.repository +import library.helm from library.project import Project from library.user import User from library.chart import Chart @@ -31,7 +30,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDownClass(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -52,30 +51,27 @@ class TestProjects(unittest.TestCase): 1. Delete user(UA). """ - print "#1. Create user(UA);" + #1. Create user(UA); TestProjects.user_id, user_name = self.user.create_user(user_password = self.user_push_chart_password, **ADMIN_CLIENT) TestProjects.USER_CLIENT=dict(endpoint = self.url, username = user_name, password = self.user_push_chart_password) TestProjects.API_CHART_CLIENT=dict(endpoint = self.chart_api_url, username = user_name, password = self.user_push_chart_password) - print "#2. Create private project(PA) with user(UA);" + #2. Create private project(PA) with user(UA); TestProjects.project_id, TestProjects.project_name = self.project.create_project(metadata = {"public": "false"}, **TestProjects.USER_CLIENT) - print "#3. Create a new robot account(RA) with full priviliges in project(PA) with user(UA);" + #3. Create a new robot account(RA) with full priviliges in project(PA) with user(UA); robot_id, robot_account = self.project.add_project_robot_account(TestProjects.project_id, TestProjects.project_name, 2441000531 ,**TestProjects.USER_CLIENT) - print robot_account.name - print robot_account.token - - print "#4. Push chart to project(PA) by Helm2 CLI with robot account(RA);" + #4. Push chart to project(PA) by Helm2 CLI with robot account(RA);" library.helm.helm2_add_repo(self.chart_repo_name, "https://"+harbor_server, TestProjects.project_name, robot_account.name, robot_account.token) library.helm.helm2_push(self.chart_repo_name, self.chart_file, TestProjects.project_name, robot_account.name, robot_account.token) - print "#5. Get chart repositry from project(PA) successfully;" + #5. Get chart repositry from project(PA) successfully; self.chart.chart_should_exist(TestProjects.project_name, self.CHART_NAME, **TestProjects.API_CHART_CLIENT) - print "#6. Push chart to project(PA) by Helm3 CLI with robot account(RA);" + #6. Push chart to project(PA) by Helm3 CLI with robot account(RA); chart_cli_ret = library.helm.helm_chart_push_to_harbor(self.chart_file, self.archive, harbor_server, TestProjects.project_name, self.repo_name, self.verion, robot_account.name, robot_account.token) - print "chart_cli_ret:", chart_cli_ret + if __name__ == '__main__': unittest.main() diff --git a/tests/apitests/python/test_push_chart_by_helm3_chart_cli.py b/tests/apitests/python/test_push_chart_by_helm3_chart_cli.py index 2e7c653f8..593053810 100644 --- a/tests/apitests/python/test_push_chart_by_helm3_chart_cli.py +++ b/tests/apitests/python/test_push_chart_by_helm3_chart_cli.py @@ -3,12 +3,11 @@ from __future__ import absolute_import import unittest -import library.repository -import library.helm from testutils import ADMIN_CLIENT from testutils import harbor_server - from testutils import TEARDOWN +import library.repository +import library.helm from library.project import Project from library.user import User from library.repository import Repository @@ -30,7 +29,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDownClass(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -69,7 +68,6 @@ class TestProjects(unittest.TestCase): #3. Push an chart(CA) to Harbor by helm3 registry/chart CLI successfully; chart_cli_ret = library.helm.helm_chart_push_to_harbor(self.chart_file, self.archive, harbor_server, TestProjects.project_push_chart_name, self.repo_name, self.verion, user_name, self.user_push_chart_password) - print "chart_cli_ret:", chart_cli_ret #4. List artifacts successfully; artifacts = self.artifact.list_artifacts(TestProjects.project_push_chart_name, self.repo_name, **TestProjects.USER_CLIENT) diff --git a/tests/apitests/python/test_push_cnab_bundle.py b/tests/apitests/python/test_push_cnab_bundle.py index 3a28c006a..38ae6f2e3 100644 --- a/tests/apitests/python/test_push_cnab_bundle.py +++ b/tests/apitests/python/test_push_cnab_bundle.py @@ -3,13 +3,11 @@ from __future__ import absolute_import import unittest -import library.repository -import library.cnab - from testutils import ADMIN_CLIENT from testutils import harbor_server - from testutils import TEARDOWN +import library.repository +import library.cnab from library.project import Project from library.user import User from library.repository import Repository @@ -30,7 +28,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDownClass(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -80,7 +78,6 @@ class TestProjects(unittest.TestCase): #5. Get repository from Harbor successfully; index_data = self.repo.get_repository(TestProjects.project_push_bundle_name, self.cnab_repo_name, **TestProjects.USER_CLIENT) - print "index_data:", index_data #5.2 Cnab bundle can be pulled by ctr successfully; # This step might not successful since ctr does't support cnab fully, it might be uncomment sometime in future. diff --git a/tests/apitests/python/test_push_files_by_oras.py b/tests/apitests/python/test_push_files_by_oras.py index 3d974fc11..0f004e6ea 100644 --- a/tests/apitests/python/test_push_files_by_oras.py +++ b/tests/apitests/python/test_push_files_by_oras.py @@ -2,11 +2,11 @@ from __future__ import absolute_import import unittest import urllib -import library.oras -from library.sign import sign_image from testutils import ADMIN_CLIENT from testutils import harbor_server from testutils import TEARDOWN +import library.oras +from library.sign import sign_image from library.user import User from library.project import Project from library.repository import Repository @@ -25,7 +25,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -60,21 +60,17 @@ class TestProjects(unittest.TestCase): #3. ORAS CLI push artifacts; md5_list_push = library.oras.oras_push(harbor_server, user_name, user_001_password, TestProjects.project_name, self.repo_name, self.tag) - print "md5_list_push:",md5_list_push #4. Get repository from Harbor successfully, and verfiy repository name is repo pushed by ORAS CLI; repo_data = self.repo.get_repository(TestProjects.project_name, self.repo_name, **TestProjects.USER_CLIENT) - print "repo_data:", repo_data self.assertEqual(repo_data.name, TestProjects.project_name + "/" + self.repo_name) #5. Get and verify artifacts by tag; artifact = self.artifact.get_reference_info(TestProjects.project_name, self.repo_name, self.tag, **TestProjects.USER_CLIENT) - print "artifact:", artifact self.assertEqual(artifact[0].tags[0].name, self.tag) #6. ORAS CLI pull artifacts index by tag; md5_list_pull = library.oras.oras_pull(harbor_server, user_name, user_001_password, TestProjects.project_name, self.repo_name, self.tag) - print "md5_list_pull:",md5_list_pull #7. Verfiy MD5 between artifacts pushed by ORAS and artifacts pulled by ORAS; if set(md5_list_push) != set(md5_list_pull): diff --git a/tests/apitests/python/test_push_image_with_special_name.py b/tests/apitests/python/test_push_image_with_special_name.py index 7077ed161..93c683e34 100644 --- a/tests/apitests/python/test_push_image_with_special_name.py +++ b/tests/apitests/python/test_push_image_with_special_name.py @@ -2,10 +2,10 @@ from __future__ import absolute_import import unittest import urllib -from library.sign import sign_image from testutils import ADMIN_CLIENT from testutils import harbor_server from testutils import TEARDOWN +from library.sign import sign_image from library.artifact import Artifact from library.project import Project from library.user import User @@ -22,7 +22,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -63,7 +63,7 @@ class TestProjects(unittest.TestCase): TestProjects.project_sign_image_id, TestProjects.project_sign_image_name = self.project.create_project(metadata = {"public": "false"}, **ADMIN_CLIENT) #3. Add user(UA) as a member of project(PA) with project-admin role; - self.project.add_project_members(TestProjects.project_sign_image_id, TestProjects.user_sign_image_id, **ADMIN_CLIENT) + self.project.add_project_members(TestProjects.project_sign_image_id, user_id=TestProjects.user_sign_image_id, **ADMIN_CLIENT) #4. Get private project of user(UA), user(UA) can see only one private project which is project(PA); self.project.projects_should_exist(dict(public=False), expected_count = 1, @@ -77,10 +77,9 @@ class TestProjects(unittest.TestCase): TestProjects.repo_name, tag = push_image_to_project(TestProjects.project_sign_image_name, harbor_server, user_sign_image_name, user_001_password, image, src_tag, profix_for_image=profix) #7. Get signature of image with tag(TA), it should be exist. - full_name = urllib.quote(profix+"/"+image,'utf-8') - artifact = self.artifact.get_reference_info(TestProjects.project_sign_image_name, (str(full_name)).encode(), tag, **TestProjects.USER_sign_image_CLIENT) + full_name = urllib.parse.quote(profix+"/"+image,'utf-8') - print artifact + artifact = self.artifact.get_reference_info(TestProjects.project_sign_image_name, full_name, tag, **TestProjects.USER_sign_image_CLIENT) self.assertEqual(artifact[0].type, 'IMAGE') if __name__ == '__main__': diff --git a/tests/apitests/python/test_push_index_by_docker_manifest.py b/tests/apitests/python/test_push_index_by_docker_manifest.py index 8e371bb86..e1d51a55b 100644 --- a/tests/apitests/python/test_push_index_by_docker_manifest.py +++ b/tests/apitests/python/test_push_index_by_docker_manifest.py @@ -3,14 +3,13 @@ from __future__ import absolute_import import unittest +from testutils import ADMIN_CLIENT +from testutils import harbor_server +from testutils import TEARDOWN import library.repository import library.docker_api import library.containerd from library.base import _assert_status_code -from testutils import ADMIN_CLIENT -from testutils import harbor_server - -from testutils import TEARDOWN from library.project import Project from library.user import User from library.repository import Repository @@ -34,7 +33,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDownClass(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): diff --git a/tests/apitests/python/test_push_sif_by_singularity.py b/tests/apitests/python/test_push_sif_by_singularity.py index ab67ebf61..cc2107a77 100644 --- a/tests/apitests/python/test_push_sif_by_singularity.py +++ b/tests/apitests/python/test_push_sif_by_singularity.py @@ -2,11 +2,11 @@ from __future__ import absolute_import import unittest import urllib -import library.singularity -from library.sign import sign_image from testutils import ADMIN_CLIENT from testutils import harbor_server from testutils import TEARDOWN +import library.singularity +from library.sign import sign_image from library.user import User from library.project import Project from library.repository import Repository @@ -25,7 +25,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -63,12 +63,10 @@ class TestProjects(unittest.TestCase): #4. Get repository from Harbor successfully, and verfiy repository name is repo pushed by singularity CLI; repo_data = self.repo.get_repository(TestProjects.project_name, self.repo_name, **TestProjects.USER_CLIENT) - print "repo_data:", repo_data self.assertEqual(repo_data.name, TestProjects.project_name + "/" + self.repo_name) #5. Get and verify artifacts by tag; artifact = self.artifact.get_reference_info(TestProjects.project_name, self.repo_name, self.tag, **TestProjects.USER_CLIENT) - print "artifact:", artifact self.assertEqual(artifact[0].tags[0].name, self.tag) #6. Pull sif file from harbor by singularity; diff --git a/tests/apitests/python/test_registry_api.py b/tests/apitests/python/test_registry_api.py index 40a8d9080..b4573c207 100644 --- a/tests/apitests/python/test_registry_api.py +++ b/tests/apitests/python/test_registry_api.py @@ -13,6 +13,8 @@ from library.repository import Repository from library.repository import push_image_to_project from library.artifact import Artifact from library.scanner import Scanner +from library.docker_api import list_image_tags +from library.docker_api import list_repositories import os import library.base import json @@ -29,7 +31,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -84,24 +86,24 @@ class TestProjects(unittest.TestCase): for tag in create_tags: self.artifact.create_tag(TestProjects.project_Alice_name, self.repo_name, tag_c, tag, **USER_ALICE_CLIENT) #4. Call the image_list_tags API - tags = library.docker_api.list_image_tags(harbor_server,TestProjects.repo_c,user_Alice_name,user_common_password) - for tag in create_tags: + tags = list_image_tags(harbor_server,TestProjects.repo_c,user_Alice_name,user_common_password) + for tag in create_tags: self.assertTrue(tags.count(tag)>0, "Expect tag: %s is not listed"%tag) - page_tags = library.docker_api.list_image_tags(harbor_server,TestProjects.repo_c,user_Alice_name,user_common_password,len(tags)/2+1) - page_tags += library.docker_api.list_image_tags(harbor_server,TestProjects.repo_c,user_Alice_name,user_common_password,len(tags)/2+1,tags[len(tags)/2]) - for tag in create_tags: + page_tags = list_image_tags(harbor_server,TestProjects.repo_c,user_Alice_name,user_common_password,len(tags)/2+1) + page_tags += list_image_tags(harbor_server,TestProjects.repo_c,user_Alice_name,user_common_password,len(tags)/2+1,tags[int(len(tags)/2)]) + for tag in create_tags: self.assertTrue(page_tags.count(tag)>0, "Expect tag: %s is not listed by the pagination query"%tag) #5. Call the catalog API; - repos = library.docker_api.list_repositories(harbor_server,admin_user,admin_pwd) - self.assertTrue(repos.count(TestProjects.repo_a)>0 and repos.count(TestProjects.repo_b)>0 and repos.count(TestProjects.repo_c)>0, "Expected repo not found") + repos = list_repositories(harbor_server,admin_user,admin_pwd) + self.assertTrue(repos.count(TestProjects.repo_a)>0 and repos.count(TestProjects.repo_b)>0 and repos.count(TestProjects.repo_c)>0, "Expected repo not found") for repo in [TestProjects.repo_a,TestProjects.repo_b,TestProjects.repo_c]: self.assertTrue(repos.count(repo)>0,"Expected repo: %s is not listed"%repo) - page_repos = library.docker_api.list_repositories(harbor_server,admin_user,admin_pwd,len(repos)/2+1) - page_repos += library.docker_api.list_repositories(harbor_server,admin_user,admin_pwd,len(repos)/2+1,repos[len(repos)/2]) + page_repos = list_repositories(harbor_server,admin_user,admin_pwd,len(repos)/2+1) + page_repos += list_repositories(harbor_server,admin_user,admin_pwd,len(repos)/2+1,repos[int(len(repos)/2)]) for repo in [TestProjects.repo_a,TestProjects.repo_b,TestProjects.repo_c]: self.assertTrue(page_repos.count(repo)>0,"Expected repo: %s is not listed by the pagination query"%repo) - null_repos = library.docker_api.list_repositories(harbor_server,user_Alice_name,user_common_password) + null_repos = list_repositories(harbor_server,user_Alice_name,user_common_password) self.assertEqual(null_repos, "") if __name__ == '__main__': diff --git a/tests/apitests/python/test_replication_from_dockerhub.py b/tests/apitests/python/test_replication_from_dockerhub.py index ae41e6947..29fd6c2c5 100644 --- a/tests/apitests/python/test_replication_from_dockerhub.py +++ b/tests/apitests/python/test_replication_from_dockerhub.py @@ -25,7 +25,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -80,7 +80,6 @@ class TestProjects(unittest.TestCase): #3. Create a new registry; TestProjects.registry_id, _ = self.registry.create_registry("https://hub.docker.com", registry_type="docker-hub", access_key = "", access_secret = "", insecure=False, **ADMIN_CLIENT) - print "TestProjects.registry_id:", TestProjects.registry_id #4. Create a pull-based rule for this registry; TestProjects.rule_id, rule_name = self.replication.create_replication_policy(src_registry=swagger_client.Registry(id=int(TestProjects.registry_id)), @@ -99,8 +98,6 @@ class TestProjects(unittest.TestCase): #8. Check image is replicated into target project successfully. artifact = self.artifact.get_reference_info(TestProjects.project_name, self.image, self.tag, **ADMIN_CLIENT) - print artifact - if __name__ == '__main__': unittest.main() diff --git a/tests/apitests/python/test_retention.py b/tests/apitests/python/test_retention.py index 7aad5c87f..4e9a491a9 100644 --- a/tests/apitests/python/test_retention.py +++ b/tests/apitests/python/test_retention.py @@ -8,7 +8,6 @@ from testutils import TEARDOWN from testutils import harbor_server from library.repository import push_special_image_to_project from library.docker_api import list_image_tags - from library.retention import Retention from library.project import Project from library.repository import Repository @@ -64,10 +63,8 @@ class TestProjects(unittest.TestCase): push_special_image_to_project(TestProjects.project_src_repo_name, harbor_server, user_ra_name, user_ra_password, "test4", ['1.0']) tag_data_artifact3_image1 = self.artifact.get_reference_info(TestProjects.project_src_repo_name, self.repo_name_1, "3.0", **TestProjects.USER_RA_CLIENT) - print tag_data_artifact3_image1[0].digest tag_data_artifact2_image2 = self.artifact.get_reference_info(TestProjects.project_src_repo_name, self.repo_name_2, "latest", **TestProjects.USER_RA_CLIENT) - print tag_data_artifact2_image2[0].digest tags = list_image_tags(harbor_server, TestProjects.project_src_repo_name+"/"+self.repo_name_1, user_ra_name, user_ra_password) #Delete all 2 tags of "artifact3" in repostory "image1"; @@ -114,19 +111,17 @@ class TestProjects(unittest.TestCase): #List artifacts successfully, and untagged artifact in test1 should be the only one retained; artifacts_1 = self.artifact.list_artifacts(TestProjects.project_src_repo_name, self.repo_name_1, **TestProjects.USER_RA_CLIENT) - print artifacts_1[0].digest self.assertTrue(len(artifacts_1)==1) self.assertEqual(artifacts_1[0].digest, tag_data_artifact3_image1[0].digest) #List artifacts successfully, and artifact with latest tag in test2 should be the only one retained; artifacts_2 = self.artifact.list_artifacts(TestProjects.project_src_repo_name, self.repo_name_2, **TestProjects.USER_RA_CLIENT) - print artifacts_2[0].digest self.assertTrue(len(artifacts_2)==1) self.assertEqual(artifacts_2[0].digest, tag_data_artifact2_image2[0].digest) @classmethod def tearDownClass(self): - print "Case completed" + print("Case completed") # TODO delete_repoitory will fail when no tags left anymore # @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") diff --git a/tests/apitests/python/test_robot_account.py b/tests/apitests/python/test_robot_account.py index 9c78abbbe..bbb9924f5 100644 --- a/tests/apitests/python/test_robot_account.py +++ b/tests/apitests/python/test_robot_account.py @@ -4,12 +4,12 @@ import unittest from testutils import ADMIN_CLIENT from testutils import TEARDOWN +from testutils import harbor_server 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): @@ -21,7 +21,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -74,58 +74,56 @@ class TestProjects(unittest.TestCase): image_robot_account = "alpine" tag = "latest" - print "#1. Create user(UA);" + #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);" + #2. Create private project(PA), private project(PB) and public project(PC) by user(UA); TestProjects.project_ra_id_a, TestProjects.project_ra_name_a = self.project.create_project(metadata = {"public": "false"}, **TestProjects.USER_RA_CLIENT) TestProjects.project_ra_id_b, TestProjects.project_ra_name_b = self.project.create_project(metadata = {"public": "false"}, **TestProjects.USER_RA_CLIENT) TestProjects.project_ra_id_c, TestProjects.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);" + #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(TestProjects.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(TestProjects.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(TestProjects.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);" + #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, TestProjects.project_ra_name_a, 2441000531 ,**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;" + #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;" + #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;" + #7. Push image(ImageRA) to project(PA) by robot account(RA), it must be successful; TestProjects.repo_name_pa, _ = push_image_to_project(TestProjects.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;" + #8. Push image(ImageRA) to project(PB) by robot account(RA), it must be not successful; push_image_to_project(TestProjects.project_ra_name_b, harbor_server, robot_account.name, robot_account.token, image_robot_account, tag, expected_error_message = "unauthorized to access repository") - print "#9. Pull image(ImagePB) from 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; pull_harbor_image(harbor_server, robot_account.name, robot_account.token, TestProjects.repo_name_in_project_b, tag_b, expected_error_message = "unauthorized to access repository") - print "#10. Pull image from project(PC), it must be successful;" + #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;" + #11. Push image(ImageRA) to project(PC) by robot account(RA), it must be not successful; push_image_to_project(TestProjects.project_ra_name_c, harbor_server, robot_account.name, robot_account.token, image_robot_account, tag, expected_error_message = "unauthorized to access repository") - print "#12. Update action property of robot account(RA);" + #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;" + #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_login_error_message = "unauthorized: authentication required") - print "#14. Push image(ImageRA) to 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; push_image_to_project(TestProjects.project_ra_name_a, harbor_server, robot_account.name, robot_account.token, image_robot_account, tag, expected_login_error_message = "unauthorized: authentication required") - print "#15. Delete robot account(RA), it must be not successful." + #15. Delete 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__': diff --git a/tests/apitests/python/test_scan_image_artifact.py b/tests/apitests/python/test_scan_image_artifact.py index 93e04c76d..15169c2a5 100644 --- a/tests/apitests/python/test_scan_image_artifact.py +++ b/tests/apitests/python/test_scan_image_artifact.py @@ -23,7 +23,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == True, "Test data won't be erased.") def test_ClearData(self): @@ -66,7 +66,7 @@ class TestProjects(unittest.TestCase): TestProjects.project_scan_image_id, TestProjects.project_scan_image_name = self.project.create_project(metadata = {"public": "false"}, **ADMIN_CLIENT) #3. Add user(UA) as a member of project(PA) with project-admin role; - self.project.add_project_members(TestProjects.project_scan_image_id, TestProjects.user_scan_image_id, **ADMIN_CLIENT) + self.project.add_project_members(TestProjects.project_scan_image_id, user_id=TestProjects.user_scan_image_id, **ADMIN_CLIENT) #4. Get private project of user(UA), user(UA) can see only one private project which is project(PA); self.project.projects_should_exist(dict(public=False), expected_count = 1, diff --git a/tests/apitests/python/test_sign_image.py b/tests/apitests/python/test_sign_image.py index caa3482dd..95f5b1aa8 100644 --- a/tests/apitests/python/test_sign_image.py +++ b/tests/apitests/python/test_sign_image.py @@ -1,10 +1,10 @@ from __future__ import absolute_import import unittest -from library.sign import sign_image from testutils import ADMIN_CLIENT from testutils import harbor_server from testutils import TEARDOWN +from library.sign import sign_image from library.artifact import Artifact from library.project import Project from library.user import User @@ -23,7 +23,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): @@ -64,7 +64,7 @@ class TestProjects(unittest.TestCase): TestProjects.project_sign_image_id, TestProjects.project_sign_image_name = self.project.create_project(metadata = {"public": "false"}, **ADMIN_CLIENT) #3. Add user(UA) as a member of project(PA) with project-admin role; - self.project.add_project_members(TestProjects.project_sign_image_id, TestProjects.user_sign_image_id, **ADMIN_CLIENT) + self.project.add_project_members(TestProjects.project_sign_image_id, user_id=TestProjects.user_sign_image_id, **ADMIN_CLIENT) #4. Get private project of user(UA), user(UA) can see only one private project which is project(PA); self.project.projects_should_exist(dict(public=False), expected_count = 1, diff --git a/tests/apitests/python/test_system_level_scan_all.py b/tests/apitests/python/test_system_level_scan_all.py index 20c15782b..030b30440 100644 --- a/tests/apitests/python/test_system_level_scan_all.py +++ b/tests/apitests/python/test_system_level_scan_all.py @@ -24,7 +24,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): diff --git a/tests/apitests/python/test_user_group.py b/tests/apitests/python/test_user_group.py index e2e2e84d0..f727cd0ad 100644 --- a/tests/apitests/python/test_user_group.py +++ b/tests/apitests/python/test_user_group.py @@ -3,10 +3,10 @@ """ Harbor API - These APIs provide services for manipulating Harbor project. + These APIs provide services for manipulating Harbor project. OpenAPI spec version: 1.4.0 - + Generated by: https://github.com/swagger-api/swagger-codegen.git """ @@ -22,8 +22,8 @@ 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 swagger_client.models.user_group import UserGroup +from swagger_client.models.configurations import Configurations from pprint import pprint #Testcase @@ -37,7 +37,7 @@ class TestUserGroup(unittest.TestCase): 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) + pprint(result) pass def tearDown(self): @@ -50,10 +50,10 @@ class TestUserGroup(unittest.TestCase): 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 diff --git a/tests/apitests/python/test_user_view_logs.py b/tests/apitests/python/test_user_view_logs.py index 777b0c97b..d25bc5628 100644 --- a/tests/apitests/python/test_user_view_logs.py +++ b/tests/apitests/python/test_user_view_logs.py @@ -34,7 +34,7 @@ class TestProjects(unittest.TestCase): @classmethod def tearDown(self): self.test_result.get_final_result() - print "Case completed" + print("Case completed") @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") def test_ClearData(self): diff --git a/tests/apitests/python/testutils.py b/tests/apitests/python/testutils.py index 3ee4e222b..b3a56b9f9 100644 --- a/tests/apitests/python/testutils.py +++ b/tests/apitests/python/testutils.py @@ -3,6 +3,13 @@ import os import sys sys.path.insert(0, os.environ["SWAGGER_CLIENT_PATH"]) +path=os.getcwd() + "/library" +sys.path.insert(0, path) + + +path=os.getcwd() + "/tests/apitests/python/library" +sys.path.insert(0, path) + import v2_swagger_client from swagger_client.rest import ApiException import swagger_client.models @@ -53,7 +60,7 @@ class TestResult(object): def get_final_result(self): if self.num_errors > 0: for each_err_msg in self.error_message: - print "Error message:", each_err_msg + print("Error message:", each_err_msg) raise Exception(r"Test case failed with {} errors.".format(self.num_errors)) from contextlib import contextmanager @@ -79,7 +86,7 @@ def created_project(name=None, metadata=None, user_id=None, member_role_id=None) project_id, project_name = api.create_project(name=name, metadata=metadata, **ADMIN_CLIENT) if user_id: - api.add_project_members(project_id, user_id, member_role_id=member_role_id, **ADMIN_CLIENT) + api.add_project_members(project_id, user_id=user_id, member_role_id=member_role_id, **ADMIN_CLIENT) try: yield (project_id, project_name) diff --git a/tests/ci/api_common_install.sh b/tests/ci/api_common_install.sh index f962bdc85..66ae75f20 100755 --- a/tests/ci/api_common_install.sh +++ b/tests/ci/api_common_install.sh @@ -25,7 +25,7 @@ fi sudo curl -o $DIR/../../tests/apitests/python/mariadb-4.3.1.tgz https://storage.googleapis.com/harbor-builds/bin/charts/mariadb-4.3.1.tgz sudo apt-get update && sudo apt-get install -y --no-install-recommends python-dev openjdk-7-jdk libssl-dev && sudo apt-get autoremove -y && sudo rm -rf /var/lib/apt/lists/* -sudo wget https://bootstrap.pypa.io/get-pip.py && sudo python ./get-pip.py && sudo pip install --ignore-installed urllib3 chardet requests && sudo pip install robotframework==3.0.4 robotframework-httplibrary requests dbbot robotframework-pabot --upgrade +sudo wget https://bootstrap.pypa.io/get-pip.py && sudo python ./get-pip.py && sudo pip install --ignore-installed urllib3 chardet requests && sudo pip install robotframework==3.2.1 robotframework-httplibrary requests --upgrade sudo make swagger_client if [ $GITHUB_TOKEN ]; then @@ -38,4 +38,5 @@ for((i=1;i<=30;i++)); do echo $i waiting 10 seconds... sleep 10 curl -k -L -f 127.0.0.1/api/v2.0/systeminfo && break -done \ No newline at end of file + docker ps +done diff --git a/tests/ci/api_run.sh b/tests/ci/api_run.sh index 149448d6a..33ad774bf 100755 --- a/tests/ci/api_run.sh +++ b/tests/ci/api_run.sh @@ -30,7 +30,7 @@ set +e docker ps # run db auth api cases if [ "$1" = 'DB' ]; then - pybot -X -v ip:$2 -v HARBOR_PASSWORD:Harbor12345 $DIR/../../tests/robot-cases/Group0-BAT/API_DB.robot + robot -X -v ip:$2 -v HARBOR_PASSWORD:Harbor12345 $DIR/../../tests/robot-cases/Group0-BAT/API_DB.robot elif [ "$1" = 'LDAP' ]; then # run ldap api cases python $DIR/../../tests/configharbor.py -H $IP -u $HARBOR_ADMIN -p $HARBOR_ADMIN_PASSWD -c auth_mode=ldap_auth \ @@ -39,7 +39,7 @@ elif [ "$1" = 'LDAP' ]; then ldap_search_password=admin \ ldap_base_dn=dc=example,dc=com \ ldap_uid=cn - pybot -X -v ip:$2 -v HARBOR_PASSWORD:Harbor12345 $DIR/../../tests/robot-cases/Group0-BAT/API_LDAP.robot + robot -X -v ip:$2 -v HARBOR_PASSWORD:Harbor12345 $DIR/../../tests/robot-cases/Group0-BAT/API_LDAP.robot else rc=999 fi diff --git a/tests/resources/Docker-Util.robot b/tests/resources/Docker-Util.robot index 5cc63e9b1..3b75d3ca6 100644 --- a/tests/resources/Docker-Util.robot +++ b/tests/resources/Docker-Util.robot @@ -36,21 +36,25 @@ Pull image Should Not Contain ${output} No such image: Push image - [Arguments] ${ip} ${user} ${pwd} ${project} ${image} ${sha256}=${null} ${is_robot}=${false} - ${image_with_sha256}= Set Variable If '${sha256}'=='${null}' ${image} ${image}@sha256:${sha256} - ${image_with_tag}= Set Variable If '${sha256}'=='${null}' ${image} ${image}:${sha256} + # If no tag provided in $(image_with_or_without_tag}, latest will be the tag pulled from docker-hub or read from local + [Arguments] ${ip} ${user} ${pwd} ${project} ${image_with_or_without_tag} ${need_pull_first}=${true} ${sha256}=${null} ${is_robot}=${false} + ${d}= Get Current Date result_format=%m%s + ${image_in_use}= Set Variable If '${sha256}'=='${null}' ${image_with_or_without_tag} ${image_with_or_without_tag}@sha256:${sha256} + ${image_in_use_with_tag}= Set Variable If '${sha256}'=='${null}' ${image_with_or_without_tag} ${image_with_or_without_tag}:${sha256} Sleep 3 - Log To Console \nRunning docker push ${image}... - Docker Pull ${LOCAL_REGISTRY}/${LOCAL_REGISTRY_NAMESPACE}/${image_with_sha256} + Log To Console \nRunning docker push ${image_with_or_without_tag}... + ${image_in_use}= Set Variable If ${need_pull_first}==${true} ${image_in_use} ${image_with_or_without_tag} + Run Keyword If ${need_pull_first}==${true} Docker Pull ${LOCAL_REGISTRY}/${LOCAL_REGISTRY_NAMESPACE}/${image_in_use} Run Keyword If ${is_robot}==${false} Wait Unitl Command Success docker login -u ${user} -p ${pwd} ${ip} ... ELSE Wait Unitl Command Success docker login -u robot\\\$${user} -p ${pwd} ${ip} - Wait Unitl Command Success docker tag ${LOCAL_REGISTRY}/${LOCAL_REGISTRY_NAMESPACE}/${image_with_sha256} ${ip}/${project}/${image_with_tag} - Wait Unitl Command Success docker push ${ip}/${project}/${image_with_tag} + Run Keyword If ${need_pull_first}==${true} Wait Unitl Command Success docker tag ${LOCAL_REGISTRY}/${LOCAL_REGISTRY_NAMESPACE}/${image_in_use} ${ip}/${project}/${image_in_use_with_tag} + ... ELSE Wait Unitl Command Success docker tag ${image_in_use} ${ip}/${project}/${image_in_use_with_tag} + Wait Unitl Command Success docker push ${ip}/${project}/${image_in_use_with_tag} Wait Unitl Command Success docker logout ${ip} Sleep 1 Push Image With Tag -#tag1 is tag of image on docker hub,default latest,use a version existing if you do not want to use latest +#tag1 is tag of image on docker hub,default latest,use a existed version if you do not want to use latest [Arguments] ${ip} ${user} ${pwd} ${project} ${image} ${tag} ${tag1}=latest Log To Console \nRunning docker push ${image}... Docker Pull ${LOCAL_REGISTRY}/${LOCAL_REGISTRY_NAMESPACE}/${image}:${tag1} @@ -67,10 +71,11 @@ Cannot Pull Image [Arguments] ${ip} ${user} ${pwd} ${project} ${image} ${tag}=${null} ${err_msg}=${null} ${image_with_tag}= Set Variable If '${tag}'=='${null}' ${image} ${image}:${tag} Wait Unitl Command Success docker login -u ${user} -p ${pwd} ${ip} - :FOR ${idx} IN RANGE 0 30 - \ ${out} Run Keyword And Ignore Error Command Should be Failed docker pull ${ip}/${project}/${image_with_tag} - \ Exit For Loop If '${out[0]}'=='PASS' - \ Sleep 3 + FOR ${idx} IN RANGE 0 30 + ${out} Run Keyword And Ignore Error Command Should be Failed docker pull ${ip}/${project}/${image_with_tag} + Exit For Loop If '${out[0]}'=='PASS' + Sleep 3 + END Log To Console Cannot Pull Image - Pull Log: ${out[1]} Should Be Equal As Strings '${out[0]}' 'PASS' Run Keyword If '${err_msg}' != '${null}' Should Contain ${out[1]} ${err_msg} @@ -89,17 +94,19 @@ Cannot Push image Wait Unitl Command Success docker login -u ${user} -p ${pwd} ${ip} Wait Unitl Command Success docker tag ${LOCAL_REGISTRY}/${LOCAL_REGISTRY_NAMESPACE}/${image} ${ip}/${project}/${image} ${output}= Command Should be Failed docker push ${ip}/${project}/${image} + Log To Console ${output} Run Keyword If '${err_msg}' != '${null}' Should Contain ${output} ${err_msg} Run Keyword If '${err_msg_2}' != '${null}' Should Contain ${output} ${err_msg_2} Wait Unitl Command Success docker logout ${ip} Wait Until Container Stops [Arguments] ${container} - :FOR ${idx} IN RANGE 0 60 - \ ${out}= Run docker %{VCH-PARAMS} inspect ${container} | grep Status - \ ${status}= Run Keyword And Return Status Should Contain ${out} exited - \ Return From Keyword If ${status} - \ Sleep 1 + FOR ${idx} IN RANGE 0 60 + ${out}= Run docker %{VCH-PARAMS} inspect ${container} | grep Status + ${status}= Run Keyword And Return Status Should Contain ${out} exited + Return From Keyword If ${status} + Sleep 1 + END Fail Container did not stop within 60 seconds Hit Nginx Endpoint @@ -123,10 +130,11 @@ Start Docker Daemon Locally OperatingSystem.File Should Exist /usr/local/bin/dockerd-entrypoint.sh ${handle}= Start Process /usr/local/bin/dockerd-entrypoint.sh dockerd>./daemon-local.log 2>&1 shell=True Process Should Be Running ${handle} - :FOR ${IDX} IN RANGE 5 - \ ${pid}= Run pidof dockerd - \ Exit For Loop If '${pid}' != '${EMPTY}' - \ Sleep 2s + FOR ${IDX} IN RANGE 5 + ${pid}= Run pidof dockerd + Exit For Loop If '${pid}' != '${EMPTY}' + Sleep 2s + END Sleep 2s [Return] ${handle} @@ -158,7 +166,7 @@ Docker Pull [Arguments] ${image} ${output}= Retry Keyword N Times When Error 10 Wait Unitl Command Success docker pull ${image} Log ${output} - Log To Console Docker Pull: \n ${output} + Log To Console Docker Pull: ${output} [Return] ${output} Docker Tag @@ -174,3 +182,25 @@ Docker Push Index ${rc} ${output}= Run And Return Rc And Output ./tests/robot-cases/Group0-Util/docker_push_manifest_list.sh ${ip} ${user} ${pwd} ${index} ${image1} ${image2} Log ${output} Should Be Equal As Integers ${rc} 0 + +Docker Image Can Not Be Pulled + [Arguments] ${image} + FOR ${idx} IN RANGE 0 30 + ${out}= Run Keyword And Ignore Error Command Should be Failed docker pull ${image} + Exit For Loop If '${out[0]}'=='PASS' + Sleep 3 + END + Log To Console Cannot Pull Image From Docker - Pull Log: ${out[1]} + Should Be Equal As Strings '${out[0]}' 'PASS' + +Docker Image Can Be Pulled + [Arguments] ${image} ${period}=60 ${times}=10 + FOR ${n} IN RANGE 1 ${times} + Sleep ${period} + ${out}= Run Keyword And Ignore Error Docker Pull ${image} + Log To Console Return value is ${out[0]} + Exit For Loop If '${out[0]}'=='PASS' + Sleep 5 + END + Run Keyword If '${out[0]}'=='FAIL' Capture Page Screenshot + Should Be Equal As Strings '${out[0]}' 'PASS' \ No newline at end of file diff --git a/tests/resources/Github-Util.robot b/tests/resources/Github-Util.robot index 1ee6a7644..edeefff9b 100644 --- a/tests/resources/Github-Util.robot +++ b/tests/resources/Github-Util.robot @@ -19,10 +19,11 @@ Documentation This resource provides keywords to interact with Github Get State Of Github Issue [Arguments] ${num} [Tags] secret - :FOR ${idx} IN RANGE 0 5 - \ ${status} ${result}= Run Keyword And Ignore Error Get https://api.github.com/repos/vmware/vic/issues/${num}?access_token\=%{GITHUB_AUTOMATION_API_KEY} - \ Exit For Loop If '${status}' - \ Sleep 1 + FOR ${idx} IN RANGE 0 5 + ${status} ${result}= Run Keyword And Ignore Error Get https://api.github.com/repos/vmware/vic/issues/${num}?access_token\=%{GITHUB_AUTOMATION_API_KEY} + Exit For Loop If '${status}' + Sleep 1 + END Should Be Equal ${result.status_code} ${200} ${status}= Get From Dictionary ${result.json()} state [Return] ${status} diff --git a/tests/resources/Harbor-Pages/Configuration.robot b/tests/resources/Harbor-Pages/Configuration.robot index 49962969c..05fe8439b 100644 --- a/tests/resources/Harbor-Pages/Configuration.robot +++ b/tests/resources/Harbor-Pages/Configuration.robot @@ -325,8 +325,9 @@ Add Items To System CVE Whitelist Delete Top Item In System CVE Whitelist [Arguments] ${count}=1 - :FOR ${idx} IN RANGE 1 ${count} - \ Retry Element Click ${configuration_system_wl_delete_a_cve_id_icon} + FOR ${idx} IN RANGE 1 ${count} + Retry Element Click ${configuration_system_wl_delete_a_cve_id_icon} + END Retry Element Click ${config_system_save_button_xpath} Get Project Count Quota Text From Project Quotas List diff --git a/tests/resources/Harbor-Pages/Project-Helmcharts.robot b/tests/resources/Harbor-Pages/Project-Helmcharts.robot index 74ac151ae..e2b84b8a6 100644 --- a/tests/resources/Harbor-Pages/Project-Helmcharts.robot +++ b/tests/resources/Harbor-Pages/Project-Helmcharts.robot @@ -43,8 +43,9 @@ Go Into Chart Detail Multi-delete Chart Files [Arguments] @{obj} Switch To Project Charts - :For ${obj} in @{obj} - \ Retry Element Click //clr-dg-row[contains(.,'${obj}')]//label + FOR ${obj} IN @{obj} + Retry Element Click //clr-dg-row[contains(.,'${obj}')]//label + END #Retry Element Click xpath=${version_checkbox} Capture Page Screenshot Retry Double Keywords When Error Retry Element Click xpath=${version_delete} Retry Wait Until Page Contains Element ${version_confirm_delete} diff --git a/tests/resources/Harbor-Pages/Project-Repository.robot b/tests/resources/Harbor-Pages/Project-Repository.robot index 51717d6a4..862a69821 100644 --- a/tests/resources/Harbor-Pages/Project-Repository.robot +++ b/tests/resources/Harbor-Pages/Project-Repository.robot @@ -21,8 +21,9 @@ View Repo Scan Details [Arguments] @{vulnerabilities_level} Retry Element Click xpath=${first_repo_xpath} Capture Page Screenshot - :FOR ${item} IN @{vulnerabilities_level} - \ Retry Wait Until Page Contains Element //hbr-artifact-vulnerabilities//clr-dg-row[contains(.,'${item}')] + FOR ${item} IN @{vulnerabilities_level} + Retry Wait Until Page Contains Element //hbr-artifact-vulnerabilities//clr-dg-row[contains(.,'${item}')] + END Retry Element Click xpath=${build_history_btn} Retry Wait Until Page Contains Element xpath=${build_history_data} diff --git a/tests/resources/Harbor-Pages/Project-Tag-Retention.robot b/tests/resources/Harbor-Pages/Project-Tag-Retention.robot index 1bd2d6051..046944fed 100644 --- a/tests/resources/Harbor-Pages/Project-Tag-Retention.robot +++ b/tests/resources/Harbor-Pages/Project-Tag-Retention.robot @@ -81,10 +81,11 @@ Set Daily Schedule Execute Result Should Be [Arguments] ${result} - :FOR ${idx} IN RANGE 0 20 - \ ${out} Run Keyword And Ignore Error Retry Wait Until Page Contains Element xpath=//clr-dg-cell[contains(., '${result}')] - \ Exit For Loop If '${out[0]}'=='PASS' - \ Sleep 6 + FOR ${idx} IN RANGE 0 20 + ${out} Run Keyword And Ignore Error Retry Wait Until Page Contains Element xpath=//clr-dg-cell[contains(., '${result}')] + Exit For Loop If '${out[0]}'=='PASS' + Sleep 6 + END Should Be Equal As Strings '${out[0]}' 'PASS' Execute Dry Run diff --git a/tests/resources/Harbor-Pages/Project.robot b/tests/resources/Harbor-Pages/Project.robot index d15720eb0..bc6777248 100644 --- a/tests/resources/Harbor-Pages/Project.robot +++ b/tests/resources/Harbor-Pages/Project.robot @@ -198,14 +198,16 @@ Do Log Advanced Search Retry Click Repo Name [Arguments] ${repo_name_element} - :For ${n} IN RANGE 1 10 - \ ${out} Run Keyword And Ignore Error Retry Double Keywords When Error Retry Element Click ${repo_name_element} Retry Wait Element ${tag_table_column_vulnerabilities} - \ Exit For Loop If '${out[0]}'=='PASS' + FOR ${n} IN RANGE 1 10 + ${out} Run Keyword And Ignore Error Retry Double Keywords When Error Retry Element Click ${repo_name_element} Retry Wait Element ${tag_table_column_vulnerabilities} + Exit For Loop If '${out[0]}'=='PASS' + END Should Be Equal As Strings '${out[0]}' 'PASS' - :For ${n} IN RANGE 1 10 - \ ${out} Run Keyword And Ignore Error Retry Wait Until Page Not Contains Element ${repo_list_spinner} - \ Exit For Loop If '${out[0]}'=='PASS' + FOR ${n} IN RANGE 1 10 + ${out} Run Keyword And Ignore Error Retry Wait Until Page Not Contains Element ${repo_list_spinner} + Exit For Loop If '${out[0]}'=='PASS' + END Should Be Equal As Strings '${out[0]}' 'PASS' Go Into Repo @@ -214,15 +216,16 @@ Go Into Repo Retry Wait Until Page Not Contains Element ${repo_list_spinner} ${repo_name_element}= Set Variable xpath=//clr-dg-cell[contains(.,'${repoName}')]/a Retry Element Click ${repo_search_icon} - :For ${n} IN RANGE 1 10 - \ Retry Clear Element Text ${repo_search_input} - \ Retry Text Input ${repo_search_input} ${repoName} - \ ${out} Run Keyword And Ignore Error Retry Wait Until Page Contains Element ${repo_name_element} - \ Sleep 2 - \ Continue For Loop If '${out[0]}'=='FAIL' - \ ${out} Retry Click Repo Name ${repo_name_element} - \ Sleep 2 - \ Exit For Loop + FOR ${n} IN RANGE 1 10 + Retry Clear Element Text ${repo_search_input} + Retry Text Input ${repo_search_input} ${repoName} + ${out} Run Keyword And Ignore Error Retry Wait Until Page Contains Element ${repo_name_element} + Sleep 2 + Continue For Loop If '${out[0]}'=='FAIL' + ${out} Retry Click Repo Name ${repo_name_element} + Sleep 2 + Exit For Loop + END Click Index Achieve @@ -232,11 +235,12 @@ Click Index Achieve Go Into Index And Contain Artifacts [Arguments] ${tag_name} ${limit}=3 Retry Double Keywords When Error Click Index Achieve ${tag_name} Page Should Contain Element ${tag_table_column_os_arch} - :For ${n} IN RANGE 1 10 - \ ${out} Run Keyword And Ignore Error Page Should Contain Element ${artifact_rows} limit=${limit} - \ Exit For Loop If '${out[0]}'=='PASS' - \ Capture Page Screenshot gointo_${tag_name}.png - \ Sleep 3 + FOR ${n} IN RANGE 1 10 + ${out} Run Keyword And Ignore Error Page Should Contain Element ${artifact_rows} limit=${limit} + Exit For Loop If '${out[0]}'=='PASS' + Capture Page Screenshot gointo_${tag_name}.png + Sleep 3 + END Run Keyword If '${out[0]}'=='FAIL' Capture Page Screenshot Should Be Equal As Strings '${out[0]}' 'PASS' diff --git a/tests/resources/Harbor-Pages/Replication.robot b/tests/resources/Harbor-Pages/Replication.robot index 56e0634e5..d637e7f98 100644 --- a/tests/resources/Harbor-Pages/Replication.robot +++ b/tests/resources/Harbor-Pages/Replication.robot @@ -19,7 +19,7 @@ Resource ../../resources/Util.robot *** Variables *** *** Keywords *** -Filter Replicatin Rule +Filter Replication Rule [Arguments] ${ruleName} ${rule_name_element}= Set Variable xpath=//clr-dg-cell[contains(.,'${ruleName}')] Retry Element Click ${filter_rules_btn} @@ -27,6 +27,16 @@ Filter Replicatin Rule Retry Wait Until Page Contains Element ${rule_name_element} Capture Page Screenshot filter_replic_${ruleName}.png +Filter Registry + [Arguments] ${registry_name} + ${registry_name_element}= Set Variable xpath=//clr-dg-cell[contains(.,'${registry_name}')] + Switch To Replication Manage + Switch To Registries + Retry Element Click ${filter_registry_btn} + Retry Text Input ${filter_registry_input} ${registry_name} + Retry Wait Until Page Contains Element ${registry_name_element} + Capture Page Screenshot filter_repistry_${registry_name}.png + Select Dest Registry [Arguments] ${endpoint} Retry Element Click ${dest_registry_dropdown_list} @@ -68,27 +78,28 @@ Create A New Endpoint #cancel verify cert since we use a selfsigned cert Retry Element Click ${destination_insecure_xpath} Run Keyword If '${save}' == 'Y' Run keyword Retry Double Keywords When Error Retry Element Click ${replication_save_xpath} Retry Wait Until Page Not Contains Element ${replication_save_xpath} - Run Keyword If '${save}' == 'Y' Run keyword Retry Wait Until Page Contains ${name} + Run Keyword If '${save}' == 'Y' Run keyword Filter Registry ${name} Run Keyword If '${save}' == 'N' No Operation Create A Rule With Existing Endpoint - [Arguments] ${name} ${replication_mode} ${project_name} ${resource_type} ${endpoint} ${dest_namespace} - ... ${mode}=Manual ${cron}="* */59 * * * *" + [Arguments] ${name} ${replication_mode} ${filter_project_name} ${resource_type} ${endpoint} ${dest_namespace} + ... ${mode}=Manual ${cron}="* */59 * * * *" ${del_remote}=${false} ${filter_tag}=${false} #click new Retry Element Click ${new_name_xpath} #input name Retry Text Input ${rule_name} ${name} - Run Keyword If '${replication_mode}' == 'push' Run Keywords Retry Element Click ${replication_mode_radio_push} - ... AND Select Dest Registry ${endpoint} - ... ELSE Run Keywords Retry Element Click ${replication_mode_radio_pull} - ... AND Select Source Registry ${endpoint} + Run Keyword If '${replication_mode}' == 'push' Run Keywords Retry Element Click ${replication_mode_radio_push} AND Select Dest Registry ${endpoint} + ... ELSE Run Keywords Retry Element Click ${replication_mode_radio_pull} AND Select Source Registry ${endpoint} + #set filter - Retry Text Input ${source_project} ${project_name} + Retry Text Input ${filter_name_id} ${filter_project_name} + Run Keyword If '${filter_tag}' != '${false}' Retry Text Input ${filter_tag_id} ${filter_tag} Run Keyword And Ignore Error Select From List By Value ${rule_resource_selector} ${resource_type} Retry Text Input ${dest_namespace_xpath} ${dest_namespace} #set trigger Select Trigger ${mode} - Run Keyword If '${mode}' == 'Scheduled' Retry Text Input ${targetCron_id} ${cron} + Run Keyword If '${mode}' == 'Scheduled' Retry Text Input ${targetCron_id} ${cron} + Run Keyword If '${mode}' == 'Event Based' and '${del_remote}' == '${true}' Retry Element Click ${del_remote_checkbox} #click save Retry Double Keywords When Error Retry Element Click ${rule_save_button} Retry Wait Until Page Not Contains Element ${rule_save_button} Sleep 2 @@ -225,7 +236,7 @@ Delete Endpoint Select Rule And Replicate [Arguments] ${rule_name} - Retry Element Click //hbr-list-replication-rule//clr-dg-cell[contains(.,'${rule_name}')] + Select Rule ${rule_name} Retry Element Click ${replication_exec_id} Retry Double Keywords When Error Retry Element Click xpath=${dialog_replicate} Retry Wait Until Page Not Contains Element xpath=${dialog_replicate} @@ -245,15 +256,25 @@ Delete Replication Rule Retry Element Click ${dialog_delete} Image Should Be Replicated To Project - [Arguments] ${project} ${image} ${period}=60 ${times}=10 - :For ${n} IN RANGE 1 ${times} - \ Sleep ${period} - \ Go Into Project ${project} - \ Switch To Project Repo - \ #In AWS-ECR, under repository a, there're only several images: httpd,alpine,hello-world. - \ ${out} Run Keyword And Ignore Error Retry Wait Until Page Contains ${project}/${image} - \ Log To Console Return value is ${out[0]} - \ Exit For Loop If '${out[0]}'=='PASS' - \ Sleep 5 + [Arguments] ${project} ${image} ${period}=60 ${times}=3 + FOR ${n} IN RANGE 0 ${times} + Sleep ${period} + Go Into Project ${project} + Switch To Project Repo + #In AWS-ECR, under repository a, there're only several images: httpd,alpine,hello-world. + ${out} Run Keyword And Ignore Error Retry Wait Until Page Contains ${project}/${image} + Log To Console Return value is ${out[0]} + Exit For Loop If '${out[0]}'=='PASS' + Sleep 5 + END Run Keyword If '${out[0]}'=='FAIL' Capture Page Screenshot - Should Be Equal As Strings '${out[0]}' 'PASS' \ No newline at end of file + Should Be Equal As Strings '${out[0]}' 'PASS' + +Executions Result Count Should Be + [Arguments] ${expected_status} ${expected_trigger_type} ${expected_result_count} + Sleep 10 + ${count}= Get Element Count xpath=//clr-dg-row[contains(.,'${expected_status}') and contains(.,'${expected_trigger_type}')] + Capture Page Screenshot + Should Be Equal As Integers ${count} ${expected_result_count} + Capture Page Screenshot + diff --git a/tests/resources/Harbor-Pages/Replication_Elements.robot b/tests/resources/Harbor-Pages/Replication_Elements.robot index 9ffd76096..104445e3c 100644 --- a/tests/resources/Harbor-Pages/Replication_Elements.robot +++ b/tests/resources/Harbor-Pages/Replication_Elements.robot @@ -23,7 +23,7 @@ ${policy_enable_checkbox} //input[@id='policy_enable']/../label ${policy_endpoint_checkbox} //input[@id='check_new']/../label ${destination_name_xpath} //*[@id='destination_name'] ${destination_url_xpath} //*[@id='destination_url'] -${destination_username_xpath} //*[@id='destination_access_key'] +${destination_username_xpath} //*[@id='destination_access_key'] ${destination_password_xpath} //*[@id='destination_password'] ${replication_save_xpath} //button[contains(.,'OK')] ${replication_xpath} //clr-vertical-nav-group-children/a[contains(.,'Replication')] @@ -41,7 +41,7 @@ ${rule_trigger_select} //select[@id='ruleTrigger'] ${schedule_type_select} //select[@name='scheduleType'] ${schedule_day_select} //select[@name='scheduleDay'] ${shcedule_time} //input[@type='time'] -${destination_insecure_checkbox} //hbr-create-edit-endpoint/clr-modal//input[@id='destination_insecure'] +${destination_insecure_checkbox} //hbr-create-edit-endpoint/clr-modal//input[@id='destination_insecure'] ${ping_test_button} //button[contains(.,'Test')] ${nav_to_registries} //clr-vertical-nav//span[contains(.,'Registries')] ${nav_to_replications} //clr-vertical-nav//span[contains(.,'Replications')] @@ -59,29 +59,32 @@ ${dialog_delete} //clr-modal//button[contains(.,'DELETE')] ${dialog_replicate} //clr-modal//button[contains(.,'REPLICATE')] ${action_bar_replicate} //button[contains(.,'Replicate')] ${rule_save_button} //button[contains(.,'SAVE')] -${provider_selector} //*[@id='adapter'] -${replication_mode_radio_push} //clr-main-container//hbr-create-edit-rule//label[contains(.,'Push-based')] -${replication_mode_radio_pull} //clr-main-container//hbr-create-edit-rule//label[contains(.,'Pull-based')] -${source_project} //input[@id='filter_name'] -${rule_resource_selector} //*[@id='select_resource'] -${trigger_mode_selector} //*[@id='ruleTrigger'] -${dest_namespace_xpath} //*[@id='dest_namespace'] -${new_replication_rule_id} //*[@id='new_replication_rule_id'] -${edit_replication_rule_id} //*[@id='edit_replication_rule_id'] -${delete_replication_rule_id} //*[@id='delete_replication_rule_id'] -${replication_exec_id} //*[@id='replication_exe_id'] -${replication_task_line_1} //clr-datagrid//clr-dg-row/div/div[2]//clr-checkbox-wrapper/label[1] -${filter_tag} //*[@id='filter_tag'] -${is_overide_xpath} //label[contains(.,'Replace the destination resources if name exists')] -${enable_rule_xpath} //label[contains(.,'Enable rule')] -${targetCron_id} //*[@id='targetCron'] -${rule_name_input} //*[@id='ruleName'] -${src_registry_dropdown_list} //select[@id='src_registry_id'] -${dest_registry_dropdown_list} //select[@id='dest_registry'] -${rule_confirm_btn} //*[@id='ruleBtnOk'] -${rule_cancel_btn} //*[@id='ruleBtnCancel'] -${filter_rules_btn} //*[@id='filter-rules'] +${provider_selector} //*[@id='adapter'] +${replication_mode_radio_push} //clr-main-container//hbr-create-edit-rule//label[contains(.,'Push-based')] +${replication_mode_radio_pull} //clr-main-container//hbr-create-edit-rule//label[contains(.,'Pull-based')] +${filter_name_id} //input[@id='filter_name'] +${filter_tag_id} //input[@id='filter_tag'] +${rule_resource_selector} //*[@id='select_resource'] +${trigger_mode_selector} //*[@id='ruleTrigger'] +${dest_namespace_xpath} //*[@id='dest_namespace'] +${new_replication_rule_id} //*[@id='new_replication_rule_id'] +${edit_replication_rule_id} //*[@id='edit_replication_rule_id'] +${delete_replication_rule_id} //*[@id='delete_replication_rule_id'] +${replication_exec_id} //*[@id='replication_exe_id'] +${replication_task_line_1} //clr-datagrid//clr-dg-row/div/div[2]//clr-checkbox-wrapper/label[1] +${is_overide_xpath} //label[contains(.,'Replace the destination resources if name exists')] +${enable_rule_xpath} //label[contains(.,'Enable rule')] +${targetCron_id} //*[@id='targetCron'] +${rule_name_input} //*[@id='ruleName'] +${src_registry_dropdown_list} //select[@id='src_registry_id'] +${dest_registry_dropdown_list} //select[@id='dest_registry'] +${rule_confirm_btn} //*[@id='ruleBtnOk'] +${rule_cancel_btn} //*[@id='ruleBtnCancel'] +${filter_rules_btn} //*[@id='filter-rules'] ${filter_rules_input} //*[@id='filter-rules']//input +${del_remote_checkbox} //label[@for='ruleDeletion'] +${filter_registry_btn} //hbr-filter +${filter_registry_input} //input[contains(@class,'filter-input')] diff --git a/tests/resources/Harbor-Pages/ToolKit.robot b/tests/resources/Harbor-Pages/ToolKit.robot index 15e319f93..dea0d08e5 100644 --- a/tests/resources/Harbor-Pages/ToolKit.robot +++ b/tests/resources/Harbor-Pages/ToolKit.robot @@ -21,15 +21,17 @@ Resource ../../resources/Util.robot *** Keywords *** Delete Success [Arguments] @{obj} - :For ${obj} in @{obj} - \ Retry Wait Until Page Contains Element //*[@id='contentAll']//div[contains(.,'${obj}')]/../div/clr-icon[@shape='success-standard'] + FOR ${obj} IN @{obj} + Retry Wait Until Page Contains Element //*[@id='contentAll']//div[contains(.,'${obj}')]/../div/clr-icon[@shape='success-standard'] + END Sleep 1 Capture Page Screenshot Delete Fail [Arguments] @{obj} - :For ${obj} in @{obj} - \ Retry Wait Until Page Contains Element //*[@id='contentAll']//div[contains(.,'${obj}')]/../div/clr-icon[@shape='error-standard'] + FOR ${obj} IN @{obj} + Retry Wait Until Page Contains Element //*[@id='contentAll']//div[contains(.,'${obj}')]/../div/clr-icon[@shape='error-standard'] + END Sleep 1 Capture Page Screenshot @@ -46,7 +48,7 @@ Filter Object Filter Project #Filter project repo user tag. [Arguments] ${kw} - Retry Element Click ${log_xpath} + Retry Element Click ${log_xpath} Retry Element Click ${projects_xpath} Filter Object ${kw} @@ -57,9 +59,10 @@ Select Object Multi-delete Object [Arguments] ${delete_btn} @{obj} - :For ${obj} in @{obj} - \ ${element}= Set Variable xpath=//clr-dg-row[contains(.,'${obj}')]//label - \ Retry Element Click ${element} + FOR ${obj} IN @{obj} + ${element}= Set Variable xpath=//clr-dg-row[contains(.,'${obj}')]//label + Retry Element Click ${element} + END Sleep 1 Capture Page Screenshot Retry Element Click ${delete_btn} @@ -73,9 +76,10 @@ Multi-delete Object # This func cannot support as the delete user flow changed. Multi-delete Artifact [Arguments] ${delete_btn} @{obj} - :For ${obj} in @{obj} - \ ${element}= Set Variable xpath=//clr-dg-row[contains(.,'${obj}')]//label - \ Retry Element Click ${element} + FOR ${obj} IN @{obj} + ${element}= Set Variable xpath=//clr-dg-row[contains(.,'${obj}')]//label + Retry Element Click ${element} + END Sleep 1 Capture Page Screenshot Retry Element Click ${artifact_action_xpath} @@ -90,8 +94,9 @@ Multi-delete Artifact Multi-delete User [Arguments] @{obj} - :For ${obj} in @{obj} - \ Retry Element Click //clr-dg-row[contains(.,'${obj}')]//label + FOR ${obj} IN @{obj} + Retry Element Click //clr-dg-row[contains(.,'${obj}')]//label + END Retry Element Click ${member_action_xpath} Retry Element Click //*[@id='deleteUser'] Retry Double Keywords When Error Retry Element Click ${delete_btn} Retry Wait Until Page Not Contains Element ${delete_btn} @@ -99,8 +104,9 @@ Multi-delete User Multi-delete Member [Arguments] @{obj} - :For ${obj} in @{obj} - \ Retry Element Click //clr-dg-row[contains(.,'${obj}')]//clr-checkbox-wrapper/label + FOR ${obj} IN @{obj} + Retry Element Click //clr-dg-row[contains(.,'${obj}')]//clr-checkbox-wrapper/label + END Retry Double Keywords When Error Retry Element Click ${member_action_xpath} Retry Wait Until Page Contains Element ${delete_action_xpath} Retry Double Keywords When Error Retry Element Click ${delete_action_xpath} Retry Wait Until Page Contains Element ${delete_btn} Retry Double Keywords When Error Retry Element Click ${delete_btn} Retry Wait Until Page Not Contains Element ${delete_btn} @@ -108,8 +114,9 @@ Multi-delete Member Multi-delete Object Without Confirmation [Arguments] @{obj} - :For ${obj} in @{obj} - \ Retry Element Click //clr-dg-row[contains(.,'${obj}')]//label + FOR ${obj} IN @{obj} + Retry Element Click //clr-dg-row[contains(.,'${obj}')]//label + END Retry Double Keywords When Error Retry Element Click ${delete_btn_2} Retry Wait Until Page Not Contains Element ${delete_btn_2} diff --git a/tests/resources/Harbor-Pages/Verify.robot b/tests/resources/Harbor-Pages/Verify.robot index 77f594663..796f2201a 100644 --- a/tests/resources/Harbor-Pages/Verify.robot +++ b/tests/resources/Harbor-Pages/Verify.robot @@ -11,14 +11,16 @@ Verify User Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Switch To User Tag @{user}= Get Value From Json ${json} $.users..name - :FOR ${user} IN @{user} - \ Page Should Contain ${user} + FOR ${user} IN @{user} + Page Should Contain ${user} + END Logout Harbor #verify user can login @{user}= Get Value From Json ${json} $.users..name - :FOR ${user} IN @{user} - \ Sign In Harbor ${HARBOR_URL} ${user} ${HARBOR_PASSWORD} - \ Logout Harbor + FOR ${user} IN @{user} + Sign In Harbor ${HARBOR_URL} ${user} ${HARBOR_PASSWORD} + Logout Harbor + END Close Browser Verify Project @@ -27,8 +29,9 @@ Verify Project @{project}= Get Value From Json ${json} $.projects.[*].name Init Chrome Driver Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - :FOR ${project} IN @{project} - \ Retry Wait Until Page Contains ${project} + FOR ${project} IN @{project} + Retry Wait Until Page Contains ${project} + END Verify Project Metadata ${json} Close Browser @@ -38,13 +41,14 @@ Verify Image Tag @{project}= Get Value From Json ${json} $.projects.[*].name Init Chrome Driver Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - :FOR ${project} IN @{project} - \ @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image - \ ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} - \ Go Into Project ${project} has_image=${has_image} - \ @{repo}= Get Value From Json ${json} $.projects[?(@.name=${project})]..repo..name - \ Run Keyword If ${has_image} == ${true} Loop Image Repo @{repo} - \ Navigate To Projects + FOR ${project} IN @{project} + @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image + ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} + Go Into Project ${project} has_image=${has_image} + @{repo}= Get Value From Json ${json} $.projects[?(@.name=${project})]..repo..name + Run Keyword If ${has_image} == ${true} Loop Image Repo @{repo} + Navigate To Projects + END Close Browser Verify Project Metadata @@ -52,19 +56,20 @@ Verify Project Metadata @{project}= Get Value From Json ${json} $.projects.[*].name Init Chrome Driver Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - :FOR ${project} IN @{project} - \ @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image - \ ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} - \ Go Into Project ${project} has_image=${has_image} - \ Switch To Project Configuration - \ Verify Checkbox ${json} $.projects[?(@.name=${project})].configuration.public ${project_config_public_checkbox} - \ Verify Checkbox ${json} $.projects[?(@.name=${project})].configuration.enable_content_trust ${project_config_content_trust_checkbox} - \ Verify Checkbox ${json} $.projects[?(@.name=${project})].configuration.auto_scan ${project_config_scan_images_on_push_checkbox} - \ Verify Checkbox ${json} $.projects[?(@.name=${project})].configuration.prevent_vul ${project_config_prevent_vulnerable_images_from_running_checkbox} - \ ${ret} Get Selected List Value ${project_config_severity_select} - \ @{severity}= Get Value From Json ${json} $.projects[?(@.name=${project})].configuration.severity - \ Should Contain ${ret} @{severity}[0] - \ Navigate To Projects + FOR ${project} IN @{project} + @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image + ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} + Go Into Project ${project} has_image=${has_image} + Switch To Project Configuration + Verify Checkbox ${json} $.projects[?(@.name=${project})].configuration.public ${project_config_public_checkbox} + Verify Checkbox ${json} $.projects[?(@.name=${project})].configuration.enable_content_trust ${project_config_content_trust_checkbox} + Verify Checkbox ${json} $.projects[?(@.name=${project})].configuration.auto_scan ${project_config_scan_images_on_push_checkbox} + Verify Checkbox ${json} $.projects[?(@.name=${project})].configuration.prevent_vul ${project_config_prevent_vulnerable_images_from_running_checkbox} + ${ret} Get Selected List Value ${project_config_severity_select} + @{severity}= Get Value From Json ${json} $.projects[?(@.name=${project})].configuration.severity + Should Contain ${ret} @{severity}[0] + Navigate To Projects + END Close Browser Verify Checkbox @@ -77,8 +82,9 @@ Verify Checkbox Loop Image Repo [Arguments] @{repo} - :For ${repo} In @{repo} - \ Page Should Contain ${repo} + FOR ${repo} IN @{repo} + Page Should Contain ${repo} + END Verify Member Exist [Arguments] ${json} @@ -86,14 +92,15 @@ Verify Member Exist @{project}= Get Value From Json ${json} $.projects.[*].name Init Chrome Driver Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - :For ${project} In @{project} - \ @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image - \ ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} - \ Go Into Project ${project} has_image=${has_image} - \ Switch To Member - \ @{members}= Get Value From Json ${json} $.projects[?(@.name=${project})].member..name - \ Loop Member @{members} - \ Navigate To Projects + FOR ${project} IN @{project} + @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image + ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} + Go Into Project ${project} has_image=${has_image} + Switch To Member + @{members}= Get Value From Json ${json} $.projects[?(@.name=${project})].member..name + Loop Member @{members} + Navigate To Projects + END Close Browser Verify Webhook @@ -102,24 +109,25 @@ Verify Webhook @{project}= Get Value From Json ${json} $.projects.[*].name Init Chrome Driver Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - :For ${project} In @{project} - \ @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image - \ ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} - \ Go Into Project ${project} has_image=${has_image} - \ Switch To Project Webhooks - \ @{enabled}= Get Value From Json ${json} $.projects[?(@.name=${project})].webhook.enabled - \ ${enable_count} Get Matching Xpath Count xpath=//span[contains(.,'Enabled')] - \ ${disable_count} Get Matching Xpath Count xpath=//span[contains(.,'Disabled')] - \ Log To Console '@{enabled}[0]' - \ Log To Console '${true}' - \ Run Keyword If '@{enabled}[0]' == '${true}' Page Should Contain Enabled - \ ... ELSE Page Should Contain Disabled - \ @{address}= Get Value From Json ${json} $.projects[?(@.name=${project})].webhook.address - \ Log To Console '@{address}[0]' - \ Page Should Contain @{address}[0] - \ Page Should Contain policy - \ Page Should Contain http - \ Navigate To Projects + FOR ${project} IN @{project} + @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image + ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} + Go Into Project ${project} has_image=${has_image} + Switch To Project Webhooks + ${enabled}= Get Value From Json ${json} $.projects[?(@.name=${project})].webhook.enabled + ${enable_count} Get Element Count xpath=//span[contains(.,'Enabled')] + ${disable_count} Get Element Count xpath=//span[contains(.,'Disabled')] + Log To Console '${enabled}[0]' + Log To Console '${true}' + Run Keyword If '${enabled}[0]' == '${true}' Page Should Contain Enabled + ... ELSE Page Should Contain Disabled + ${address}= Get Value From Json ${json} $.projects[?(@.name=${project})].webhook.address + Log To Console '${address}[0]' + Page Should Contain ${address}[0] + Page Should Contain policy + Page Should Contain http + Navigate To Projects + END Close Browser Verify Tag Retention Rule @@ -128,22 +136,23 @@ Verify Tag Retention Rule @{project}= Get Value From Json ${json} $.projects.[*].name Init Chrome Driver Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - :For ${project} In @{project} - \ @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image - \ ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} - \ Go Into Project ${project} has_image=${has_image} - \ Switch To Tag Retention - \ ${actions_count}= Set Variable 8 - \ @{repository_patten}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_retention_rule.repository_patten - \ @{tag_decoration}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_retention_rule.tag_decoration - \ @{latestPushedK}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_retention_rule.latestPushedK - \ @{cron}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_retention_rule.cron - \ Log To Console '@{repository_patten}[0]' - \ Page Should Contain @{repository_patten}[0] - \ Page Should Contain @{tag_decoration}[0] - \ Page Should Contain @{latestPushedK}[0] - \ Page Should Contain @{cron}[0] - \ Navigate To Projects + FOR ${project} IN @{project} + ${out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image + ${has_image} Set Variable If ${out_has_image}[0] == ${true} ${true} ${false} + Go Into Project ${project} has_image=${has_image} + Switch To Tag Retention + ${actions_count}= Set Variable 8 + ${repository_patten}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_retention_rule.repository_patten + ${tag_decoration}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_retention_rule.tag_decoration + ${latestPushedK}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_retention_rule.latestPushedK_verify + ${cron}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_retention_rule.cron + Log To Console '${repository_patten}[0]' + Page Should Contain ${repository_patten}[0] + Page Should Contain ${tag_decoration}[0] + Page Should Contain ${latestPushedK}[0] + Page Should Contain ${cron}[0] + Navigate To Projects + END Close Browser Verify Tag Immutability Rule @@ -152,27 +161,29 @@ Verify Tag Immutability Rule @{project}= Get Value From Json ${json} $.projects.[*].name Init Chrome Driver Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - :For ${project} In @{project} - \ @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image - \ ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} - \ Go Into Project ${project} has_image=${has_image} - \ Switch To Tag Immutability - \ @{repo_decoration}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_immutability_rule.repo_decoration - \ @{tag_decoration}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_immutability_rule.tag_decoration - \ @{repo_pattern}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_immutability_rule.repo_pattern - \ @{tag_pattern}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_immutability_rule.tag_pattern - \ Log To Console '@{repo_decoration}[0]' - #\ Page Should Contain @{repo_decoration}[0] - #\ Page Should Contain @{tag_decoration}[0] - \ Page Should Contain @{repo_pattern}[0] - \ Page Should Contain @{tag_pattern}[0] - \ Navigate To Projects + FOR ${project} IN @{project} + @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image + ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} + Go Into Project ${project} has_image=${has_image} + Switch To Tag Immutability + @{repo_decoration}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_immutability_rule.repo_decoration + @{tag_decoration}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_immutability_rule.tag_decoration + @{repo_pattern}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_immutability_rule.repo_pattern + @{tag_pattern}= Get Value From Json ${json} $.projects[?(@.name=${project})].tag_immutability_rule.tag_pattern + Log To Console '@{repo_decoration}[0]' + #Page Should Contain @{repo_decoration}[0] + #Page Should Contain @{tag_decoration}[0] + Page Should Contain @{repo_pattern}[0] + Page Should Contain @{tag_pattern}[0] + Navigate To Projects + END Close Browser Loop Member [Arguments] @{members} - :For ${member} In @{members} - \ Page Should Contain ${member} + FOR ${member} IN @{members} + Page Should Contain ${member} + END Verify Robot Account Exist [Arguments] ${json} @@ -180,30 +191,33 @@ Verify Robot Account Exist @{project}= Get Value From Json ${json} $.projects.[*].name Init Chrome Driver Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - :For ${project} In @{project} - \ @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image - \ ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} - \ Go Into Project ${project} has_image=${has_image} - \ Switch To Project Robot Account - \ @{robot_accounts}= Get Value From Json ${json} $.projects[?(@.name=${project})].robot_account..name - \ Loop Verify Robot Account @{robot_accounts} - \ Navigate To Projects + FOR ${project} IN @{project} + @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image + ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} + Go Into Project ${project} has_image=${has_image} + Switch To Project Robot Account + @{robot_accounts}= Get Value From Json ${json} $.projects[?(@.name=${project})].robot_account..name + Loop Verify Robot Account @{robot_accounts} + Navigate To Projects + END Close Browser Loop Verify Robot Account [Arguments] @{robot_accounts} - :For ${robot_account} In @{robot_accounts} - \ Page Should Contain ${robot_account} + FOR ${robot_account} IN @{robot_accounts} + Page Should Contain ${robot_account} + END Verify User System Admin Role [Arguments] ${json} Log To Console "Verify User System Admin Role..." @{user}= Get Value From Json ${json} $.admin..name Init Chrome Driver - :FOR ${user} IN @{user} - \ Sign In Harbor ${HARBOR_URL} ${user} ${HARBOR_PASSWORD} - \ Page Should Contain Administration - \ Logout Harbor + FOR ${user} IN @{user} + Sign In Harbor ${HARBOR_URL} ${user} ${HARBOR_PASSWORD} + Page Should Contain Administration + Logout Harbor + END Close Browser Verify System Label @@ -214,25 +228,28 @@ Verify System Label Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Switch To Configure Switch To System Labels - :For ${label} In @{label} - \ Page Should Contain ${label} + FOR ${label} IN @{label} + Page Should Contain ${label} + END Close Browser Verify Project Label - [Arguments] ${json} - Log To Console "Verify Project Label..." - @{project}= Get Value From Json ${json} $.peoject.[*].name - Init Chrome Driver - Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - :For ${project} In @{project} - \ @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image - \ ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} - \ Go Into Project ${project} has_image=${has_image} - \ Switch To Project Label - \ @{projectlabel}= Get Value From Json ${json} $.projects[?(@.name=${project})]..labels..name - \ :For ${label} In @{label} - \ \ Page Should Contain ${projectlabel} - \ Navigate To Projects + [Arguments] ${json} + Log To Console "Verify Project Label..." + @{project}= Get Value From Json ${json} $.peoject.[*].name + Init Chrome Driver + Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} + FOR ${project} IN @{project} + @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image + ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} + Go Into Project ${project} has_image=${has_image} + Switch To Project Label + @{projectlabel}= Get Value From Json ${json} $.projects[?(@.name=${project})]..labels..name + FOR ${label} IN @{label} + Page Should Contain ${projectlabel} + END + Navigate To Projects + END Close Browser Verify Endpoint @@ -242,8 +259,9 @@ Verify Endpoint Init Chrome Driver Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Switch To Registries - :For ${endpoint} In @{endpoint} - \ Page Should Contain ${endpoint} + FOR ${endpoint} IN @{endpoint} + Page Should Contain ${endpoint} + END Close Browser Verify Replicationrule @@ -251,63 +269,65 @@ Verify Replicationrule Log To Console "Verify Replicationrule..." @{replicationrules}= Get Value From Json ${json} $.replicationrule.[*].rulename @{endpoints}= Get Value From Json ${json} $.endpoint.[*].name - : FOR ${replicationrule} IN @{replicationrules} - \ Init Chrome Driver - \ Log To Console -----replicationrule-----"${replicationrule}"------------ - \ Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - \ Switch To Replication Manage - \ Select Rule And Click Edit Button ${replicationrule} - \ @{is_src_registry}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].is_src_registry - \ @{trigger_type}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].trigger_type - \ @{name_filters}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].name_filters - \ @{tag_filters}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].tag_filters - \ @{dest_namespace}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].dest_namespace - \ @{cron}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].cron - \ @{is_src_registry}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].is_src_registry - \ Log To Console -----is_src_registry-----@{is_src_registry}[0]------------ - \ @{endpoint}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].endpoint - \ Log To Console -----endpoint-----@{endpoint}------------ - \ ${endpoint0}= Set Variable @{endpoint}[0] - \ Log To Console -----endpoint0-----${endpoint0}------------ - \ @{endpoint_type}= Get Value From Json ${json} $.endpoint[?(@.name=${endpoint0})].type - \ Retry Textfield Value Should Be ${source_project} @{name_filters}[0] - \ Retry Textfield Value Should Be ${filter_tag} @{tag_filters}[0] - \ Retry Textfield Value Should Be ${rule_name_input} ${replicationrule} - \ Retry Textfield Value Should Be ${dest_namespace_xpath} @{dest_namespace}[0] - \ Log To Console -----endpoint_type-----@{endpoint_type}[0]------------ - \ ${registry}= Set Variable If "@{endpoint_type}[0]"=="harbor" ${endpoint0}-https://${IP} ${endpoint0}-https://hub.docker.com - \ Log To Console -------registry---${registry}------------ - \ Run Keyword If '@{is_src_registry}[0]' == '${true}' Retry List Selection Should Be ${src_registry_dropdown_list} ${registry} - \ ... ELSE Retry List Selection Should Be ${dest_registry_dropdown_list} ${registry} - \ #\ Retry List Selection Should Be ${rule_resource_selector} ${resource_type} - \ Retry List Selection Should Be ${rule_trigger_select} @{trigger_type}[0] - \ Run Keyword If '@{trigger_type}[0]' == 'scheduled' Log To Console ----------@{trigger_type}[0]------------ - \ Run Keyword If '@{trigger_type}[0]' == 'scheduled' Retry Textfield Value Should Be ${targetCron_id} @{cron}[0] + FOR ${replicationrule} IN @{replicationrules} + Init Chrome Driver + Log To Console -----replicationrule-----"${replicationrule}"------------ + Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} + Switch To Replication Manage + Select Rule And Click Edit Button ${replicationrule} + @{is_src_registry}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].is_src_registry + @{trigger_type}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].trigger_type + @{name_filters}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].name_filters + @{tag_filters}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].tag_filters + @{dest_namespace}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].dest_namespace + @{cron}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].cron + @{is_src_registry}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].is_src_registry + Log To Console -----is_src_registry-----@{is_src_registry}[0]------------ + @{endpoint}= Get Value From Json ${json} $.replicationrule[?(@.rulename=${replicationrule})].endpoint + Log To Console -----endpoint-----@{endpoint}------------ + ${endpoint0}= Set Variable @{endpoint}[0] + Log To Console -----endpoint0-----${endpoint0}------------ + @{endpoint_type}= Get Value From Json ${json} $.endpoint[?(@.name=${endpoint0})].type + Retry Textfield Value Should Be ${filter_name_id} @{name_filters}[0] + Retry Textfield Value Should Be ${filter_tag_id} @{tag_filters}[0] + Retry Textfield Value Should Be ${rule_name_input} ${replicationrule} + Retry Textfield Value Should Be ${dest_namespace_xpath} @{dest_namespace}[0] + Log To Console -----endpoint_type-----@{endpoint_type}[0]------------ + ${registry}= Set Variable If "@{endpoint_type}[0]"=="harbor" ${endpoint0}-https://${IP} ${endpoint0}-https://hub.docker.com + Log To Console -------registry---${registry}------------ + Run Keyword If '@{is_src_registry}[0]' == '${true}' Retry List Selection Should Be ${src_registry_dropdown_list} ${registry} + ... ELSE Retry List Selection Should Be ${dest_registry_dropdown_list} ${registry} + #Retry List Selection Should Be ${rule_resource_selector} ${resource_type} + Retry List Selection Should Be ${rule_trigger_select} @{trigger_type}[0] + Run Keyword If '@{trigger_type}[0]' == 'scheduled' Log To Console ----------@{trigger_type}[0]------------ + Run Keyword If '@{trigger_type}[0]' == 'scheduled' Retry Textfield Value Should Be ${targetCron_id} @{cron}[0] + END Close Browser Verify Project Setting [Arguments] ${json} Log To Console "Verify Project Setting..." @{projects}= Get Value From Json ${json} $.projects.[*].name - :For ${project} In @{Projects} - \ ${public}= Get Value From Json ${json} $.projects[?(@.name=${project})].accesslevel - \ ${contenttrust}= Get Value From Json ${json} $.projects[?(@.name=${project})]..enable_content_trust - \ ${preventrunning}= Get Value From Json ${json} $.projects[?(@.name=${project})]..prevent_vulnerable_images_from_running - \ ${scanonpush}= Get Value From Json ${json} $.projects[?(@.name=${project})]..automatically_scan_images_on_push - \ Init Chrome Driver - \ Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - \ @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image - \ ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} - \ Go Into Project ${project} has_image=${has_image} - \ Goto Project Config - \ Run Keyword If ${public} == "public" Checkbox Should Be Checked //clr-checkbox-wrapper[@name='public']//label - \ Run Keyword If ${contenttrust} == "true" Checkbox Should Be Checked //clr-checkbox-wrapper[@name='content-trust']//label - \ Run Keyword If ${contenttrust} == "false" Checkbox Should Not Be Checked //clr-checkbox-wrapper[@name='content-trust']//label - \ Run Keyword If ${preventrunning} == "true" Checkbox Should Be Checked //*[@id='prevent-vulenrability-image']//clr-checkbox-wrapper//label - \ Run Keyword If ${preventrunning} == "false" Checkbox Should Not Be Checked //*[@id='prevent-vulenrability-image']//clr-checkbox-wrapper//label - \ Run Keyword If ${scanonpush} == "true" Checkbox Should Be Checked //clr-checkbox-wrapper[@id='scan-image-on-push-wrapper']//input - \ Run Keyword If ${scanonpush} == "true" Checkbox Should Not Be Checked //clr-checkbox-wrapper[@id='scan-image-on-push-wrapper']//input - \ Close Browser + FOR ${project} IN @{Projects} + ${public}= Get Value From Json ${json} $.projects[?(@.name=${project})].accesslevel + ${contenttrust}= Get Value From Json ${json} $.projects[?(@.name=${project})]..enable_content_trust + ${preventrunning}= Get Value From Json ${json} $.projects[?(@.name=${project})]..prevent_vulnerable_images_from_running + ${scanonpush}= Get Value From Json ${json} $.projects[?(@.name=${project})]..automatically_scan_images_on_push + Init Chrome Driver + Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} + @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image + ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} + Go Into Project ${project} has_image=${has_image} + Goto Project Config + Run Keyword If ${public} == "public" Checkbox Should Be Checked //clr-checkbox-wrapper[@name='public']//label + Run Keyword If ${contenttrust} == "true" Checkbox Should Be Checked //clr-checkbox-wrapper[@name='content-trust']//label + Run Keyword If ${contenttrust} == "false" Checkbox Should Not Be Checked //clr-checkbox-wrapper[@name='content-trust']//label + Run Keyword If ${preventrunning} == "true" Checkbox Should Be Checked //*[@id='prevent-vulenrability-image']//clr-checkbox-wrapper//label + Run Keyword If ${preventrunning} == "false" Checkbox Should Not Be Checked //*[@id='prevent-vulenrability-image']//clr-checkbox-wrapper//label + Run Keyword If ${scanonpush} == "true" Checkbox Should Be Checked //clr-checkbox-wrapper[@id='scan-image-on-push-wrapper']//input + Run Keyword If ${scanonpush} == "true" Checkbox Should Not Be Checked //clr-checkbox-wrapper[@id='scan-image-on-push-wrapper']//input + Close Browser + END Verify Interrogation Services [Arguments] ${json} @@ -358,23 +378,25 @@ Verify Project-level Whitelist @{project}= Get Value From Json ${json} $.projects.[*].name Init Chrome Driver Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - :FOR ${project} IN @{project} - \ @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image - \ ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} - \ Go Into Project ${project} has_image=${has_image} - \ Switch To Project Configuration - \ @{is_reuse_sys_cve_whitelist}= Get Value From Json ${json} $.projects[?(@.name=${project})].configuration.reuse_sys_cve_whitelist - \ Run Keyword If "@{is_reuse_sys_cve_whitelist}[0]" == "true" Retry Wait Element Should Be Disabled ${project_config_project_wl_add_btn} - \ ... ELSE Retry Wait Element ${project_config_project_wl_add_btn} - \ @{cve_ids}= Get Value From Json ${json} $.projects[?(@.name=${project})].configuration.cve - \ Loop Verifiy CVE_IDs @{cve_ids} - \ Navigate To Projects + FOR ${project} IN @{project} + @{out_has_image}= Get Value From Json ${json} $.projects[?(@.name=${project})].has_image + ${has_image} Set Variable If @{out_has_image}[0] == ${true} ${true} ${false} + Go Into Project ${project} has_image=${has_image} + Switch To Project Configuration + @{is_reuse_sys_cve_whitelist}= Get Value From Json ${json} $.projects[?(@.name=${project})].configuration.reuse_sys_cve_whitelist + Run Keyword If "@{is_reuse_sys_cve_whitelist}[0]" == "true" Retry Wait Element Should Be Disabled ${project_config_project_wl_add_btn} + ... ELSE Retry Wait Element ${project_config_project_wl_add_btn} + @{cve_ids}= Get Value From Json ${json} $.projects[?(@.name=${project})].configuration.cve + Loop Verifiy CVE_IDs @{cve_ids} + Navigate To Projects + END Close Browser Loop Verifiy CVE_IDs [Arguments] @{cve_ids} - :For ${cve_id} In @{cve_ids} - \ Page Should Contain ${cve_id} + FOR ${cve_id} IN @{cve_ids} + Page Should Contain ${cve_id} + END Verify System Setting Whitelist [Arguments] ${json} diff --git a/tests/resources/Harbor-Util.robot b/tests/resources/Harbor-Util.robot index bff05c28a..2774242a5 100644 --- a/tests/resources/Harbor-Util.robot +++ b/tests/resources/Harbor-Util.robot @@ -14,7 +14,7 @@ *** Settings *** Documentation This resource provides any keywords related to the Harbor private registry appliance -Library Selenium2Library +Library SeleniumLibrary Library OperatingSystem *** Variables *** @@ -26,7 +26,7 @@ Install Harbor to Test Server Sleep 5s ${rc} ${output}= Run And Return Rc And Output docker ps Should Be Equal As Integers ${rc} 0 - Log To Console \n${output} + Log To Console ${output} Log To Console \nconfig harbor cfg Config Harbor cfg http_proxy=https Prepare Cert @@ -34,7 +34,7 @@ Install Harbor to Test Server Compile and Up Harbor With Source Code ${rc} ${output}= Run And Return Rc And Output docker ps Should Be Equal As Integers ${rc} 0 - Log To Console \n${output} + Log To Console ${output} Generate Certificate Authority For Chrome Up Harbor @@ -55,7 +55,7 @@ Package Harbor Offline [Arguments] ${with_notary}=true ${with_clair}=true ${with_chartmuseum}=true ${with_trivy}=true Log To Console \nStart Docker Daemon Start Docker Daemon Locally - Log To Console \n\nmake package_offline GOBUILDTAGS="include_oss include_gcs" BASEIMAGETAG=%{Harbor_Build_Base_Tag} NPM_REGISTRY=%{NPM_REGISTRY} VERSIONTAG=%{Harbor_Assets_Version} PKGVERSIONTAG=%{Harbor_Package_Version} NOTARYFLAG=${with_notary} CLAIRFLAG=${with_clair} CHARTFLAG=${with_chartmuseum} TRIVYFLAG=${with_trivy} HTTPPROXY= + Log To Console make package_offline GOBUILDTAGS="include_oss include_gcs" BASEIMAGETAG=%{Harbor_Build_Base_Tag} NPM_REGISTRY=%{NPM_REGISTRY} VERSIONTAG=%{Harbor_Assets_Version} PKGVERSIONTAG=%{Harbor_Package_Version} NOTARYFLAG=${with_notary} CLAIRFLAG=${with_clair} CHARTFLAG=${with_chartmuseum} TRIVYFLAG=${with_trivy} HTTPPROXY= ${rc} ${output}= Run And Return Rc And Output make package_offline GOBUILDTAGS="include_oss include_gcs" BASEIMAGETAG=%{Harbor_Build_Base_Tag} NPM_REGISTRY=%{NPM_REGISTRY} VERSIONTAG=%{Harbor_Assets_Version} PKGVERSIONTAG=%{Harbor_Package_Version} NOTARYFLAG=${with_notary} CLAIRFLAG=${with_clair} CHARTFLAG=${with_chartmuseum} TRIVYFLAG=${with_trivy} HTTPPROXY= Log To Console ${rc} Log To Console ${output} @@ -148,14 +148,15 @@ Compile and Up Harbor With Source Code Wait for Harbor Ready [Arguments] ${protocol} ${HARBOR_IP} Log To Console Waiting for Harbor to Come Up... - :FOR ${i} IN RANGE 20 - \ ${out}= Run curl -k ${protocol}://${HARBOR_IP} - \ Log ${out} - \ ${status}= Run Keyword And Return Status Should Not Contain ${out} 502 Bad Gateway - \ ${status}= Run Keyword If ${status} Run Keyword And Return Status Should Not Contain ${out} Connection refused - \ ${status}= Run Keyword If ${status} Run Keyword And Return Status Should Contain ${out} Harbor - \ Return From Keyword If ${status} ${HARBOR_IP} - \ Sleep 30s + FOR ${i} IN RANGE 20 + ${out}= Run curl -k ${protocol}://${HARBOR_IP} + Log ${out} + ${status}= Run Keyword And Return Status Should Not Contain ${out} 502 Bad Gateway + ${status}= Run Keyword If ${status} Run Keyword And Return Status Should Not Contain ${out} Connection refused + ${status}= Run Keyword If ${status} Run Keyword And Return Status Should Contain ${out} Harbor + Return From Keyword If ${status} ${HARBOR_IP} + Sleep 30s + END Fail Harbor failed to come up properly! Get Harbor Version diff --git a/tests/resources/SeleniumUtil.robot b/tests/resources/SeleniumUtil.robot index 420e8a7c2..06f965a1c 100644 --- a/tests/resources/SeleniumUtil.robot +++ b/tests/resources/SeleniumUtil.robot @@ -37,12 +37,13 @@ Init Chrome Driver Call Method ${chrome options} add_argument --window-size\=1600,900 ${chrome options.binary_location} Set Variable /usr/bin/google-chrome #Create Webdriver Chrome Chrome_headless chrome_options=${chrome options} desired_capabilities=${capabilities} - :For ${n} IN RANGE 1 6 - \ Log To Console Trying Create Webdriver ${n} times ... - \ ${out} Run Keyword And Ignore Error Create Webdriver Chrome Chrome_headless chrome_options=${chrome options} desired_capabilities=${capabilities} - \ Log To Console Return value is ${out[0]} - \ Exit For Loop If '${out[0]}'=='PASS' - \ Sleep 2 + FOR ${n} IN RANGE 1 6 + Log To Console Trying Create Webdriver ${n} times ... + ${out} Run Keyword And Ignore Error Create Webdriver Chrome Chrome_headless chrome_options=${chrome options} desired_capabilities=${capabilities} + Log To Console Return value is ${out[0]} + Exit For Loop If '${out[0]}'=='PASS' + Sleep 2 + END Run Keyword If '${out[0]}'=='FAIL' Capture Page Screenshot Should Be Equal As Strings '${out[0]}' 'PASS' Sleep 5 diff --git a/tests/resources/TestCaseBody.robot b/tests/resources/TestCaseBody.robot index b3c6533ab..d7e1c6cd5 100644 --- a/tests/resources/TestCaseBody.robot +++ b/tests/resources/TestCaseBody.robot @@ -186,7 +186,7 @@ Manage Project Member Without Sign In Harbor [Arguments] ${sign_in_user} ${sign_in_pwd} ${test_user1}=user005 ${test_user2}=user006 ${is_oidc_mode}=${false} ${d}= Get current Date result_format=%m%s Create An New Project And Go Into Project project${d} - Push image ip=${ip} user=${sign_in_user} pwd=${sign_in_pwd} project=project${d} image=hello-world + Push image ${ip} ${sign_in_user} ${sign_in_pwd} project${d} hello-world Logout Harbor User Should Not Be A Member Of Project ${test_user1} ${sign_in_pwd} project${d} is_oidc_mode=${is_oidc_mode} @@ -200,7 +200,7 @@ Manage Project Member Without Sign In Harbor User Should Be Master ${test_user1} ${sign_in_pwd} project${d} is_oidc_mode=${is_oidc_mode} Manage Project Member ${sign_in_user} ${sign_in_pwd} project${d} ${test_user1} Remove is_oidc_mode=${is_oidc_mode} User Should Not Be A Member Of Project ${test_user1} ${sign_in_pwd} project${d} is_oidc_mode=${is_oidc_mode} - Push image ip=${ip} user=${sign_in_user} pwd=${sign_in_pwd} project=project${d} image=hello-world + Push image ${ip} ${sign_in_user} ${sign_in_pwd} project${d} hello-world User Should Be Guest ${test_user2} ${sign_in_pwd} project${d} is_oidc_mode=${is_oidc_mode} Helm CLI Push Without Sign In Harbor @@ -254,7 +254,7 @@ Body Of Verfiy System Level CVE Whitelist # Add Items To System CVE Whitelist CVE-2019-18276 Add Items To System CVE Whitelist ${single_cve} Pull Image ${ip} ${signin_user} ${signin_pwd} project${d} ${image} tag=${sha256} - Delete Top Item In System CVE Whitelist count=6 + Delete Top Item In System CVE Whitelist count=16 Cannot Pull Image ${ip} ${signin_user} ${signin_pwd} project${d} ${image} tag=${sha256} err_msg=cannot be pulled due to configured policy Close Browser @@ -315,3 +315,31 @@ Body Of Verfiy Project Level CVE Whitelist By Quick Way of Add System Add System CVE Whitelist to Project CVE Whitelist By Add System Button Click Pull Image ${ip} ${signin_user} ${signin_pwd} project${d} ${image} tag=${sha256} Close Browser + +Body Of Replication Of Push Images to Registry Triggered By Event + [Arguments] ${provider} ${endpoint} ${username} ${pwd} ${dest_namespace} + Init Chrome Driver + ${d}= Get Current Date result_format=%m%s + ${sha256}= Set Variable 0e67625224c1da47cb3270e7a861a83e332f708d3d89dde0cbed432c94824d9a + ${image}= Set Variable test_push_repli + ${tag1}= Set Variable v1.1.0 + @{tags} Create List ${tag1} + #login source + Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} + Create An New Project And Go Into Project project${d} + Switch To Registries + Create A New Endpoint ${provider} e${d} ${endpoint} ${username} ${pwd} Y + Switch To Replication Manage + Create A Rule With Existing Endpoint rule${d} push project${d}/* image e${d} ${dest_namespace} mode=Event Based del_remote=${true} + Push Special Image To Project project${d} ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} ${image} tags=@{tags} size=12 + Filter Replication Rule rule${d} + Select Rule rule${d} + Run Keyword If '${provider}'=='docker-hub' Docker Image Can Be Pulled ${dest_namespace}/${image}:${tag1} times=3 + Executions Result Count Should Be Succeeded event_based 1 + Go Into Project project${d} + Delete Repo project${d} + Run Keyword If '${provider}'=='docker-hub' Docker Image Can Not Be Pulled ${dest_namespace}/${image}:${tag1} + Switch To Replication Manage + Filter Replication Rule rule${d} + Select Rule rule${d} + Executions Result Count Should Be Succeeded event_based 2 \ No newline at end of file diff --git a/tests/resources/Util.robot b/tests/resources/Util.robot index acbdd3e2e..48b043623 100644 --- a/tests/resources/Util.robot +++ b/tests/resources/Util.robot @@ -20,7 +20,7 @@ Library requests Library Process Library SSHLibrary 1 minute Library DateTime -Library Selenium2Library 60 10 +Library SeleniumLibrary 60 10 Library JSONLibrary Resource Nimbus-Util.robot Resource Vsphere-Util.robot @@ -206,16 +206,18 @@ Text Input Clear Field Of Characters [Arguments] ${field} ${character count} [Documentation] This keyword pushes the delete key (ascii: \8) a specified number of times in a specified field. - : FOR ${index} IN RANGE ${character count} - \ Press Keys ${field} \\8 + FOR ${index} IN RANGE ${character count} + Press Keys ${field} \\8 + END Wait Unitl Command Success [Arguments] ${cmd} ${times}=8 - :FOR ${n} IN RANGE 1 ${times} - \ Log Trying ${cmd}: ${n} ... console=True - \ ${rc} ${output}= Run And Return Rc And Output ${cmd} - \ Exit For Loop If '${rc}'=='0' - \ Sleep 2 + FOR ${n} IN RANGE 1 ${times} + Log Trying ${cmd}: ${n} ... console=True + ${rc} ${output}= Run And Return Rc And Output ${cmd} + Exit For Loop If '${rc}'=='0' + Sleep 2 + END Log Command Result is ${output} Should Be Equal As Strings '${rc}' '0' [Return] ${output} @@ -229,41 +231,45 @@ Command Should be Failed Retry Keyword N Times When Error [Arguments] ${times} ${keyword} @{elements} - :For ${n} IN RANGE 1 ${times} - \ Log To Console Trying ${keyword} elements @{elements} ${n} times ... - \ ${out} Run Keyword And Ignore Error ${keyword} @{elements} - \ Log To Console Return value is ${out} and ${out[0]} - \ Run Keyword If '${keyword}'=='Make Swagger Client' Exit For Loop If '${out[0]}'=='PASS' and '${out[1]}'=='0' - \ ... ELSE Exit For Loop If '${out[0]}'=='PASS' - \ Sleep 10 + FOR ${n} IN RANGE 1 ${times} + Log To Console Trying ${keyword} elements @{elements} ${n} times ... + ${out} Run Keyword And Ignore Error ${keyword} @{elements} + Log To Console Return value is ${out} and ${out[0]} + Capture Page Screenshot record.png + Run Keyword If '${keyword}'=='Make Swagger Client' Exit For Loop If '${out[0]}'=='PASS' and '${out[1]}'=='0' + ... ELSE Exit For Loop If '${out[0]}'=='PASS' + Sleep 10 + END Run Keyword If '${out[0]}'=='FAIL' Capture Page Screenshot Should Be Equal As Strings '${out[0]}' 'PASS' [Return] ${out[1]} Retry Keyword When Return Value Mismatch [Arguments] ${keyword} ${expected_value} ${count} @{elements} - :For ${n} IN RANGE 1 ${count} - \ Log To Console Trying ${keyword} ${n} times ... - \ ${out} Run Keyword And Ignore Error ${keyword} @{elements} - \ Log To Console Return value is ${out[1]} - \ ${status}= Set Variable If '${out[1]}'=='${expected_value}' 'PASS' 'FAIL' - \ Exit For Loop If '${out[1]}'=='${expected_value}' - \ Sleep 2 + FOR ${n} IN RANGE 1 ${count} + Log To Console Trying ${keyword} ${n} times ... + ${out} Run Keyword And Ignore Error ${keyword} @{elements} + Log To Console Return value is ${out[1]} + ${status}= Set Variable If '${out[1]}'=='${expected_value}' 'PASS' 'FAIL' + Exit For Loop If '${out[1]}'=='${expected_value}' + Sleep 2 + END Run Keyword If ${status}=='FAIL' Capture Page Screenshot Should Be Equal As Strings ${status} 'PASS' Retry Double Keywords When Error [Arguments] ${keyword1} ${element1} ${keyword2} ${element2} ${DoAssert}=${true} ${times}=3 - :For ${n} IN RANGE 1 ${times} - \ Log To Console Trying ${keyword1} and ${keyword2} ${n} times ... - \ ${out1} Run Keyword And Ignore Error ${keyword1} ${element1} - \ Capture Page Screenshot - \ Sleep 1 - \ ${out2} Run Keyword And Ignore Error ${keyword2} ${element2} - \ Capture Page Screenshot - \ Log To Console Return value is ${out1[0]} ${out2[0]} - \ Exit For Loop If '${out2[0]}'=='PASS' - \ Sleep 1 + FOR ${n} IN RANGE 1 ${times} + Log To Console Trying ${keyword1} and ${keyword2} ${n} times ... + ${out1} Run Keyword And Ignore Error ${keyword1} ${element1} + Capture Page Screenshot + Sleep 1 + ${out2} Run Keyword And Ignore Error ${keyword2} ${element2} + Capture Page Screenshot + Log To Console Return value is ${out1[0]} ${out2[0]} + Exit For Loop If '${out2[0]}'=='PASS' + Sleep 1 + END Return From Keyword If ${DoAssert} == ${false} '${out2[0]}' Should Be Equal As Strings '${out2[0]}' 'PASS' diff --git a/tests/resources/Vsphere-Util.robot b/tests/resources/Vsphere-Util.robot index 03d9ef2bd..f95d1d878 100644 --- a/tests/resources/Vsphere-Util.robot +++ b/tests/resources/Vsphere-Util.robot @@ -61,22 +61,24 @@ Reset VM Wait Until VM Powers On [Arguments] ${vm} ${vc_host} ${vc_user} ${vc_password} - :FOR ${idx} IN RANGE 0 30 - \ ${ret}= Run GOVC_URL=${vc_host} GOVC_USERNAME=${vc_user} GOVC_PASSWORD=${vc_password} GOVC_INSECURE=1 govc vm.info ${vm} - \ Set Test Variable ${out} ${ret} - \ ${status}= Run Keyword And Return Status Should Contain ${out} poweredOn - \ Return From Keyword If ${status} - \ Sleep 1 + FOR ${idx} IN RANGE 0 30 + ${ret}= Run GOVC_URL=${vc_host} GOVC_USERNAME=${vc_user} GOVC_PASSWORD=${vc_password} GOVC_INSECURE=1 govc vm.info ${vm} + Set Test Variable ${out} ${ret} + ${status}= Run Keyword And Return Status Should Contain ${out} poweredOn + Return From Keyword If ${status} + Sleep 1 + END Fail VM did not power on within 30 seconds Wait Until VM Powers Off [Arguments] ${vm} ${vc_host} ${vc_user} ${vc_password} - :FOR ${idx} IN RANGE 0 30 - \ ${ret}= Run GOVC_URL=${vc_host} GOVC_USERNAME=${vc_user} GOVC_PASSWORD=${vc_password} GOVC_INSECURE=1 govc vm.info ${vm} - \ Set Test Variable ${out} ${ret} - \ ${status}= Run Keyword And Return Status Should Contain ${out} poweredOff - \ Return From Keyword If ${status} - \ Sleep 1 + FOR ${idx} IN RANGE 0 30 + ${ret}= Run GOVC_URL=${vc_host} GOVC_USERNAME=${vc_user} GOVC_PASSWORD=${vc_password} GOVC_INSECURE=1 govc vm.info ${vm} + Set Test Variable ${out} ${ret} + ${status}= Run Keyword And Return Status Should Contain ${out} poweredOff + Return From Keyword If ${status} + Sleep 1 + END Fail VM did not power off within 30 seconds Wait Until VM Is Destroyed diff --git a/tests/robot-cases/Group0-Util/notary-remove-image-signature.expect b/tests/robot-cases/Group0-Util/notary-remove-image-signature.expect index c98b9261e..7ee0a30fa 100755 --- a/tests/robot-cases/Group0-Util/notary-remove-image-signature.expect +++ b/tests/robot-cases/Group0-Util/notary-remove-image-signature.expect @@ -1,4 +1,4 @@ -#!/usr/local/bin/expect +#!/usr/bin/env expect set HOST [lindex $argv 0] set PROJECT [lindex $argv 1] diff --git a/tests/robot-cases/Group1-Nightly/Common.robot b/tests/robot-cases/Group1-Nightly/Common.robot index 0af7b01de..ac089a8f8 100644 --- a/tests/robot-cases/Group1-Nightly/Common.robot +++ b/tests/robot-cases/Group1-Nightly/Common.robot @@ -443,20 +443,20 @@ Test Case - Create An New Project With Quotas Set Test Case - Project Storage Quotas Dispaly And Control Init Chrome Driver ${d}= Get Current Date result_format=%m%s - ${storage_quota}= Set Variable 330 + ${storage_quota}= Set Variable 350 ${storage_quota_unit}= Set Variable MB - ${image_a}= Set Variable redis - ${image_b}= Set Variable logstash - ${image_a_size}= Set Variable 34.15MB - ${image_b_size}= Set Variable 321.03MB - ${image_a_ver}= Set Variable donotremove5.0 - ${image_b_ver}= Set Variable do_not_remove_6.8.3 + ${image_a}= Set Variable one_layer + ${image_b}= Set Variable redis + ${image_a_size}= Set Variable 330.83MB + ${image_b_size}= Set Variable 34.15MB + ${image_a_ver}= Set Variable 1.0 + ${image_b_ver}= Set Variable donotremove5.0 Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Create An New Project And Go Into Project project${d} storage_quota=${storage_quota} storage_quota_unit=${storage_quota_unit} Push Image With Tag ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} project${d} ${image_b} tag=${image_b_ver} tag1=${image_b_ver} ${storage_quota_ret}= Get Project Storage Quota Text From Project Quotas List project${d} Should Be Equal As Strings ${storage_quota_ret} ${image_b_size} of ${storage_quota}${storage_quota_unit} - Cannot Push image ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} project${d} ${image_a}:${image_a_ver} err_msg=adding 25.8 MiB of storage resource, which when updated to current usage of err_msg_2=MiB will exceed the configured upper limit of 330.0 MiB + Cannot Push image ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} project${d} ${image_a}:${image_a_ver} err_msg=adding 330.1 MiB of storage resource, which when updated to current usage of err_msg_2=MiB will exceed the configured upper limit of ${storage_quota}.0 MiB Go Into Project project${d} Delete Repo project${d}/${image_b} Push Image With Tag ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} project${d} ${image_a} tag=${image_a_ver} tag1=${image_a_ver} diff --git a/tests/robot-cases/Group1-Nightly/Common_GC.robot b/tests/robot-cases/Group1-Nightly/Common_GC.robot index 28f3ba0b2..21da203af 100644 --- a/tests/robot-cases/Group1-Nightly/Common_GC.robot +++ b/tests/robot-cases/Group1-Nightly/Common_GC.robot @@ -30,13 +30,14 @@ Test Case - Garbage Collection Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Create An New Project And Go Into Project project${d} - Push Image ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} project${d} hello-world + Push Image ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} project${d} redis Sleep 2 Go Into Project project${d} Delete Repo project${d} Sleep 2 GC Now ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} - Retry GC Should Be Successful 1 0 blobs marked, 3 blobs and 0 manifests eligible for deletion + Retry GC Should Be Successful 1 8 blobs and 0 manifests eligible for deletion + #Retry GC Should Be Successful 1 The GC job actual frees up 34 MB space Close Browser Test Case - GC Untagged Images diff --git a/tests/robot-cases/Group1-Nightly/OIDC.robot b/tests/robot-cases/Group1-Nightly/OIDC.robot index d98d4bb0b..7a9fb38c8 100644 --- a/tests/robot-cases/Group1-Nightly/OIDC.robot +++ b/tests/robot-cases/Group1-Nightly/OIDC.robot @@ -75,7 +75,7 @@ Test Case - Generate User CLI Secret Sign In Harbor With OIDC User ${HARBOR_URL} Create An New Project And Go Into Project project${d} ${secret_old}= Get Secrete By API ${HARBOR_URL} - Push image ip=${ip} user=${OIDC_USERNAME} pwd=${secret_old} project=project${d} image=${image} + Push image ${ip} ${OIDC_USERNAME} ${secret_old} project${d} ${image} ${secret_new}= Generate And Return Secret ${HARBOR_URL} Log To Console ${secret_old} Log To Console ${secret_new} diff --git a/tests/robot-cases/Group1-Nightly/Replication.robot b/tests/robot-cases/Group1-Nightly/Replication.robot index fad0e7f6c..aea89a8ef 100644 --- a/tests/robot-cases/Group1-Nightly/Replication.robot +++ b/tests/robot-cases/Group1-Nightly/Replication.robot @@ -14,7 +14,7 @@ *** Settings *** Documentation Harbor BATs -Library ../../apitests/python/library/Harbor.py ${SERVER_CONFIG} +Library ../../apitests/python/library/repository.py Resource ../../resources/Util.robot Default Tags Replication @@ -115,7 +115,7 @@ Test Case - Replication Rule Edit Retry Text Input ${rule_name_input} ${rule_name_new} Select Source Registry ${endpoint2} #Source Resource Filter - Retry Text Input ${source_project} project${d} + Retry Text Input ${filter_name_id} project${d} Select From List By Value ${rule_resource_selector} ${resource_type} Retry Text Input ${dest_namespace_xpath} ${dest_namespace} Select Trigger ${mode} @@ -125,7 +125,7 @@ Test Case - Replication Rule Edit Edit Replication Rule By Name ${rule_name_new} Retry Textfield Value Should Be ${rule_name_input} ${rule_name_new} Retry List Selection Should Be ${src_registry_dropdown_list} ${endpoint2}-https://${ip} - Retry Textfield Value Should Be ${source_project} project${d} + Retry Textfield Value Should Be ${filter_name_id} project${d} Retry Textfield Value Should Be ${dest_namespace_xpath} ${dest_namespace} Retry List Selection Should Be ${rule_resource_selector} ${resource_type} Retry List Selection Should Be ${rule_trigger_select} ${mode} @@ -156,7 +156,7 @@ Test Case - Replication Of Pull Images from DockerHub To Self Switch To Registries Create A New Endpoint docker-hub e${d} https://hub.docker.com/ danfengliu Aa123456 Y Switch To Replication Manage - Create A Rule With Existing Endpoint rule${d} pull danfengliu/* image e${d} project${d} + Create A Rule With Existing Endpoint rule${d} pull danfengliu/{cent*,mariadb} image e${d} project${d} Select Rule And Replicate rule${d} #In docker-hub, under repository danfengliu, there're only 2 images: centos,mariadb. Image Should Be Replicated To Project project${d} centos @@ -268,8 +268,18 @@ Test Case - Replication Of Pull Images from Google-GCR To Self Create A New Endpoint google-gcr e${d} asia.gcr.io ${null} ${gcr_ac_key} Y Switch To Replication Manage Create A Rule With Existing Endpoint rule${d} pull eminent-nation-87317/* image e${d} project${d} - Filter Replicatin Rule rule${d} + Filter Replication Rule rule${d} Select Rule And Replicate rule${d} Image Should Be Replicated To Project project${d} httpd Image Should Be Replicated To Project project${d} tomcat Close Browser + +Test Case - Replication Of Push Images to DockerHub Triggered By Event + Body Of Replication Of Push Images to Registry Triggered By Event docker-hub https://hub.docker.com/ danfengliu Aa123456 danfengliu + +#Due to issue of delete event replication +#Test Case - Replication Of Push Images to Google-GCR Triggered By Event + #Body Of Replication Of Push Images to Registry Triggered By Event google-gcr gcr.io ${null} ${gcr_ac_key} eminent-nation-87317/harbor-nightly-replication + +Test Case - Replication Of Push Images to AWS-ECR Triggered By Event + Body Of Replication Of Push Images to Registry Triggered By Event aws-ecr us-east-2 ${ecr_ac_id} ${ecr_ac_key} harbor-nightly-replication \ No newline at end of file diff --git a/tests/robot-cases/Group3-Upgrade/data.json b/tests/robot-cases/Group3-Upgrade/data.json index c516ae7f7..8aadc1e44 100644 --- a/tests/robot-cases/Group3-Upgrade/data.json +++ b/tests/robot-cases/Group3-Upgrade/data.json @@ -216,6 +216,7 @@ "repository_patten":"*photon*", "tag_decoration":"*v1.*", "latestPushedK":666, + "latestPushedK_verify":"666", "cron":"0 0 0 1 8 0" }, "tag_immutability_rule":{ @@ -347,6 +348,7 @@ "repository_patten":"*centos*", "tag_decoration":"*latest", "latestPushedK":999, + "latestPushedK_verify":"999", "cron":"0 0 0 1 6 0" }, "tag_immutability_rule":{ diff --git a/tests/robot-cases/Group3-Upgrade/prepare.py b/tests/robot-cases/Group3-Upgrade/prepare.py index a86fe8f05..7d6cb4be5 100644 --- a/tests/robot-cases/Group3-Upgrade/prepare.py +++ b/tests/robot-cases/Group3-Upgrade/prepare.py @@ -14,7 +14,7 @@ args = parser.parse_args() url = "https://"+args.endpoint+"/api/" endpoint_url = "https://"+args.endpoint -print url +print(url) with open("feature_map.json") as f: feature_map = json.load(f) @@ -108,7 +108,7 @@ class HarborAPI: "url":""+endpointurl+"" } body=dict(body=payload) - print body + print(body) request(url+"/registries", 'post', **body) else: raise Exception(r"Error: Feature {} has no branch {}.".format(sys._getframe().f_code.co_name, branch)) @@ -131,8 +131,8 @@ class HarborAPI: else: registry = r'"dest_registry": { "id": '+str(targetid)+r'},' - body=dict(body=json.loads(r'{"name":"'+replicationrule["rulename"].encode('utf-8')+r'","dest_namespace":"'+replicationrule["dest_namespace"].encode('utf-8')+r'","deletion": '+str(replicationrule["deletion"]).lower()+r',"enabled": '+str(replicationrule["enabled"]).lower()+r',"override": '+str(replicationrule["override"]).lower()+r',"description": "string",'+ registry + r'"trigger":{"type": "'+replicationrule["trigger_type"]+r'", "trigger_settings":{"cron":"'+replicationrule["cron"]+r'"}},"filters":[ {"type":"name","value":"'+replicationrule["name_filters"]+r'"},{"type":"tag","value":"'+replicationrule["tag_filters"]+r'"}]}')) - print body + body=dict(body=json.loads(r'{"name":"'+replicationrule["rulename"]+r'","dest_namespace":"'+replicationrule["dest_namespace"]+r'","deletion": '+str(replicationrule["deletion"]).lower()+r',"enabled": '+str(replicationrule["enabled"]).lower()+r',"override": '+str(replicationrule["override"]).lower()+r',"description": "string",'+ registry + r'"trigger":{"type": "'+replicationrule["trigger_type"]+r'", "trigger_settings":{"cron":"'+replicationrule["cron"]+r'"}},"filters":[ {"type":"name","value":"'+replicationrule["name_filters"]+r'"},{"type":"tag","value":"'+replicationrule["tag_filters"]+r'"}]}')) + print(body) request(url+"replication/policies", 'post', **body) else: raise Exception(r"Error: Feature {} has no branch {}.".format(sys._getframe().f_code.co_name, branch)) @@ -151,7 +151,7 @@ class HarborAPI: } } body=dict(body=payload) - print body + print(body) request(url+"projects/"+projectid+"", 'put', **body) @get_feature_branch @@ -162,7 +162,7 @@ class HarborAPI: cve_id_str = cve_id_str + '{"cve_id":"' +cve_id["id"] + '"}' if index != len(cve_id_list["cve"]) - 1: cve_id_str = cve_id_str + "," - body=dict(body=json.loads(r'{"items":['+cve_id_str.encode('utf-8')+r'],"expires_at":'+cve_id_list["expires_at"]+'}')) + body=dict(body=json.loads(r'{"items":['+cve_id_str+r'],"expires_at":'+cve_id_list["expires_at"]+'}')) request(url+"system/CVEWhitelist", 'put', **body) else: raise Exception(r"Error: Feature {} has no branch {}.".format(sys._getframe().f_code.co_name, branch)) @@ -177,12 +177,12 @@ class HarborAPI: cve_id_str = cve_id_str + '{"cve_id":"' +cve_id["id"] + '"}' if index != len(cve_id_list["cve"]) - 1: cve_id_str = cve_id_str + "," - print cve_id_str + print(cve_id_str) if reuse_sys_cve_whitelist == "true": payload = r'{"metadata":{"reuse_sys_cve_whitelist":"true"}}' else: - payload = r'{"metadata":{"reuse_sys_cve_whitelist":"false"},"cve_whitelist":{"project_id":'+projectid+',"items":['+cve_id_str.encode('utf-8')+r'],"expires_at":'+cve_id_list["expires_at"]+'}}' - print payload + payload = r'{"metadata":{"reuse_sys_cve_whitelist":"false"},"cve_whitelist":{"project_id":'+projectid+',"items":['+cve_id_str+r'],"expires_at":'+cve_id_list["expires_at"]+'}}' + print(payload) body=dict(body=json.loads(payload)) request(url+"projects/"+projectid+"", 'put', **body) else: @@ -191,7 +191,7 @@ class HarborAPI: @get_feature_branch def update_interrogation_services(self, cron, **kwargs): payload = {"schedule":{"type":"Custom","cron": cron}} - print payload + print(payload) body=dict(body=payload) request(url+"system/scanAll/schedule", 'post', **body) @@ -217,7 +217,7 @@ class HarborAPI: } } } - print payload + print(payload) body=dict(body=payload) request(url+"configurations", 'put', **body) @@ -256,7 +256,7 @@ class HarborAPI: raise Exception(r"Error: Robot account count {} is not legal!".format(len(robot_account["access"]))) else: raise Exception(r"Error: Feature {} has no branch {}.".format(sys._getframe().f_code.co_name, branch)) - print payload + print(payload) body=dict(body=payload) request(url+"projects/"+projectid+"/robots", 'post', **body) @@ -306,7 +306,7 @@ class HarborAPI: "ref":int(projectid) } } - print payload + print(payload) body=dict(body=payload) request(url+"retentions", 'post', **body) else: @@ -343,7 +343,7 @@ class HarborAPI: "priority":0, "template":"immutable_template" } - print payload + print(payload) body=dict(body=payload) request(url+"projects/"+projectid+"/immutabletagrules", 'post', **body) else: @@ -375,7 +375,7 @@ class HarborAPI: ], "enabled":webhook["enabled"] } - print payload + print(payload) body=dict(body=payload) request(url+"projects/"+projectid+"/webhook/policies", 'post', **body) else: @@ -383,7 +383,7 @@ class HarborAPI: def update_repoinfo(self, reponame): payload = {"description": "testdescription"} - print payload + print(payload) body=dict(body=payload) request(url+"repositories/"+reponame+"", 'put', **body) @@ -398,10 +398,10 @@ class HarborAPI: if not os.path.exists(ca_path): try: os.makedirs(ca_path) - except Exception, e: - print str(e) + except Exception as e: + print(str(e)) pass - open(target, 'wb').write(ca_content) + open(target, 'wb').write(ca_content.encode('utf-8')) def request(url, method, user = None, userp = None, **kwargs): @@ -415,7 +415,7 @@ def request(url, method, user = None, userp = None, **kwargs): kwargs['headers']['Content-Type'] = 'application/json' kwargs['data'] = json.dumps(kwargs['body']) del kwargs['body'] - print "url: ", url + print("url: ", url) resp = requests.request(method, url, verify=False, auth=(user, userp), **kwargs) if resp.status_code >= 400: raise Exception("[Exception Message] - {}".format(resp.text))