From aba7b6c48d70c3267cd4aec6dcc7130385b3456a Mon Sep 17 00:00:00 2001 From: Wenkai Yin Date: Wed, 20 Jul 2016 15:49:45 +0800 Subject: [PATCH 01/14] add debug log for notificaions --- service/notification.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/service/notification.go b/service/notification.go index 77ade18d3..df3a114f1 100644 --- a/service/notification.go +++ b/service/notification.go @@ -94,6 +94,9 @@ func filterEvents(notification *models.Notification) ([]*models.Event, error) { events := []*models.Event{} for _, event := range notification.Events { + log.Debugf("receive an event: ID-%s, target-%s:%s, digest-%s, action-%s", event.ID, event.Target.Repository, event.Target.Tag, + event.Target.Digest, event.Action) + isManifest, err := regexp.MatchString(manifestPattern, event.Target.MediaType) if err != nil { log.Errorf("failed to match the media type against pattern: %v", err) @@ -107,12 +110,14 @@ func filterEvents(notification *models.Notification) ([]*models.Event, error) { //pull and push manifest by docker-client if strings.HasPrefix(event.Request.UserAgent, "docker") && (event.Action == "pull" || event.Action == "push") { events = append(events, &event) + log.Debugf("add event to collect: %s", event.ID) continue } //push manifest by docker-client or job-service if strings.ToLower(strings.TrimSpace(event.Request.UserAgent)) == "harbor-registry-client" && event.Action == "push" { events = append(events, &event) + log.Debugf("add event to collect: %s", event.ID) continue } } From 1576e4caf1541166db2d5699d5c85b77c8da174e Mon Sep 17 00:00:00 2001 From: tobe Date: Mon, 25 Jul 2016 23:15:36 +0800 Subject: [PATCH 02/14] Add harbor-py project --- vendor/harbor-py/.gitignore | 94 +++++ vendor/harbor-py/LICENSE | 201 ++++++++++ vendor/harbor-py/README.md | 69 ++++ vendor/harbor-py/examples/change_password.py | 18 + .../harbor-py/examples/check_project_exist.py | 16 + vendor/harbor-py/examples/create_project.py | 17 + vendor/harbor-py/examples/create_user.py | 20 + .../harbor-py/examples/delete_repository.py | 16 + vendor/harbor-py/examples/delete_user.py | 16 + vendor/harbor-py/examples/get_logs.py | 15 + .../examples/get_project_id_from_name.py | 16 + vendor/harbor-py/examples/get_projects.py | 15 + vendor/harbor-py/examples/get_repositories.py | 16 + .../examples/get_repository_manifests.py | 17 + .../harbor-py/examples/get_repository_tags.py | 16 + vendor/harbor-py/examples/get_statistics.py | 13 + .../examples/get_top_accessed_repositories.py | 19 + vendor/harbor-py/examples/get_users.py | 15 + vendor/harbor-py/examples/promote_as_admin.py | 16 + vendor/harbor-py/examples/search.py | 16 + .../examples/set_project_publicity.py | 17 + .../harbor-py/examples/test_harborclient.py | 12 + .../harbor-py/examples/update_user_profile.py | 19 + vendor/harbor-py/format_code.sh | 5 + vendor/harbor-py/harborclient/__init__.py | 0 vendor/harbor-py/harborclient/harborclient.py | 371 ++++++++++++++++++ .../harborclient/test_harborclient.py | 3 + vendor/harbor-py/requirements.txt | 1 + vendor/harbor-py/setup.py | 103 +++++ vendor/harbor-py/uninstall.sh | 7 + 30 files changed, 1179 insertions(+) create mode 100644 vendor/harbor-py/.gitignore create mode 100644 vendor/harbor-py/LICENSE create mode 100644 vendor/harbor-py/README.md create mode 100755 vendor/harbor-py/examples/change_password.py create mode 100755 vendor/harbor-py/examples/check_project_exist.py create mode 100755 vendor/harbor-py/examples/create_project.py create mode 100755 vendor/harbor-py/examples/create_user.py create mode 100755 vendor/harbor-py/examples/delete_repository.py create mode 100755 vendor/harbor-py/examples/delete_user.py create mode 100755 vendor/harbor-py/examples/get_logs.py create mode 100755 vendor/harbor-py/examples/get_project_id_from_name.py create mode 100755 vendor/harbor-py/examples/get_projects.py create mode 100755 vendor/harbor-py/examples/get_repositories.py create mode 100755 vendor/harbor-py/examples/get_repository_manifests.py create mode 100755 vendor/harbor-py/examples/get_repository_tags.py create mode 100755 vendor/harbor-py/examples/get_statistics.py create mode 100755 vendor/harbor-py/examples/get_top_accessed_repositories.py create mode 100755 vendor/harbor-py/examples/get_users.py create mode 100755 vendor/harbor-py/examples/promote_as_admin.py create mode 100755 vendor/harbor-py/examples/search.py create mode 100755 vendor/harbor-py/examples/set_project_publicity.py create mode 100755 vendor/harbor-py/examples/test_harborclient.py create mode 100755 vendor/harbor-py/examples/update_user_profile.py create mode 100755 vendor/harbor-py/format_code.sh create mode 100644 vendor/harbor-py/harborclient/__init__.py create mode 100755 vendor/harbor-py/harborclient/harborclient.py create mode 100644 vendor/harbor-py/harborclient/test_harborclient.py create mode 100644 vendor/harbor-py/requirements.txt create mode 100644 vendor/harbor-py/setup.py create mode 100755 vendor/harbor-py/uninstall.sh diff --git a/vendor/harbor-py/.gitignore b/vendor/harbor-py/.gitignore new file mode 100644 index 000000000..11ead4b5e --- /dev/null +++ b/vendor/harbor-py/.gitignore @@ -0,0 +1,94 @@ +# Temporary files +files.txt +*.swp +*~ + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# IPython Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# dotenv +.env + +# virtualenv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject diff --git a/vendor/harbor-py/LICENSE b/vendor/harbor-py/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/vendor/harbor-py/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/harbor-py/README.md b/vendor/harbor-py/README.md new file mode 100644 index 000000000..0e27fd2d1 --- /dev/null +++ b/vendor/harbor-py/README.md @@ -0,0 +1,69 @@ +## Introduction + +[harbor](https://github.com/vmware/harbor) is the enterprise-class registry server for docker distribution. + +[harbor-py](https://github.com/tobegit3hub/harbor-py) is the native and compatible python SDK for harbor. The supported APIs are list below. + +- [x] Projects APIs + - [x] [Get projects](./examples/get_projects.py) + - [x] [Create project](./examples/create_project.py) + - [x] [Check project exist](./examples/check_project_exist.py) + - [x] [Set project publicity](./examples/set_project_publicity.py) + - [x] [Get project id from name](./examples/get_project_id_from_name.py) + - [ ] Get project access logs + - [ ] Get project member + - [ ] Get project and user member +- [x] Users APIs + - [x] [Get users](./examples/get_users.py) + - [x] [Create user](./examples/create_user.py) + - [x] [Update user profile](./examples/update_user_profile.py) + - [x] [Delete user](./examples/delete_user.py) + - [x] [Change password](./examples/change_password.py) + - [x] [Promote as admin](./examples/promote_as_admin.py) +- [x] Repositories APIs + - [x] [Get repositories](./examples/get_repositories.py) + - [x] [Delete repository](./examples/delete_repository.py) + - [x] [Get repository tags](./examples/get_repository_tags.py) + - [x] [Get repository manifests](./examples/get_repository_manifests.py) +- [x] Others APIs + - [x] [Search](./examples/search.py) + - [x] [Get statistics](./examples/get_statistics.py) + - [x] [Get top accessed repositories](./examples/get_top_accessed_repositories.py) + - [x] [Get logs](./examples/get_logs.py) + +## Installation + +``` +pip install harbor-py +``` + +## Usage + +``` +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +client.get_projects() +client.get_users() +client.get_statistics() +client.get_top_accessed_repositories() +client.search("library") +``` + +For more usage, please refer to the [examples](./examples/). + +## Contribution + +If you have any suggestion, feel free to submit [issues](https://github.com/tobegit3hub/harbor-py/issues) or send [pull-requests](https://github.com/tobegit3hub/harbor-py/pulls) for `harbor-py`. + +Publish `harbor-py` package to [pypi](https://pypi.python.org/pypi/harbor-py/) server with the following commands. + +``` +python setup.py register -r pypi +python setup.py sdist upload -r pypi +``` diff --git a/vendor/harbor-py/examples/change_password.py b/vendor/harbor-py/examples/change_password.py new file mode 100755 index 000000000..8b69cd12e --- /dev/null +++ b/vendor/harbor-py/examples/change_password.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Change password +user_id = 2 +old_password = "test-password" +new_password = "new-password" +client.change_password(user_id, old_password, new_password) diff --git a/vendor/harbor-py/examples/check_project_exist.py b/vendor/harbor-py/examples/check_project_exist.py new file mode 100755 index 000000000..3667b71ba --- /dev/null +++ b/vendor/harbor-py/examples/check_project_exist.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Check if project exists +project_name = "test-project" +print(client.check_project_exist(project_name)) diff --git a/vendor/harbor-py/examples/create_project.py b/vendor/harbor-py/examples/create_project.py new file mode 100755 index 000000000..adb07eefa --- /dev/null +++ b/vendor/harbor-py/examples/create_project.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Create project +project_name = "test-project" +is_public = True +client.create_project(project_name, is_public) diff --git a/vendor/harbor-py/examples/create_user.py b/vendor/harbor-py/examples/create_user.py new file mode 100755 index 000000000..1ac2e5e39 --- /dev/null +++ b/vendor/harbor-py/examples/create_user.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Create user +username = "test-username" +email = "test-email@gmail.com" +password = "test-password" +realname = "test-realname" +comment = "test-comment" +client.create_user(username, email, password, realname, comment) diff --git a/vendor/harbor-py/examples/delete_repository.py b/vendor/harbor-py/examples/delete_repository.py new file mode 100755 index 000000000..b12508ec5 --- /dev/null +++ b/vendor/harbor-py/examples/delete_repository.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Delete repository +repo_name = "library/cirros" +client.delete_repository(repo_name) diff --git a/vendor/harbor-py/examples/delete_user.py b/vendor/harbor-py/examples/delete_user.py new file mode 100755 index 000000000..7fa6ecbcb --- /dev/null +++ b/vendor/harbor-py/examples/delete_user.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Delete user +user_id = 2 +print(client.delete_user(user_id)) diff --git a/vendor/harbor-py/examples/get_logs.py b/vendor/harbor-py/examples/get_logs.py new file mode 100755 index 000000000..c62c5ac0a --- /dev/null +++ b/vendor/harbor-py/examples/get_logs.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Get logs +print(client.get_logs()) diff --git a/vendor/harbor-py/examples/get_project_id_from_name.py b/vendor/harbor-py/examples/get_project_id_from_name.py new file mode 100755 index 000000000..67366679f --- /dev/null +++ b/vendor/harbor-py/examples/get_project_id_from_name.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Get project id from name +project_name = "library" +print(client.get_project_id_from_name(project_name)) diff --git a/vendor/harbor-py/examples/get_projects.py b/vendor/harbor-py/examples/get_projects.py new file mode 100755 index 000000000..b95d0701e --- /dev/null +++ b/vendor/harbor-py/examples/get_projects.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Get all projects +print(client.get_projects()) diff --git a/vendor/harbor-py/examples/get_repositories.py b/vendor/harbor-py/examples/get_repositories.py new file mode 100755 index 000000000..3c83c7eca --- /dev/null +++ b/vendor/harbor-py/examples/get_repositories.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Get all repositories +project_id = 1 +print(client.get_repositories(project_id)) diff --git a/vendor/harbor-py/examples/get_repository_manifests.py b/vendor/harbor-py/examples/get_repository_manifests.py new file mode 100755 index 000000000..7a3fd0b0b --- /dev/null +++ b/vendor/harbor-py/examples/get_repository_manifests.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Get repository manifests +repo_name = "library/cirros" +tag = "latest" +client.get_repository_manifests(repo_name, tag) diff --git a/vendor/harbor-py/examples/get_repository_tags.py b/vendor/harbor-py/examples/get_repository_tags.py new file mode 100755 index 000000000..03fffdea1 --- /dev/null +++ b/vendor/harbor-py/examples/get_repository_tags.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Get repository tags +repo_name = "library/cirros" +client.get_repository_tags(repo_name) diff --git a/vendor/harbor-py/examples/get_statistics.py b/vendor/harbor-py/examples/get_statistics.py new file mode 100755 index 000000000..8a6dcb6b2 --- /dev/null +++ b/vendor/harbor-py/examples/get_statistics.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) +print(client.get_statistics()) diff --git a/vendor/harbor-py/examples/get_top_accessed_repositories.py b/vendor/harbor-py/examples/get_top_accessed_repositories.py new file mode 100755 index 000000000..b19e5901d --- /dev/null +++ b/vendor/harbor-py/examples/get_top_accessed_repositories.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Get top accessed respositories +print(client.get_top_accessed_repositories()) + +# Get top accessed respositories with count +count = 1 +print(client.get_top_accessed_repositories(count)) diff --git a/vendor/harbor-py/examples/get_users.py b/vendor/harbor-py/examples/get_users.py new file mode 100755 index 000000000..1a634bed5 --- /dev/null +++ b/vendor/harbor-py/examples/get_users.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Get all users +print(client.get_users()) diff --git a/vendor/harbor-py/examples/promote_as_admin.py b/vendor/harbor-py/examples/promote_as_admin.py new file mode 100755 index 000000000..c7692f21a --- /dev/null +++ b/vendor/harbor-py/examples/promote_as_admin.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Promote as admin +user_id = 2 +client.promote_as_admin(user_id) diff --git a/vendor/harbor-py/examples/search.py b/vendor/harbor-py/examples/search.py new file mode 100755 index 000000000..3ecd52f4a --- /dev/null +++ b/vendor/harbor-py/examples/search.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Search with query string +query_string = "library" +print(client.search(query_string)) diff --git a/vendor/harbor-py/examples/set_project_publicity.py b/vendor/harbor-py/examples/set_project_publicity.py new file mode 100755 index 000000000..6f29b6dd7 --- /dev/null +++ b/vendor/harbor-py/examples/set_project_publicity.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Set project publicity +project_id = 1 +is_public = True +client.set_project_publicity(project_id, is_public) diff --git a/vendor/harbor-py/examples/test_harborclient.py b/vendor/harbor-py/examples/test_harborclient.py new file mode 100755 index 000000000..b1731ebd8 --- /dev/null +++ b/vendor/harbor-py/examples/test_harborclient.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) diff --git a/vendor/harbor-py/examples/update_user_profile.py b/vendor/harbor-py/examples/update_user_profile.py new file mode 100755 index 000000000..750ab120a --- /dev/null +++ b/vendor/harbor-py/examples/update_user_profile.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +import sys +sys.path.append("../") + +from harborclient import harborclient + +host = "127.0.0.1" +user = "admin" +password = "Harbor12345" + +client = harborclient.HarborClient(host, user, password) + +# Update user profile +user_id = 2 +email = "new@gmail.com" +realname = "new_realname" +comment = "new_comment" +client.update_user_profile(user_id, email, realname, comment) diff --git a/vendor/harbor-py/format_code.sh b/vendor/harbor-py/format_code.sh new file mode 100755 index 000000000..ee8253cbb --- /dev/null +++ b/vendor/harbor-py/format_code.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -x + +find ./ -name "*.py" |xargs sudo yapf -i diff --git a/vendor/harbor-py/harborclient/__init__.py b/vendor/harbor-py/harborclient/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/harbor-py/harborclient/harborclient.py b/vendor/harbor-py/harborclient/harborclient.py new file mode 100755 index 000000000..91d8b5d58 --- /dev/null +++ b/vendor/harbor-py/harborclient/harborclient.py @@ -0,0 +1,371 @@ +#!/usr/bin/env python + +import requests +import simplejson +import logging + +logging.basicConfig(level=logging.INFO) + + +class HarborClient(object): + def __init__(self, host, user, password, protocol="http"): + self.host = host + self.user = user + self.password = password + self.protocol = protocol + + self.session_id = self.login() + + def __del__(self): + self.logout() + + def login(self): + login_data = requests.post('%s://%s/login' % + (self.protocol, self.host), + data={'principal': self.user, + 'password': self.password}) + if login_data.status_code == 200: + session_id = login_data.cookies.get('beegosessionID') + + logging.debug("Successfully login, session id: {}".format( + session_id)) + return session_id + else: + logging.error("Fail to login, please try again") + return None + + def logout(self): + requests.get('%s://%s/logout' % (self.protocol, self.host), + cookies={'beegosessionID': self.session_id}) + logging.debug("Successfully logout") + + # Get project id + def get_project_id_from_name(self, project_name): + registry_data = requests.get( + '%s://%s/api/projects?project_name=%s' % + (self.protocol, self.host, project_name), + cookies={'beegosessionID': self.session_id}) + if registry_data.status_code == 200 and registry_data.json(): + project_id = registry_data.json()[0]['project_id'] + logging.debug( + "Successfully get project id: {}, project name: {}".format( + project_id, project_name)) + return project_id + else: + pritn("Fail to get project id from project name", project_name) + return None + + # GET /search + def search(self, query_string): + result = None + path = '%s://%s/api/search?q=%s' % (self.protocol, self.host, + query_string) + response = requests.get(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = response.json() + logging.debug("Successfully get search result: {}".format(result)) + else: + logging.error("Fail to get search result") + return result + + # GET /projects + def get_projects(self, project_name=None, is_public=None): + # TODO: support parameter + result = None + path = '%s://%s/api/projects' % (self.protocol, self.host) + response = requests.get(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = response.json() + logging.debug("Successfully get projects result: {}".format( + result)) + else: + logging.error("Fail to get projects result") + return result + + # HEAD /projects + def check_project_exist(self, project_name): + result = False + path = '%s://%s/api/projects?project_name=%s' % ( + self.protocol, self.host, project_name) + response = requests.head(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = True + logging.debug( + "Successfully check project exist, result: {}".format(result)) + elif response.status_code == 404: + result = False + logging.debug( + "Successfully check project exist, result: {}".format(result)) + else: + logging.error("Fail to check project exist") + return result + + # POST /projects + def create_project(self, project_name, is_public=False): + result = False + path = '%s://%s/api/projects' % (self.protocol, self.host) + request_body = simplejson.dumps({'project_name': project_name, + 'public': is_public}) + response = requests.post(path, + cookies={'beegosessionID': self.session_id}, + data=request_body) + if response.status_code == 201 or response.status_code == 500: + # TODO: the response return 500 sometimes + result = True + logging.debug( + "Successfully create project with project name: {}".format( + project_name)) + else: + logging.error( + "Fail to create project with project name: {}, response code: {}".format( + project_name, response.status_code)) + return result + + # PUT /projects/{project_id}/publicity + def set_project_publicity(self, project_id, is_public): + result = False + path = '%s://%s/api/projects/%s/publicity?project_id=%s' % ( + self.protocol, self.host, project_id, project_id) + request_body = simplejson.dumps({'public': is_public}) + response = requests.put(path, + cookies={'beegosessionID': self.session_id}, + data=request_body) + if response.status_code == 200: + result = True + logging.debug( + "Success to set project id: {} with publicity: {}".format( + project_id, is_public)) + else: + logging.error( + "Fail to set publicity to project id: {} with status code: {}".format( + project_id, response.status_code)) + return result + + # GET /statistics + def get_statistics(self): + result = None + path = '%s://%s/api/statistics' % (self.protocol, self.host) + response = requests.get(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = response.json() + logging.debug("Successfully get statistics: {}".format(result)) + else: + logging.error("Fail to get statistics result") + return result + + # GET /users + def get_users(self, user_name=None): + # TODO: support parameter + result = None + path = '%s://%s/api/users' % (self.protocol, self.host) + response = requests.get(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = response.json() + logging.debug("Successfully get users result: {}".format(result)) + else: + logging.error("Fail to get users result") + return result + + # POST /users + def create_user(self, username, email, password, realname, comment): + result = False + path = '%s://%s/api/users' % (self.protocol, self.host) + request_body = simplejson.dumps({'username': username, + 'email': email, + 'password': password, + 'realname': realname, + 'comment': comment}) + response = requests.post(path, + cookies={'beegosessionID': self.session_id}, + data=request_body) + if response.status_code == 201: + result = True + logging.debug("Successfully create user with username: {}".format( + username)) + else: + logging.error( + "Fail to create user with username: {}, response code: {}".format( + username, response.status_code)) + return result + + # PUT /users/{user_id} + def update_user_profile(self, user_id, email, realname, comment): + # TODO: support not passing comment + result = False + path = '%s://%s/api/users/%s?user_id=%s' % (self.protocol, self.host, + user_id, user_id) + request_body = simplejson.dumps({'email': email, + 'realname': realname, + 'comment': comment}) + response = requests.put(path, + cookies={'beegosessionID': self.session_id}, + data=request_body) + if response.status_code == 200: + result = True + logging.debug( + "Successfully update user profile with user id: {}".format( + user_id)) + else: + logging.error( + "Fail to update user profile with user id: {}, response code: {}".format( + user_id, response.status_code)) + return result + + # DELETE /users/{user_id} + def delete_user(self, user_id): + result = False + path = '%s://%s/api/users/%s?user_id=%s' % (self.protocol, self.host, + user_id, user_id) + response = requests.delete(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = True + logging.debug("Successfully delete user with id: {}".format( + user_id)) + else: + logging.error("Fail to delete user with id: {}".format(user_id)) + return result + + # PUT /users/{user_id}/password + def change_password(self, user_id, old_password, new_password): + result = False + path = '%s://%s/api/users/%s/password?user_id=%s' % ( + self.protocol, self.host, user_id, user_id) + request_body = simplejson.dumps({'old_password': old_password, + 'new_password': new_password}) + response = requests.put(path, + cookies={'beegosessionID': self.session_id}, + data=request_body) + if response.status_code == 200: + result = True + logging.debug( + "Successfully change password for user id: {}".format(user_id)) + else: + logging.error("Fail to change password for user id: {}".format( + user_id)) + return result + + # PUT /users/{user_id}/sysadmin + def promote_as_admin(self, user_id): + # TODO: always return 404, need more test + result = False + path = '%s://%s/api/users/%s/sysadmin?user_id=%s' % ( + self.protocol, self.host, user_id, user_id) + response = requests.put(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = True + logging.debug( + "Successfully promote user as admin with user id: {}".format( + user_id)) + else: + logging.error( + "Fail to promote user as admin with user id: {}, response code: {}".format( + user_id, response.status_code)) + return result + + # GET /repositories + def get_repositories(self, project_id, query_string=None): + # TODO: support parameter + result = None + path = '%s://%s/api/repositories?project_id=%s' % ( + self.protocol, self.host, project_id) + response = requests.get(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = response.json() + logging.debug( + "Successfully get repositories with id: {}, result: {}".format( + project_id, result)) + else: + logging.error("Fail to get repositories result with id: {}".format( + project_id)) + return result + + # DELETE /repositories + def delete_repository(self, repo_name, tag=None): + # TODO: support to check tag + # TODO: return 200 but the repo is not deleted, need more test + result = False + path = '%s://%s/api/repositories?repo_name=%s' % (self.protocol, + self.host, repo_name) + response = requests.delete(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = True + logging.debug("Successfully delete repository: {}".format( + repo_name)) + else: + logging.error("Fail to delete repository: {}".format(repo_name)) + return result + + # Get /repositories/tags + def get_repository_tags(self, repo_name): + result = None + path = '%s://%s/api/repositories/tags?repo_name=%s' % ( + self.protocol, self.host, repo_name) + response = requests.get(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = response.json() + logging.debug( + "Successfully get tag with repo name: {}, result: {}".format( + repo_name, result)) + else: + logging.error("Fail to get tags with repo name: {}".format( + repo_name)) + return result + + # GET /repositories/manifests + def get_repository_manifests(self, repo_name, tag): + result = None + path = '%s://%s/api/repositories/manifests?repo_name=%s&tag=%s' % ( + self.protocol, self.host, repo_name, tag) + response = requests.get(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = response.json() + logging.debug( + "Successfully get manifests with repo name: {}, tag: {}, result: {}".format( + repo_name, tag, result)) + else: + logging.error( + "Fail to get manifests with repo name: {}, tag: {}".format( + repo_name, tag)) + return result + + # GET /repositories/top + def get_top_accessed_repositories(self, count=None): + result = None + path = '%s://%s/api/repositories/top' % (self.protocol, self.host) + if count: + path += "?count=%s" % (count) + response = requests.get(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = response.json() + logging.debug( + "Successfully get top accessed repositories, result: {}".format( + result)) + else: + logging.error("Fail to get top accessed repositories") + return result + + # GET /logs + def get_logs(self, lines=None, start_time=None, end_time=None): + result = None + path = '%s://%s/api/logs' % (self.protocol, self.host) + response = requests.get(path, + cookies={'beegosessionID': self.session_id}) + if response.status_code == 200: + result = response.json() + logging.debug("Successfully get logs") + else: + logging.error("Fail to get logs and response code: {}".format( + response.status_code)) + return result diff --git a/vendor/harbor-py/harborclient/test_harborclient.py b/vendor/harbor-py/harborclient/test_harborclient.py new file mode 100644 index 000000000..07ca718d6 --- /dev/null +++ b/vendor/harbor-py/harborclient/test_harborclient.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python + +import harborclient diff --git a/vendor/harbor-py/requirements.txt b/vendor/harbor-py/requirements.txt new file mode 100644 index 000000000..f7778fa68 --- /dev/null +++ b/vendor/harbor-py/requirements.txt @@ -0,0 +1 @@ +requests>2.2.0 diff --git a/vendor/harbor-py/setup.py b/vendor/harbor-py/setup.py new file mode 100644 index 000000000..ea63d8d24 --- /dev/null +++ b/vendor/harbor-py/setup.py @@ -0,0 +1,103 @@ +""" The missing harbor python SDK + +See: https://github.com/tobegit3hub/harbor-py +""" + +from setuptools import setup, find_packages +from codecs import open +from os import path + +setup( + name='harbor-py', + + # Versions should comply with PEP440. For a discussion on single-sourcing + # the version across setup.py and the project code, see + # https://packaging.python.org/en/latest/single_source_version.html + version='1.2.0', + description='The missing harbor python SDK', + + # The project's main homepage. + url='https://github.com/tobegit3hub/harbor-py', + + # Author details + author='tobe', + author_email='tobeg3oogle@gmail.com', + + # Choose your license + license='Apache Software', + + # See https://pypi.python.org/pypi?%3Aaction=list_classifiers + classifiers=[ + # How mature is this project? Common values are + # 3 - Alpha + # 4 - Beta + # 5 - Production/Stable + 'Development Status :: 3 - Alpha', + + # Indicate who your project is intended for + 'Intended Audience :: Developers', + 'Topic :: Software Development :: Build Tools', + + # Pick your license as you wish (should match "license" above) + 'License :: OSI Approved :: Apache Software License', + + # Specify the Python versions you support here. In particular, ensure + # that you indicate whether you support Python 2, Python 3 or both. + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + ], + + # What does your project relate to? + keywords='docker registry distribution harbor python sdk', + + # You can just specify the packages manually here if your project is + # simple. Or you can use find_packages(). + #packages=find_packages(exclude=['contrib', 'docs', 'tests']), + packages=['harborclient'], + + # Alternatively, if you want to distribute just a my_module.py, uncomment + # this: + # py_modules=["my_module"], + + # List run-time dependencies here. These will be installed by pip when + # your project is installed. For an analysis of "install_requires" vs pip's + # requirements files see: + # https://packaging.python.org/en/latest/requirements.html + #install_requires=['peppercorn'], + + # List additional groups of dependencies here (e.g. development + # dependencies). You can install these using the following syntax, + # for example: + # $ pip install -e .[dev,test] + #extras_require={ + # 'dev': ['check-manifest'], + # 'test': ['coverage'], + #}, + + # If there are data files included in your packages that need to be + # installed, specify them here. If using Python 2.6 or less, then these + # have to be included in MANIFEST.in as well. + #package_data={ + # 'sample': ['package_data.dat'], + #}, + + # Although 'package_data' is the preferred approach, in some case you may + # need to place data files outside of your packages. See: + # http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files # noqa + # In this case, 'data_file' will be installed into '/my_data' + #data_files=[('my_data', ['data/data_file'])], + + # To provide executable scripts, use entry points in preference to the + # "scripts" keyword. Entry points provide cross-platform support and allow + # pip to create the appropriate form of executable for the target platform. + #entry_points={ + # 'console_scripts': [ + # 'harbor=harborclient:main', + # ], + #}, +) diff --git a/vendor/harbor-py/uninstall.sh b/vendor/harbor-py/uninstall.sh new file mode 100755 index 000000000..49197286d --- /dev/null +++ b/vendor/harbor-py/uninstall.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -x +set -e + +python setup.py install --record files.txt +cat files.txt | xargs rm -rf From ebb8fd6b9f2f8737d006750a903bc4f2cbe86104 Mon Sep 17 00:00:00 2001 From: tobe Date: Tue, 26 Jul 2016 00:19:30 +0800 Subject: [PATCH 03/14] Move harbor-py to contrib/sdk/ --- {vendor => contrib/sdk}/harbor-py/.gitignore | 0 {vendor => contrib/sdk}/harbor-py/LICENSE | 0 {vendor => contrib/sdk}/harbor-py/README.md | 0 {vendor => contrib/sdk}/harbor-py/examples/change_password.py | 0 {vendor => contrib/sdk}/harbor-py/examples/check_project_exist.py | 0 {vendor => contrib/sdk}/harbor-py/examples/create_project.py | 0 {vendor => contrib/sdk}/harbor-py/examples/create_user.py | 0 {vendor => contrib/sdk}/harbor-py/examples/delete_repository.py | 0 {vendor => contrib/sdk}/harbor-py/examples/delete_user.py | 0 {vendor => contrib/sdk}/harbor-py/examples/get_logs.py | 0 .../sdk}/harbor-py/examples/get_project_id_from_name.py | 0 {vendor => contrib/sdk}/harbor-py/examples/get_projects.py | 0 {vendor => contrib/sdk}/harbor-py/examples/get_repositories.py | 0 .../sdk}/harbor-py/examples/get_repository_manifests.py | 0 {vendor => contrib/sdk}/harbor-py/examples/get_repository_tags.py | 0 {vendor => contrib/sdk}/harbor-py/examples/get_statistics.py | 0 .../sdk}/harbor-py/examples/get_top_accessed_repositories.py | 0 {vendor => contrib/sdk}/harbor-py/examples/get_users.py | 0 {vendor => contrib/sdk}/harbor-py/examples/promote_as_admin.py | 0 {vendor => contrib/sdk}/harbor-py/examples/search.py | 0 .../sdk}/harbor-py/examples/set_project_publicity.py | 0 {vendor => contrib/sdk}/harbor-py/examples/test_harborclient.py | 0 {vendor => contrib/sdk}/harbor-py/examples/update_user_profile.py | 0 {vendor => contrib/sdk}/harbor-py/format_code.sh | 0 {vendor => contrib/sdk}/harbor-py/harborclient/__init__.py | 0 {vendor => contrib/sdk}/harbor-py/harborclient/harborclient.py | 0 .../sdk}/harbor-py/harborclient/test_harborclient.py | 0 {vendor => contrib/sdk}/harbor-py/requirements.txt | 0 {vendor => contrib/sdk}/harbor-py/setup.py | 0 {vendor => contrib/sdk}/harbor-py/uninstall.sh | 0 30 files changed, 0 insertions(+), 0 deletions(-) rename {vendor => contrib/sdk}/harbor-py/.gitignore (100%) rename {vendor => contrib/sdk}/harbor-py/LICENSE (100%) rename {vendor => contrib/sdk}/harbor-py/README.md (100%) rename {vendor => contrib/sdk}/harbor-py/examples/change_password.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/check_project_exist.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/create_project.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/create_user.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/delete_repository.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/delete_user.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/get_logs.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/get_project_id_from_name.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/get_projects.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/get_repositories.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/get_repository_manifests.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/get_repository_tags.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/get_statistics.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/get_top_accessed_repositories.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/get_users.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/promote_as_admin.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/search.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/set_project_publicity.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/test_harborclient.py (100%) rename {vendor => contrib/sdk}/harbor-py/examples/update_user_profile.py (100%) rename {vendor => contrib/sdk}/harbor-py/format_code.sh (100%) rename {vendor => contrib/sdk}/harbor-py/harborclient/__init__.py (100%) rename {vendor => contrib/sdk}/harbor-py/harborclient/harborclient.py (100%) rename {vendor => contrib/sdk}/harbor-py/harborclient/test_harborclient.py (100%) rename {vendor => contrib/sdk}/harbor-py/requirements.txt (100%) rename {vendor => contrib/sdk}/harbor-py/setup.py (100%) rename {vendor => contrib/sdk}/harbor-py/uninstall.sh (100%) diff --git a/vendor/harbor-py/.gitignore b/contrib/sdk/harbor-py/.gitignore similarity index 100% rename from vendor/harbor-py/.gitignore rename to contrib/sdk/harbor-py/.gitignore diff --git a/vendor/harbor-py/LICENSE b/contrib/sdk/harbor-py/LICENSE similarity index 100% rename from vendor/harbor-py/LICENSE rename to contrib/sdk/harbor-py/LICENSE diff --git a/vendor/harbor-py/README.md b/contrib/sdk/harbor-py/README.md similarity index 100% rename from vendor/harbor-py/README.md rename to contrib/sdk/harbor-py/README.md diff --git a/vendor/harbor-py/examples/change_password.py b/contrib/sdk/harbor-py/examples/change_password.py similarity index 100% rename from vendor/harbor-py/examples/change_password.py rename to contrib/sdk/harbor-py/examples/change_password.py diff --git a/vendor/harbor-py/examples/check_project_exist.py b/contrib/sdk/harbor-py/examples/check_project_exist.py similarity index 100% rename from vendor/harbor-py/examples/check_project_exist.py rename to contrib/sdk/harbor-py/examples/check_project_exist.py diff --git a/vendor/harbor-py/examples/create_project.py b/contrib/sdk/harbor-py/examples/create_project.py similarity index 100% rename from vendor/harbor-py/examples/create_project.py rename to contrib/sdk/harbor-py/examples/create_project.py diff --git a/vendor/harbor-py/examples/create_user.py b/contrib/sdk/harbor-py/examples/create_user.py similarity index 100% rename from vendor/harbor-py/examples/create_user.py rename to contrib/sdk/harbor-py/examples/create_user.py diff --git a/vendor/harbor-py/examples/delete_repository.py b/contrib/sdk/harbor-py/examples/delete_repository.py similarity index 100% rename from vendor/harbor-py/examples/delete_repository.py rename to contrib/sdk/harbor-py/examples/delete_repository.py diff --git a/vendor/harbor-py/examples/delete_user.py b/contrib/sdk/harbor-py/examples/delete_user.py similarity index 100% rename from vendor/harbor-py/examples/delete_user.py rename to contrib/sdk/harbor-py/examples/delete_user.py diff --git a/vendor/harbor-py/examples/get_logs.py b/contrib/sdk/harbor-py/examples/get_logs.py similarity index 100% rename from vendor/harbor-py/examples/get_logs.py rename to contrib/sdk/harbor-py/examples/get_logs.py diff --git a/vendor/harbor-py/examples/get_project_id_from_name.py b/contrib/sdk/harbor-py/examples/get_project_id_from_name.py similarity index 100% rename from vendor/harbor-py/examples/get_project_id_from_name.py rename to contrib/sdk/harbor-py/examples/get_project_id_from_name.py diff --git a/vendor/harbor-py/examples/get_projects.py b/contrib/sdk/harbor-py/examples/get_projects.py similarity index 100% rename from vendor/harbor-py/examples/get_projects.py rename to contrib/sdk/harbor-py/examples/get_projects.py diff --git a/vendor/harbor-py/examples/get_repositories.py b/contrib/sdk/harbor-py/examples/get_repositories.py similarity index 100% rename from vendor/harbor-py/examples/get_repositories.py rename to contrib/sdk/harbor-py/examples/get_repositories.py diff --git a/vendor/harbor-py/examples/get_repository_manifests.py b/contrib/sdk/harbor-py/examples/get_repository_manifests.py similarity index 100% rename from vendor/harbor-py/examples/get_repository_manifests.py rename to contrib/sdk/harbor-py/examples/get_repository_manifests.py diff --git a/vendor/harbor-py/examples/get_repository_tags.py b/contrib/sdk/harbor-py/examples/get_repository_tags.py similarity index 100% rename from vendor/harbor-py/examples/get_repository_tags.py rename to contrib/sdk/harbor-py/examples/get_repository_tags.py diff --git a/vendor/harbor-py/examples/get_statistics.py b/contrib/sdk/harbor-py/examples/get_statistics.py similarity index 100% rename from vendor/harbor-py/examples/get_statistics.py rename to contrib/sdk/harbor-py/examples/get_statistics.py diff --git a/vendor/harbor-py/examples/get_top_accessed_repositories.py b/contrib/sdk/harbor-py/examples/get_top_accessed_repositories.py similarity index 100% rename from vendor/harbor-py/examples/get_top_accessed_repositories.py rename to contrib/sdk/harbor-py/examples/get_top_accessed_repositories.py diff --git a/vendor/harbor-py/examples/get_users.py b/contrib/sdk/harbor-py/examples/get_users.py similarity index 100% rename from vendor/harbor-py/examples/get_users.py rename to contrib/sdk/harbor-py/examples/get_users.py diff --git a/vendor/harbor-py/examples/promote_as_admin.py b/contrib/sdk/harbor-py/examples/promote_as_admin.py similarity index 100% rename from vendor/harbor-py/examples/promote_as_admin.py rename to contrib/sdk/harbor-py/examples/promote_as_admin.py diff --git a/vendor/harbor-py/examples/search.py b/contrib/sdk/harbor-py/examples/search.py similarity index 100% rename from vendor/harbor-py/examples/search.py rename to contrib/sdk/harbor-py/examples/search.py diff --git a/vendor/harbor-py/examples/set_project_publicity.py b/contrib/sdk/harbor-py/examples/set_project_publicity.py similarity index 100% rename from vendor/harbor-py/examples/set_project_publicity.py rename to contrib/sdk/harbor-py/examples/set_project_publicity.py diff --git a/vendor/harbor-py/examples/test_harborclient.py b/contrib/sdk/harbor-py/examples/test_harborclient.py similarity index 100% rename from vendor/harbor-py/examples/test_harborclient.py rename to contrib/sdk/harbor-py/examples/test_harborclient.py diff --git a/vendor/harbor-py/examples/update_user_profile.py b/contrib/sdk/harbor-py/examples/update_user_profile.py similarity index 100% rename from vendor/harbor-py/examples/update_user_profile.py rename to contrib/sdk/harbor-py/examples/update_user_profile.py diff --git a/vendor/harbor-py/format_code.sh b/contrib/sdk/harbor-py/format_code.sh similarity index 100% rename from vendor/harbor-py/format_code.sh rename to contrib/sdk/harbor-py/format_code.sh diff --git a/vendor/harbor-py/harborclient/__init__.py b/contrib/sdk/harbor-py/harborclient/__init__.py similarity index 100% rename from vendor/harbor-py/harborclient/__init__.py rename to contrib/sdk/harbor-py/harborclient/__init__.py diff --git a/vendor/harbor-py/harborclient/harborclient.py b/contrib/sdk/harbor-py/harborclient/harborclient.py similarity index 100% rename from vendor/harbor-py/harborclient/harborclient.py rename to contrib/sdk/harbor-py/harborclient/harborclient.py diff --git a/vendor/harbor-py/harborclient/test_harborclient.py b/contrib/sdk/harbor-py/harborclient/test_harborclient.py similarity index 100% rename from vendor/harbor-py/harborclient/test_harborclient.py rename to contrib/sdk/harbor-py/harborclient/test_harborclient.py diff --git a/vendor/harbor-py/requirements.txt b/contrib/sdk/harbor-py/requirements.txt similarity index 100% rename from vendor/harbor-py/requirements.txt rename to contrib/sdk/harbor-py/requirements.txt diff --git a/vendor/harbor-py/setup.py b/contrib/sdk/harbor-py/setup.py similarity index 100% rename from vendor/harbor-py/setup.py rename to contrib/sdk/harbor-py/setup.py diff --git a/vendor/harbor-py/uninstall.sh b/contrib/sdk/harbor-py/uninstall.sh similarity index 100% rename from vendor/harbor-py/uninstall.sh rename to contrib/sdk/harbor-py/uninstall.sh From 707401e379e86fa94cb1943c67ba69de73a8168e Mon Sep 17 00:00:00 2001 From: "Bobby (Jun) Zhang" Date: Tue, 26 Jul 2016 18:19:53 +0800 Subject: [PATCH 04/14] README update (#590) README update to highlight the benefits of Harbor --- README.md | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 3ed8e62d3..b5bbda471 100644 --- a/README.md +++ b/README.md @@ -5,22 +5,25 @@ ![alg tag](https://cloud.githubusercontent.com/assets/2390463/13484557/088a1000-e13a-11e5-87d4-a64366365bef.png) -Project Harbor is an enterprise-class registry server, which extends the open source Docker Registry server by adding the functionality usually required by an enterprise, such as security, replication and management. Harbor is primarily designed to be a private registry - providing the needed security and control that enterprises require. It also helps minimize bandwidth usage, which is helpful to both improve productivity (local network access) as well as performance (for those with poor internet connectivity). +Project Harbor is an enterprise-class registry server that stores and distributes Docker images. Harbor extends the open source Docker Distribution by adding the functionalities usually required by an enterprise, such as security, identity and management. As an enterprise private registry, Harbor offers better performance and security. Having a registry closer to the build and run environment improves the image transfer efficiency. Harbor supports the setup of multiple registries and has images replicated between them. With Harbor, the images are stored within the private registry, keeping the bits and intellectual properties behind the company firewall. In addition, Harbor offers advanced security features, such as user management, access control and activity auditing. ### Features -* **Role based access control**: Users and Docker repositories are organized via "projects", a user can have different permission for images under a project. -* **Image replication**: Images can be replicated(synchronized) between multiple registry instances. Great for load balancing and distributed data centers. -* **Graphical user portal**: User can easily browse, search Docker repositories, manage projects/namespaces. +* **Role based access control**: Users and repositories are organized via 'projects' and a user can have different permission for images under a project. +* **Image replication**: Images can be replicated (synchronized) between multiple registry instances. Great for load balancing, high availability, hybrid and multi-cloud scenarios. +* **Graphical user portal**: User can easily browse, search repositories and manage projects. * **AD/LDAP support**: Harbor integrates with existing enterprise AD/LDAP for user authentication and management. * **Auditing**: All the operations to the repositories are tracked. * **Internationalization**: Already localized for English, Chinese, German, Japanese and Russian. More languages can be added. -* **RESTful API**: RESTful APIs for most administrative operations, easing intergration with external management platforms. +* **RESTful API**: RESTful APIs for most administrative operations, easy to integrate with external systems. +* **Easy deployment**: docker compose and offline installer. -### Getting Started -Harbor is self-contained and can be easily deployed via docker-compose (Quick-Start steps below). Refer to the [Installation and Configuration Guide](docs/installation_guide.md) for detailed information. +### Install -**System requirements:** -Harbor only works with docker 1.10+ and docker-compose 1.6.0+, and an internet-connected host. +**System requirements:** +Harbor only works with docker 1.10.0+ and docker-compose 1.6.0+. + +#### Install via docker compose +On an Internet connected host, Harbor can be easily installed via docker-compose: 1. Get the source code: @@ -43,22 +46,24 @@ Harbor only works with docker 1.10+ and docker-compose 1.6.0+, and an internet-c $ docker-compose up -d ``` -_If everything worked properly, you should be able to open a browser to visit the admin portal at http://reg.yourdomain.com . Note that the default administrator username/password are admin/Harbor12345 ._ +#### Install via offline installer +For those who do not want to clone the source, or need to install Harbor on a server not connected to the Internet, there is a pre-built installation package available. For details on how to download and use the installation package, please refer to [Installation and Configuration Guide](docs/installation_guide.md). -Log in to the admin portal and create a new project, e.g. `myproject`. You can then use docker commands to login and push images (By default, the registry server listens on port 80): +#### After installation +_If everything worked properly, you should be able to open a browser to visit the admin portal at http://reg.yourdomain.com. Note that the default administrator username/password are admin/Harbor12345._ + +Log in to the admin portal and create a new project, e.g. `myproject`. You can then use docker commands to login and push images (by default, the registry server listens on port 80): ```sh $ docker login reg.yourdomain.com $ docker push reg.yourdomain.com/myproject/myrepo ``` -**Data migration:** +### Upgrade -If you are upgrading Harbor from an older version with existing data, you may need to migrate the data to fit the new database schema. For more details please refer to [Data Migration Guide](docs/migration_guide.md) . +If you are upgrading Harbor from an older version with existing data, you need to migrate the data to fit the new database schema. For more details, please refer to [Data Migration Guide](docs/migration_guide.md). -**NOTE:** -For those who don't want to clone the source, or need to install Harbor on a server not connected to the Internet - there is a pre-built installation package available. For details on how to download and use this installation package, please refer to [Installation and Configuration Guide](docs/installation_guide.md) . - -For information on how to use Harbor, please see [User Guide](docs/user_guide.md) . +### Run +For information on how to use Harbor, please take a look at [User Guide](docs/user_guide.md). ### Contribution We welcome contributions from the community. If you wish to contribute code and you have not signed our contributor license agreement (CLA), our bot will update the issue when you open a pull request. For any questions about the CLA process, please refer to our [FAQ](https://cla.vmware.com/faq). @@ -77,4 +82,4 @@ Harbor is available under the [Apache 2 license](LICENSE). beego Harbor is powered by Beego. ### About -Project Harbor is initiated by VMware China R&D as a Cloud Application Accelerator (CAA) project. CAA provides a set of tools to improve the productivity of cloud developers in China and other countries. CAA includes tools like registry server, mirror server, decentralized image distributor, etc. +Project Harbor is initiated by the Advanced Technology Center (ATC), VMware China R&D as a Cloud Application Accelerator (CAA) project. From 405f013e7aa7e709131e4232fe5b62667b439629 Mon Sep 17 00:00:00 2001 From: Tan Jiang Date: Tue, 26 Jul 2016 18:30:13 +0800 Subject: [PATCH 05/14] remove license --- contrib/sdk/harbor-py/LICENSE | 201 ---------------------------------- 1 file changed, 201 deletions(-) delete mode 100644 contrib/sdk/harbor-py/LICENSE diff --git a/contrib/sdk/harbor-py/LICENSE b/contrib/sdk/harbor-py/LICENSE deleted file mode 100644 index 8dada3eda..000000000 --- a/contrib/sdk/harbor-py/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. From 9b687f2ed62781b6a78b3b869b0b62a1e2f9bba6 Mon Sep 17 00:00:00 2001 From: tobe Date: Wed, 27 Jul 2016 09:13:25 +0800 Subject: [PATCH 06/14] Replace simplejson with json and fix missed print statement --- .../harbor-py/harborclient/harborclient.py | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/contrib/sdk/harbor-py/harborclient/harborclient.py b/contrib/sdk/harbor-py/harborclient/harborclient.py index 91d8b5d58..31f9690bc 100755 --- a/contrib/sdk/harbor-py/harborclient/harborclient.py +++ b/contrib/sdk/harbor-py/harborclient/harborclient.py @@ -1,8 +1,8 @@ #!/usr/bin/env python -import requests -import simplejson +import json import logging +import requests logging.basicConfig(level=logging.INFO) @@ -52,7 +52,8 @@ class HarborClient(object): project_id, project_name)) return project_id else: - pritn("Fail to get project id from project name", project_name) + logging.error("Fail to get project id from project name", + project_name) return None # GET /search @@ -107,8 +108,8 @@ class HarborClient(object): def create_project(self, project_name, is_public=False): result = False path = '%s://%s/api/projects' % (self.protocol, self.host) - request_body = simplejson.dumps({'project_name': project_name, - 'public': is_public}) + request_body = json.dumps({'project_name': project_name, + 'public': is_public}) response = requests.post(path, cookies={'beegosessionID': self.session_id}, data=request_body) @@ -129,7 +130,7 @@ class HarborClient(object): result = False path = '%s://%s/api/projects/%s/publicity?project_id=%s' % ( self.protocol, self.host, project_id, project_id) - request_body = simplejson.dumps({'public': is_public}) + request_body = json.dumps({'public': is_public}) response = requests.put(path, cookies={'beegosessionID': self.session_id}, data=request_body) @@ -175,11 +176,11 @@ class HarborClient(object): def create_user(self, username, email, password, realname, comment): result = False path = '%s://%s/api/users' % (self.protocol, self.host) - request_body = simplejson.dumps({'username': username, - 'email': email, - 'password': password, - 'realname': realname, - 'comment': comment}) + request_body = json.dumps({'username': username, + 'email': email, + 'password': password, + 'realname': realname, + 'comment': comment}) response = requests.post(path, cookies={'beegosessionID': self.session_id}, data=request_body) @@ -199,9 +200,9 @@ class HarborClient(object): result = False path = '%s://%s/api/users/%s?user_id=%s' % (self.protocol, self.host, user_id, user_id) - request_body = simplejson.dumps({'email': email, - 'realname': realname, - 'comment': comment}) + request_body = json.dumps({'email': email, + 'realname': realname, + 'comment': comment}) response = requests.put(path, cookies={'beegosessionID': self.session_id}, data=request_body) @@ -236,8 +237,8 @@ class HarborClient(object): result = False path = '%s://%s/api/users/%s/password?user_id=%s' % ( self.protocol, self.host, user_id, user_id) - request_body = simplejson.dumps({'old_password': old_password, - 'new_password': new_password}) + request_body = json.dumps({'old_password': old_password, + 'new_password': new_password}) response = requests.put(path, cookies={'beegosessionID': self.session_id}, data=request_body) From b68e12b52a9dd97e737479ea251f916b396ea2ed Mon Sep 17 00:00:00 2001 From: kunw Date: Wed, 27 Jul 2016 23:18:24 +0800 Subject: [PATCH 07/14] fixed toggling admin user option. --- static/resources/js/components/user/toggle-admin.directive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/resources/js/components/user/toggle-admin.directive.js b/static/resources/js/components/user/toggle-admin.directive.js index f4eb5e5b7..ec768cd89 100644 --- a/static/resources/js/components/user/toggle-admin.directive.js +++ b/static/resources/js/components/user/toggle-admin.directive.js @@ -25,7 +25,7 @@ function ToggleAdminController($scope, ToggleAdminService, $filter, trFilter) { var vm = this; - vm.isAdmin = (vm.hasAdminRole === 1) ? true : false; + vm.isAdmin = (Number(vm.hasAdminRole) === 1) ? true : false; vm.enabled = vm.isAdmin ? 0 : 1; vm.toggle = toggle; From c4d742a8749db655a52b510fc2a0c2b923b61f06 Mon Sep 17 00:00:00 2001 From: kunw Date: Wed, 27 Jul 2016 23:52:19 +0800 Subject: [PATCH 08/14] refine comparsion expression --- static/resources/js/components/user/toggle-admin.directive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/resources/js/components/user/toggle-admin.directive.js b/static/resources/js/components/user/toggle-admin.directive.js index ec768cd89..01b2d850e 100644 --- a/static/resources/js/components/user/toggle-admin.directive.js +++ b/static/resources/js/components/user/toggle-admin.directive.js @@ -25,7 +25,7 @@ function ToggleAdminController($scope, ToggleAdminService, $filter, trFilter) { var vm = this; - vm.isAdmin = (Number(vm.hasAdminRole) === 1) ? true : false; + vm.isAdmin = (Number(vm.hasAdminRole) === 1); vm.enabled = vm.isAdmin ? 0 : 1; vm.toggle = toggle; From 5ac7f9442a93351a526f0efb513b5cbdb892d12d Mon Sep 17 00:00:00 2001 From: kun wang Date: Thu, 28 Jul 2016 00:15:22 +0800 Subject: [PATCH 09/14] Fixed toggling admin user option. (#597) * fixed toggling admin user option. * refine comparsion expression --- static/resources/js/components/user/toggle-admin.directive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/resources/js/components/user/toggle-admin.directive.js b/static/resources/js/components/user/toggle-admin.directive.js index f4eb5e5b7..01b2d850e 100644 --- a/static/resources/js/components/user/toggle-admin.directive.js +++ b/static/resources/js/components/user/toggle-admin.directive.js @@ -25,7 +25,7 @@ function ToggleAdminController($scope, ToggleAdminService, $filter, trFilter) { var vm = this; - vm.isAdmin = (vm.hasAdminRole === 1) ? true : false; + vm.isAdmin = (Number(vm.hasAdminRole) === 1); vm.enabled = vm.isAdmin ? 0 : 1; vm.toggle = toggle; From b0c957aefc6b547408be15720fb96235f64debc7 Mon Sep 17 00:00:00 2001 From: kunw Date: Thu, 28 Jul 2016 11:22:16 +0800 Subject: [PATCH 10/14] update for toggling admin option check. --- static/resources/js/components/user/list-user.directive.html | 2 +- static/resources/js/components/user/toggle-admin.directive.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/static/resources/js/components/user/list-user.directive.html b/static/resources/js/components/user/list-user.directive.html index 893ad7060..705ca4441 100644 --- a/static/resources/js/components/user/list-user.directive.html +++ b/static/resources/js/components/user/list-user.directive.html @@ -44,7 +44,7 @@ //u.email// //u.creation_time | dateL : 'YYYY-MM-DD HH:mm:ss'// - +    diff --git a/static/resources/js/components/user/toggle-admin.directive.js b/static/resources/js/components/user/toggle-admin.directive.js index 01b2d850e..718a6888e 100644 --- a/static/resources/js/components/user/toggle-admin.directive.js +++ b/static/resources/js/components/user/toggle-admin.directive.js @@ -25,7 +25,7 @@ function ToggleAdminController($scope, ToggleAdminService, $filter, trFilter) { var vm = this; - vm.isAdmin = (Number(vm.hasAdminRole) === 1); + vm.isAdmin = (vm.hasAdminRole === 1); vm.enabled = vm.isAdmin ? 0 : 1; vm.toggle = toggle; From 09fc1f3ee08b6825b58c0586cea5bd76f6c41d15 Mon Sep 17 00:00:00 2001 From: wemeya Date: Thu, 28 Jul 2016 16:18:24 +0800 Subject: [PATCH 11/14] add script to auto configure platform to pull images from --- contrib/docker-compose.yml.daocloud | 68 ---------------------- contrib/prebuild-install/README.md | 1 + contrib/prebuild-install/docker-compose.sh | 32 ++++++++++ 3 files changed, 33 insertions(+), 68 deletions(-) delete mode 100644 contrib/docker-compose.yml.daocloud create mode 100644 contrib/prebuild-install/README.md create mode 100755 contrib/prebuild-install/docker-compose.sh diff --git a/contrib/docker-compose.yml.daocloud b/contrib/docker-compose.yml.daocloud deleted file mode 100644 index e93fb42f1..000000000 --- a/contrib/docker-compose.yml.daocloud +++ /dev/null @@ -1,68 +0,0 @@ -version: '2' -services: - log: - image: daocloud.io/harbor/deploy_log:latest - volumes: - - /var/log/harbor/:/var/log/docker/ - ports: - - 1514:514 - registry: - image: daocloud.io/library/registry:2.3.0 - volumes: - - /data/registry:/storage - - ./config/registry/:/etc/registry/ - ports: - - 5001:5001 - command: - /etc/registry/config.yml - depends_on: - - log - logging: - driver: "syslog" - options: - syslog-address: "tcp://127.0.0.1:1514" - syslog-tag: "registry" - mysql: - image: daocloud.io/harbor/deploy_mysql:latest - volumes: - - /data/database:/var/lib/mysql - env_file: - - ./config/db/env - depends_on: - - log - logging: - driver: "syslog" - options: - syslog-address: "tcp://127.0.0.1:1514" - syslog-tag: "mysql" - ui: - image: daocloud.io/harbor/deploy_ui:latest - env_file: - - ./config/ui/env - volumes: - - ./config/ui/app.conf:/etc/ui/app.conf - - ./config/ui/private_key.pem:/etc/ui/private_key.pem - depends_on: - - log - logging: - driver: "syslog" - options: - syslog-address: "tcp://127.0.0.1:1514" - syslog-tag: "ui" - proxy: - image: daocloud.io/library/nginx:1.9 - volumes: - - ./config/nginx:/etc/nginx - ports: - - 80:80 - - 443:443 - depends_on: - - mysql - - registry - - ui - - log - logging: - driver: "syslog" - options: - syslog-address: "tcp://127.0.0.1:1514" - syslog-tag: "proxy" diff --git a/contrib/prebuild-install/README.md b/contrib/prebuild-install/README.md new file mode 100644 index 000000000..3984e78b4 --- /dev/null +++ b/contrib/prebuild-install/README.md @@ -0,0 +1 @@ +docker-compose.sh is used to configure docker-compose.yml to pull images from platform like docker hub, daocloud.io and others. If you don't want to waste time on building images, you can execute this script to pull images from platform you prefer. Currently, we only support daocloud.io and docker hub, the default is docker hub. diff --git a/contrib/prebuild-install/docker-compose.sh b/contrib/prebuild-install/docker-compose.sh new file mode 100755 index 000000000..eff4aa7f4 --- /dev/null +++ b/contrib/prebuild-install/docker-compose.sh @@ -0,0 +1,32 @@ +#/bin/eash +read -p "Please input the platform name you want to pull images, for docker hub, enter 1; for daocloud.io, enter 2, otherwise enter the name of the platform, the default is 1:" choice +cd ../../Deploy +template_file="docker-compose.yml.template" +yml_file='docker-compose.yml' +if test -e $template_file +then + cp $template_file $yml_file +else + cp $yml_file $template_file +fi +platform='' +choice=${choice:-1} +if [ $choice == '1' ] +then + platform='prjharbor/' +elif [ $choice == '2' ] +then + platform='daocloud.io/harbor/' +else + platform=$choice +fi +version='0.3.0' +log='deploy_log:' +db='deploy_mysql:' +job_service='deploy_jobservice:' +ui='deploy_ui:' +sed -i -- '/build: .\/log\//c\ image: '$platform$log$version'' $yml_file +sed -i -- '/build: .\/db\//c\ image: '$platform$db$version'' $yml_file +sed -i -- '/ui:/{n;N;N;d}' $yml_file && sed -i -- '/ui:/a\\ image: '$platform$ui$version'' $yml_file +sed -i -- '/jobservice:/{n;N;N;d}' $yml_file && sed -i -- '/jobservice:/a\\ image: '$platform$job_service$version'' $yml_file +echo "succeed! " From 6ca46b5b143498a35d49c3cdb1769b8e6acb4a31 Mon Sep 17 00:00:00 2001 From: wemeya Date: Thu, 28 Jul 2016 19:19:56 +0800 Subject: [PATCH 12/14] modify docker-compose.sh --- contrib/prebuild-install/docker-compose.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/prebuild-install/docker-compose.sh b/contrib/prebuild-install/docker-compose.sh index eff4aa7f4..2e3a2f946 100755 --- a/contrib/prebuild-install/docker-compose.sh +++ b/contrib/prebuild-install/docker-compose.sh @@ -1,4 +1,4 @@ -#/bin/eash +#/bin/bash read -p "Please input the platform name you want to pull images, for docker hub, enter 1; for daocloud.io, enter 2, otherwise enter the name of the platform, the default is 1:" choice cd ../../Deploy template_file="docker-compose.yml.template" From 82af69d9f6b05ba6eb1803146faab0ca763dd9de Mon Sep 17 00:00:00 2001 From: Wenkai Yin Date: Sun, 31 Jul 2016 20:21:19 +0800 Subject: [PATCH 13/14] fix #591 --- api/replication_job.go | 4 ++++ api/repository.go | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/api/replication_job.go b/api/replication_job.go index ae3d080a3..49db4ccad 100644 --- a/api/replication_job.go +++ b/api/replication_job.go @@ -134,6 +134,10 @@ func (ra *RepJobAPI) Delete() { ra.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) } + if job == nil { + ra.CustomAbort(http.StatusNotFound, fmt.Sprintf("job %d not found", ra.jobID)) + } + if job.Status == models.JobPending || job.Status == models.JobRunning { ra.CustomAbort(http.StatusBadRequest, fmt.Sprintf("job is %s, can not be deleted", job.Status)) } diff --git a/api/repository.go b/api/repository.go index 8de2f2bcc..260757538 100644 --- a/api/repository.go +++ b/api/repository.go @@ -17,6 +17,7 @@ package api import ( "encoding/json" + "fmt" "net/http" "os" "sort" @@ -210,6 +211,10 @@ func (ra *RepositoryAPI) GetTags() { ra.CustomAbort(http.StatusInternalServerError, "") } + if project == nil { + ra.CustomAbort(http.StatusNotFound, fmt.Sprintf("project %s not found", projectName)) + } + if project.Public == 0 { userID := ra.ValidateUser() if !checkProjectPermission(userID, project.ProjectID) { From 1fa32fcb274194ec20326fb099a2dbd68a9e55f2 Mon Sep 17 00:00:00 2001 From: Wenkai Yin Date: Sun, 31 Jul 2016 20:24:13 +0800 Subject: [PATCH 14/14] longer the timeout time for notification --- Deploy/templates/registry/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Deploy/templates/registry/config.yml b/Deploy/templates/registry/config.yml index 999488a95..faabe10cd 100644 --- a/Deploy/templates/registry/config.yml +++ b/Deploy/templates/registry/config.yml @@ -30,6 +30,6 @@ notifications: - name: harbor disabled: false url: http://ui/service/notifications - timeout: 500ms + timeout: 3000ms threshold: 5 backoff: 1s