mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-22 10:15:35 +01:00
Add script of push cnab bunlde API test
Signed-off-by: danfengliu <danfengl@vmware.com>
This commit is contained in:
parent
2615339f4c
commit
843b05c2d3
10
.github/workflows/CI.yml
vendored
10
.github/workflows/CI.yml
vendored
@ -109,6 +109,7 @@ jobs:
|
||||
cd src/github.com/goharbor/harbor
|
||||
pwd
|
||||
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 "::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"
|
||||
@ -130,9 +131,14 @@ jobs:
|
||||
sudo cp ./tests/harbor_ca.crt /usr/local/share/ca-certificates/
|
||||
sudo update-ca-certificates
|
||||
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 && \
|
||||
sudo mv linux-386/helm /usr/local/bin/helm3 && \
|
||||
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
|
||||
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
|
||||
run: |
|
||||
cd src/github.com/goharbor/harbor
|
||||
|
1
tests/apitests/python/bundle_data/bundle.json.tmpl
Normal file
1
tests/apitests/python/bundle_data/bundle.json.tmpl
Normal 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"}
|
51
tests/apitests/python/library/cnab.py
Normal file
51
tests/apitests/python/library/cnab.py
Normal 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
|
@ -10,14 +10,15 @@ except ImportError:
|
||||
pip.main(['install', '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]
|
||||
print "Docker Login Command: ", command
|
||||
base.run_command(command)
|
||||
try:
|
||||
ret = subprocess.check_output(["./tests/apitests/python/update_docker_cfg.sh"], shell=False)
|
||||
except subprocess.CalledProcessError, exc:
|
||||
raise Exception("Failed to update docker config, error is {} {}.".format(exc.returncode, exc.output))
|
||||
if enable_manifest == True:
|
||||
try:
|
||||
subprocess.check_output(["./tests/apitests/python/update_docker_cfg.sh"], shell=False)
|
||||
except subprocess.CalledProcessError, 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]
|
||||
@ -149,6 +150,9 @@ class DockerAPI(object):
|
||||
print("build image %s with size %d" % (repo, size))
|
||||
self.DCLIENT.remove_image(repo)
|
||||
self.DCLIENT.remove_container(c)
|
||||
self.DCLIENT.pull(repo)
|
||||
image = self.DCLIENT2.images.get(repo)
|
||||
return repo, image.id
|
||||
except Exception, err:
|
||||
caught_err = True
|
||||
if expected_error_message is not None:
|
||||
@ -165,5 +169,3 @@ class DockerAPI(object):
|
||||
else:
|
||||
if str(ret).lower().find("errorDetail".lower()) >= 0:
|
||||
raise Exception(r" It's was not suppose to catch error when push image {}, return message is [{}]".format (harbor_registry, ret))
|
||||
|
||||
|
||||
|
@ -37,7 +37,7 @@ def push_special_image_to_project(project_name, registry, username, password, im
|
||||
time.sleep(2)
|
||||
if expected_login_error_message != None:
|
||||
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):
|
||||
result = False
|
||||
@ -78,12 +78,18 @@ class Repository(base.Base):
|
||||
_, status_code, _ = client.delete_repository_with_http_info(project_name, repo_name)
|
||||
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)
|
||||
data, status_code, _ = client.list_repositories_with_http_info(project_name)
|
||||
base._assert_status_code(200, status_code)
|
||||
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):
|
||||
client = self._get_client(**kwargs)
|
||||
label = swagger_client.Label(id=label_id)
|
||||
@ -122,7 +128,7 @@ class Repository(base.Base):
|
||||
return data
|
||||
|
||||
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:
|
||||
raise Exception("Repository {} is not exist.".format(repo_name))
|
||||
|
||||
|
@ -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)
|
||||
|
||||
#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)
|
||||
|
||||
#7. Get repository(RA)'s image tag detail information;
|
||||
|
@ -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")
|
||||
|
||||
#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)
|
||||
|
||||
#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)
|
||||
|
||||
#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)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -69,7 +69,7 @@ class TestProjects(unittest.TestCase):
|
||||
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;
|
||||
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)
|
||||
|
||||
#6. Tigger garbage collection operation;
|
||||
|
95
tests/apitests/python/test_push_cnab_bundle.py
Normal file
95
tests/apitests/python/test_push_cnab_bundle.py
Normal 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()
|
||||
|
@ -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, "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)
|
||||
|
||||
# Create Retention Policy
|
||||
@ -91,7 +91,7 @@ class TestProjects(unittest.TestCase):
|
||||
print(resp)
|
||||
# TODO As the repository isn't deleted when no tags left anymore
|
||||
# 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)
|
||||
|
||||
|
||||
@ -102,7 +102,7 @@ class TestProjects(unittest.TestCase):
|
||||
# TODO delete_repoitory will fail when no tags left anymore
|
||||
# @unittest.skipIf(TEARDOWN == False, "Test data won't be erased.")
|
||||
# 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:
|
||||
# self.repo.delete_repoitory(repo.name, **TestProjects.USER_RA_CLIENT)
|
||||
# self.project.delete_project(TestProjects.project_src_repo_id, **TestProjects.USER_RA_CLIENT)
|
||||
|
@ -71,4 +71,6 @@ Test Case - Push Index By Docker Manifest
|
||||
Harbor API Test ./tests/apitests/python/test_push_index_by_docker_manifest.py
|
||||
Test Case - Push Index By Docker Manifest
|
||||
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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user