Add script of push cnab bunlde API test

Signed-off-by: danfengliu <danfengl@vmware.com>
This commit is contained in:
danfengliu 2020-03-07 11:15:19 +08:00
parent 2615339f4c
commit 843b05c2d3
11 changed files with 182 additions and 19 deletions

View File

@ -109,6 +109,7 @@ jobs:
cd src/github.com/goharbor/harbor cd src/github.com/goharbor/harbor
pwd pwd
go env go env
echo "::set-env name=CNAB_PATH::$(go env GOPATH)/src/github.com/docker"
echo "::set-env name=GOPATH::$(go env GOPATH):$GITHUB_WORKSPACE" echo "::set-env name=GOPATH::$(go env GOPATH):$GITHUB_WORKSPACE"
echo "::add-path::$(go env GOPATH)/bin" echo "::add-path::$(go env GOPATH)/bin"
echo "::set-env name=TOKEN_PRIVATE_KEY_PATH::${GITHUB_WORKSPACE}/src/github.com/goharbor/harbor/tests/private_key.pem" echo "::set-env name=TOKEN_PRIVATE_KEY_PATH::${GITHUB_WORKSPACE}/src/github.com/goharbor/harbor/tests/private_key.pem"
@ -130,9 +131,14 @@ jobs:
sudo cp ./tests/harbor_ca.crt /usr/local/share/ca-certificates/ sudo cp ./tests/harbor_ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates sudo update-ca-certificates
sudo service docker restart sudo service docker restart
wget https://get.helm.sh/helm-v3.1.1-linux-386.tar.gz && tar zxvf helm-v3.1.1-linux-386.tar.gz && \ wget https://get.helm.sh/helm-v3.1.1-linux-386.tar.gz && tar zxvf helm-v3.1.1-linux-386.tar.gz
sudo mv linux-386/helm /usr/local/bin/helm3 && \ sudo mv linux-386/helm /usr/local/bin/helm3
helm3 plugin install https://github.com/chartmuseum/helm-push helm3 plugin install https://github.com/chartmuseum/helm-push
mkdir -p $CNAB_PATH && cd $CNAB_PATH && git clone https://github.com/cnabio/cnab-to-oci.git
cd cnab-to-oci && git checkout v0.3.0-beta4
go list
make build
sudo mv bin/cnab-to-oci /usr/local/bin
- name: install - name: install
run: | run: |
cd src/github.com/goharbor/harbor cd src/github.com/goharbor/harbor

View File

@ -0,0 +1 @@
{"actions":{"io.cnab.status":{}},"definitions":{"port":{"default":"8080","type":"string"},"text":{"default":"Hello, World!","type":"string"}},"description":"Hello, World!","images":{"hello":{"contentDigest":"sha256:61d5cb94d7e546518a7bbd5bee06bfad0ecea8f56a75b084522a43dccbbcd845","description":"hello","image":"{{ .ServiceImage }}","imageType":"docker","mediaType":"application/vnd.docker.distribution.manifest.v2+json","size":528}},"invocationImages":[{"contentDigest":"sha256:61d5cb94d7e546518a7bbd5bee06bfad0ecea8f56a75b084522a43dccbbcd845","image":"{{ .InvocationImage }}","imageType":"docker","mediaType":"application/vnd.docker.distribution.manifest.v2+json","size":941}],"maintainers":[{"email":"user@email.com","name":"user"}],"name":"hello-world","parameters":{"fields":{"definition":"","destination":null}},"schemaVersion":"v1.0.0","version":"0.1.0"}

View File

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
import base
import json
import docker_api
def load_bundle(service_image, invocation_image):
bundle_file = "./tests/apitests/python/bundle_data/bundle.json"
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()
return bundle_file
def cnab_fixup_bundle(bundle_file, target, auto_update_bundle = True):
fixed_bundle_file = "./tests/apitests/python/bundle_data/fixed-bundle.json"
command = ["sudo", "cnab-to-oci", "--log-level", "debug", "fixup", bundle_file, "--target", target, "--bundle", fixed_bundle_file]
if auto_update_bundle == True:
command.append("--auto-update-bundle")
#fixed_bundle_file = bundle_file
print "Command: ", command
ret = base.run_command(command)
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
ret = base.run_command(command)
print "Command return: ", ret
for line in ret.split("\n"):
line = line.replace('\"', '')
if line.find('sha256') >= 0:
return line[-71:]
raise Exception(r"Fail to get sha256 in returned data: {}".format(ret))
def push_cnab_bundle(harbor_server, user, password, service_image, invocation_image, target, auto_update_bundle = True):
docker_api.docker_login(harbor_server, user, password, enable_manifest = False)
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

View File

@ -10,14 +10,15 @@ except ImportError:
pip.main(['install', 'docker']) pip.main(['install', 'docker'])
import docker import docker
def docker_login(harbor_host, user, password): def docker_login(harbor_host, user, password, enable_manifest = True):
command = ["sudo", "docker", "login", harbor_host, "-u", user, "-p", password] command = ["sudo", "docker", "login", harbor_host, "-u", user, "-p", password]
print "Docker Login Command: ", command print "Docker Login Command: ", command
base.run_command(command) base.run_command(command)
try: if enable_manifest == True:
ret = subprocess.check_output(["./tests/apitests/python/update_docker_cfg.sh"], shell=False) try:
except subprocess.CalledProcessError, exc: subprocess.check_output(["./tests/apitests/python/update_docker_cfg.sh"], shell=False)
raise Exception("Failed to update docker config, error is {} {}.".format(exc.returncode, exc.output)) except subprocess.CalledProcessError, exc:
raise Exception("Failed to update docker config, error is {} {}.".format(exc.returncode, exc.output))
def docker_manifest_create(index, manifests): def docker_manifest_create(index, manifests):
command = ["sudo", "docker","manifest","create",index] command = ["sudo", "docker","manifest","create",index]
@ -149,6 +150,9 @@ class DockerAPI(object):
print("build image %s with size %d" % (repo, size)) print("build image %s with size %d" % (repo, size))
self.DCLIENT.remove_image(repo) self.DCLIENT.remove_image(repo)
self.DCLIENT.remove_container(c) self.DCLIENT.remove_container(c)
self.DCLIENT.pull(repo)
image = self.DCLIENT2.images.get(repo)
return repo, image.id
except Exception, err: except Exception, err:
caught_err = True caught_err = True
if expected_error_message is not None: if expected_error_message is not None:
@ -165,5 +169,3 @@ class DockerAPI(object):
else: else:
if str(ret).lower().find("errorDetail".lower()) >= 0: if str(ret).lower().find("errorDetail".lower()) >= 0:
raise Exception(r" It's was not suppose to catch error when push image {}, return message is [{}]".format (harbor_registry, ret)) raise Exception(r" It's was not suppose to catch error when push image {}, return message is [{}]".format (harbor_registry, ret))

View File

@ -37,7 +37,7 @@ def push_special_image_to_project(project_name, registry, username, password, im
time.sleep(2) time.sleep(2)
if expected_login_error_message != None: 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=size, expected_error_message=expected_error_message)
def is_repo_exist_in_project(repositories, repo_name): def is_repo_exist_in_project(repositories, repo_name):
result = False result = False
@ -78,12 +78,18 @@ class Repository(base.Base):
_, status_code, _ = client.delete_repository_with_http_info(project_name, repo_name) _, status_code, _ = client.delete_repository_with_http_info(project_name, repo_name)
base._assert_status_code(200, status_code) base._assert_status_code(200, status_code)
def get_repository(self, project_name, **kwargs): def list_repositories(self, project_name, **kwargs):
client = self._get_client(**kwargs) client = self._get_client(**kwargs)
data, status_code, _ = client.list_repositories_with_http_info(project_name) data, status_code, _ = client.list_repositories_with_http_info(project_name)
base._assert_status_code(200, status_code) base._assert_status_code(200, status_code)
return data return data
def get_repository(self, project_name, repo_name, **kwargs):
client = self._get_client(**kwargs)
data, status_code, _ = client.get_repository_with_http_info(project_name, repo_name)
base._assert_status_code(200, status_code)
return data
def add_label_to_tag(self, repo_name, tag, label_id, expect_status_code = 200, **kwargs): def add_label_to_tag(self, repo_name, tag, label_id, expect_status_code = 200, **kwargs):
client = self._get_client(**kwargs) client = self._get_client(**kwargs)
label = swagger_client.Label(id=label_id) label = swagger_client.Label(id=label_id)
@ -122,7 +128,7 @@ class Repository(base.Base):
return data return data
def repository_should_exist(self, project_id, repo_name, **kwargs): def repository_should_exist(self, project_id, repo_name, **kwargs):
repositories = self.get_repository(project_id, **kwargs) repositories = self.list_repositories(project_id, **kwargs)
if is_repo_exist_in_project(repositories, repo_name) == False: if is_repo_exist_in_project(repositories, repo_name) == False:
raise Exception("Repository {} is not exist.".format(repo_name)) raise Exception("Repository {} is not exist.".format(repo_name))

View File

@ -91,7 +91,7 @@ class TestProjects(unittest.TestCase):
TestProjects.src_repo_name, tag_name = push_image_to_project(TestProjects.project_src_repo_name, harbor_server, 'admin', 'Harbor12345', "hello-world", pull_tag_name) TestProjects.src_repo_name, tag_name = push_image_to_project(TestProjects.project_src_repo_name, harbor_server, 'admin', 'Harbor12345', "hello-world", pull_tag_name)
#6. Get repository in project(PA), there should be one repository which was created by user(UA); #6. Get repository in project(PA), there should be one repository which was created by user(UA);
src_repo_data = self.repo.get_repository(TestProjects.project_src_repo_name, **TestProjects.USER_RETAG_CLIENT) src_repo_data = self.repo.list_repositories(TestProjects.project_src_repo_name, **TestProjects.USER_RETAG_CLIENT)
_assert_status_code(TestProjects.src_repo_name, src_repo_data[0].name) _assert_status_code(TestProjects.src_repo_name, src_repo_data[0].name)
#7. Get repository(RA)'s image tag detail information; #7. Get repository(RA)'s image tag detail information;

View File

@ -62,14 +62,14 @@ class TestProjects(unittest.TestCase):
repo_name, _ = push_image_to_project(TestProjects.project_del_repo_name, harbor_server, 'admin', 'Harbor12345', "hello-world", "latest") repo_name, _ = push_image_to_project(TestProjects.project_del_repo_name, harbor_server, 'admin', 'Harbor12345', "hello-world", "latest")
#4. Get repository in project(PA), there should be one repository which was created by user(UA); #4. Get repository in project(PA), there should be one repository which was created by user(UA);
repo_data = self.repo.get_repository(TestProjects.project_del_repo_name, **TestProjects.USER_del_repo_CLIENT) repo_data = self.repo.list_repositories(TestProjects.project_del_repo_name, **TestProjects.USER_del_repo_CLIENT)
_assert_status_code(repo_name, repo_data[0].name) _assert_status_code(repo_name, repo_data[0].name)
#5. Delete repository(RA) by user(UA); #5. Delete repository(RA) by user(UA);
self.repo.delete_repoitory(TestProjects.project_del_repo_name, repo_name.split('/')[1], **TestProjects.USER_del_repo_CLIENT) self.repo.delete_repoitory(TestProjects.project_del_repo_name, repo_name.split('/')[1], **TestProjects.USER_del_repo_CLIENT)
#6. Get repository by user(UA), it should get nothing; #6. Get repository by user(UA), it should get nothing;
repo_data = self.repo.get_repository(TestProjects.project_del_repo_name, **TestProjects.USER_del_repo_CLIENT) repo_data = self.repo.list_repositories(TestProjects.project_del_repo_name, **TestProjects.USER_del_repo_CLIENT)
_assert_status_code(len(repo_data), 0) _assert_status_code(len(repo_data), 0)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -69,7 +69,7 @@ class TestProjects(unittest.TestCase):
self.repo.delete_repoitory(TestProjects.project_gc_name, repo_name.split('/')[1], **TestProjects.USER_GC_CLIENT) self.repo.delete_repoitory(TestProjects.project_gc_name, repo_name.split('/')[1], **TestProjects.USER_GC_CLIENT)
#5. Get repository by user(UA), it should get nothing; #5. Get repository by user(UA), it should get nothing;
repo_data = self.repo.get_repository(TestProjects.project_gc_name, **TestProjects.USER_GC_CLIENT) repo_data = self.repo.list_repositories(TestProjects.project_gc_name, **TestProjects.USER_GC_CLIENT)
_assert_status_code(len(repo_data), 0) _assert_status_code(len(repo_data), 0)
#6. Tigger garbage collection operation; #6. Tigger garbage collection operation;

View File

@ -0,0 +1,95 @@
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
from library.project import Project
from library.user import User
from library.repository import Repository
from library.artifact import Artifact
from library.docker_api import DockerAPI
class TestProjects(unittest.TestCase):
@classmethod
def setUpClass(self):
self.project= Project()
self.user= User()
self.artifact = Artifact(api_type='artifact')
self.repo= Repository(api_type='repository')
self.url = ADMIN_CLIENT["endpoint"]
self.user_push_chart_password = "Aa123456"
self.cnab_repo_name = "test_cnab"
@classmethod
def tearDownClass(self):
print "Case completed"
@unittest.skipIf(TEARDOWN == False, "Test data won't be erased.")
def test_ClearData(self):
#1. Delete repository(RA) by user(UA);
self.repo.delete_repoitory(TestProjects.project_push_bundle_name, self.cnab_repo_name, **TestProjects.USER_CLIENT)
#2. Delete project(PA);
self.project.delete_project(TestProjects.project_push_bundle_id, **TestProjects.USER_CLIENT)
#3. Delete user(UA).
self.user.delete_user(TestProjects.user_id, **ADMIN_CLIENT)
def testPushBundleByCnab(self):
"""
Test case:
Push Bundle By Cnab
Test step and expected result:
1. Create a new user(UA);
2. Create a new project(PA) by user(UA);
3. Pull images for bundle;
4. Push bundle to harbor as repository(RA);
5. Get repository from Harbor successfully;
6. Verfiy bundle name;
7. Get artifact by sha256;
8. Verify artifact information.
Tear down:
1. Delete repository(RA) by user(UA);
2. Delete project(PA);
3. Delete user(UA).
"""
#1. Create a new 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)
#2. Create a new project(PA) by user(UA);
TestProjects.project_push_bundle_id, TestProjects.project_push_bundle_name = self.project.create_project(metadata = {"public": "false"}, **TestProjects.USER_CLIENT)
#3. Pull images for bundle;
_docker_api = DockerAPI()
_docker_api.docker_image_pull("hello-world", tag = "latest")
_docker_api.docker_image_pull("busybox", tag = "latest")
#4. Push bundle to harbor as repository(RA);
target = harbor_server + "/" + TestProjects.project_push_bundle_name + "/" + self.cnab_repo_name
reference_sha256 = library.cnab.push_cnab_bundle(harbor_server, user_name, self.user_push_chart_password, "hello-world:latest", "busybox:latest", target)
#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
#6. Verfiy bundle name;
self.assertEqual(index_data.name, TestProjects.project_push_bundle_name + "/" + self.cnab_repo_name)
#7. Get artifact by sha256;
artifact = self.artifact.get_reference_info(TestProjects.project_push_bundle_name, self.cnab_repo_name, reference_sha256, **TestProjects.USER_CLIENT)
#8. Verify artifact information;
self.assertEqual(artifact[0].type, 'CNAB')
self.assertEqual(artifact[0].digest, reference_sha256)
if __name__ == '__main__':
unittest.main()

View File

@ -59,7 +59,7 @@ class TestProjects(unittest.TestCase):
push_special_image_to_project(TestProjects.project_src_repo_name, harbor_server, user_ra_name, user_ra_password, "test3", ['1.0']) push_special_image_to_project(TestProjects.project_src_repo_name, harbor_server, user_ra_name, user_ra_password, "test3", ['1.0'])
push_special_image_to_project(TestProjects.project_src_repo_name, harbor_server, user_ra_name, user_ra_password, "test4", ['1.0']) push_special_image_to_project(TestProjects.project_src_repo_name, harbor_server, user_ra_name, user_ra_password, "test4", ['1.0'])
resp=self.repo.get_repository(TestProjects.project_src_repo_name, **TestProjects.USER_RA_CLIENT) resp=self.repo.list_repositories(TestProjects.project_src_repo_name, **TestProjects.USER_RA_CLIENT)
self.assertEqual(len(resp), 4) self.assertEqual(len(resp), 4)
# Create Retention Policy # Create Retention Policy
@ -91,7 +91,7 @@ class TestProjects(unittest.TestCase):
print(resp) print(resp)
# TODO As the repository isn't deleted when no tags left anymore # TODO As the repository isn't deleted when no tags left anymore
# TODO we should check the artifact/tag count here # TODO we should check the artifact/tag count here
# resp=self.repo.get_repository(TestProjects.project_src_repo_id, **TestProjects.USER_RA_CLIENT) # resp=self.repo.list_repositories(TestProjects.project_src_repo_id, **TestProjects.USER_RA_CLIENT)
# self.assertEqual(len(resp), 3) # self.assertEqual(len(resp), 3)
@ -102,7 +102,7 @@ class TestProjects(unittest.TestCase):
# TODO delete_repoitory will fail when no tags left anymore # TODO delete_repoitory will fail when no tags left anymore
# @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.") # @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.")
# def test_ClearData(self): # def test_ClearData(self):
# resp=self.repo.get_repository(TestProjects.project_src_repo_id, **TestProjects.USER_RA_CLIENT) # resp=self.repo.list_repositories(TestProjects.project_src_repo_id, **TestProjects.USER_RA_CLIENT)
# for repo in resp: # for repo in resp:
# self.repo.delete_repoitory(repo.name, **TestProjects.USER_RA_CLIENT) # self.repo.delete_repoitory(repo.name, **TestProjects.USER_RA_CLIENT)
# self.project.delete_project(TestProjects.project_src_repo_id, **TestProjects.USER_RA_CLIENT) # self.project.delete_project(TestProjects.project_src_repo_id, **TestProjects.USER_RA_CLIENT)

View File

@ -71,4 +71,6 @@ Test Case - Push Index By Docker Manifest
Harbor API Test ./tests/apitests/python/test_push_index_by_docker_manifest.py Harbor API Test ./tests/apitests/python/test_push_index_by_docker_manifest.py
Test Case - Push Index By Docker Manifest Test Case - Push Index By Docker Manifest
Harbor API Test ./tests/apitests/python/test_push_chart_by_helm3_chart_cli.py Harbor API Test ./tests/apitests/python/test_push_chart_by_helm3_chart_cli.py
Test Case - Push Cnab Bundle
Harbor API Test ./tests/apitests/python/test_push_cnab_bundle.py