diff --git a/contrib/Configure_mirror.md b/contrib/Configure_mirror.md deleted file mode 100644 index 3b01742f7a4..00000000000 --- a/contrib/Configure_mirror.md +++ /dev/null @@ -1,30 +0,0 @@ -# Configuring Harbor as a local registry mirror - -Harbor runs as a local registry by default. It can also be configured as a registry mirror, -which caches downloaded images for subsequent use. Note that under this setup, the Harbor registry only acts as a mirror server and -no longer accepts image pushing requests. Edit `Deploy/templates/registry/config.yml` before executing `./prepare`, and append a `proxy` section as follows: - -``` -proxy: - remoteurl: https://registry-1.docker.io -``` -In order to access private images on the Docker Hub, a username and a password can be supplied: - -``` -proxy: - remoteurl: https://registry-1.docker.io - username: [username] - password: [password] -``` -You will need to pass the `--registry-mirror` option to your Docker daemon on startup: - -``` -docker --registry-mirror=https:// daemon -``` -For example, if your mirror is serving on `http://reg.yourdomain.com`, you would run: - -``` -docker --registry-mirror=https://reg.yourdomain.com daemon -``` - -Refer to the [Registry as a pull through cache](https://docs.docker.com/registry/recipes/mirror/) for detailed information. diff --git a/contrib/registryapi/README.md b/contrib/registryapi/README.md deleted file mode 100644 index 83be8202226..00000000000 --- a/contrib/registryapi/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# registryapi -api for docker registry by token authorization - -+ a simple api class which lies in registryapi.py, which simulates the interactions -between docker registry and the vendor authorization platform like harbor. -``` -usage: -from registryapi import RegistryApi -api = RegistryApi('username', 'password', 'http://www.your_registry_url.com/') -repos = api.getRepositoryList() -tags = api.getTagList('public/ubuntu') -manifest = api.getManifest('public/ubuntu', 'latest') -res = api.deleteManifest('public/ubuntu', '23424545**4343') - -``` - -+ a simple client tool based on api class, which contains basic read and delete -operations for repo, tag, manifest -``` -usage: -./cli.py --username username --password password --registry_endpoint http://www.your_registry_url.com/ target action params - -target can be: repo, tag, manifest -action can be: list, get, delete -params can be: --repo --ref --tag - -more see: ./cli.py -h - -``` diff --git a/contrib/registryapi/cli.py b/contrib/registryapi/cli.py deleted file mode 100755 index 298c0523f61..00000000000 --- a/contrib/registryapi/cli.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python -# -*- coding:utf-8 -*- -# bug-report: feilengcui008@gmail.com - -""" cli tool """ - -import argparse -import sys -import json -from registry import RegistryApi - - -class ApiProxy(object): - """ user RegistryApi """ - def __init__(self, registry, args): - self.registry = registry - self.args = args - self.callbacks = dict() - self.register_callback("repo", "list", self.list_repo) - self.register_callback("tag", "list", self.list_tag) - self.register_callback("tag", "delete", self.delete_tag) - self.register_callback("manifest", "list", self.list_manifest) - self.register_callback("manifest", "delete", self.delete_manifest) - self.register_callback("manifest", "get", self.get_manifest) - - def register_callback(self, target, action, func): - """ register real actions """ - if not target in self.callbacks.keys(): - self.callbacks[target] = {action: func} - return - self.callbacks[target][action] = func - - def execute(self, target, action): - """ execute """ - print json.dumps(self.callbacks[target][action](), indent=4, sort_keys=True) - - def list_repo(self): - """ list repo """ - return self.registry.getRepositoryList(self.args.num) - - def list_tag(self): - """ list tag """ - return self.registry.getTagList(self.args.repo) - - def delete_tag(self): - """ delete tag """ - (_, ref) = self.registry.existManifest(self.args.repo, self.args.tag) - if ref is not None: - return self.registry.deleteManifest(self.args.repo, ref) - return False - - def list_manifest(self): - """ list manifest """ - tags = self.registry.getTagList(self.args.repo)["tags"] - manifests = list() - if tags is None: - return None - for i in tags: - content = self.registry.getManifestWithConf(self.args.repo, i) - manifests.append({i: content}) - return manifests - - def delete_manifest(self): - """ delete manifest """ - return self.registry.deleteManifest(self.args.repo, self.args.ref) - - def get_manifest(self): - """ get manifest """ - return self.registry.getManifestWithConf(self.args.repo, self.args.tag) - - -# since just a script tool, we do not construct whole target->action->args -# structure with oo abstractions which has more flexibility, just register -# parser directly -def get_parser(): - """ return a parser """ - parser = argparse.ArgumentParser("cli") - - parser.add_argument('--username', action='store', required=True, help='username') - parser.add_argument('--password', action='store', required=True, help='password') - parser.add_argument('--registry_endpoint', action='store', required=True, - help='registry endpoint') - - subparsers = parser.add_subparsers(dest='target', help='target to operate on') - - # repo target - repo_target_parser = subparsers.add_parser('repo', help='target repository') - repo_target_subparsers = repo_target_parser.add_subparsers(dest='action', - help='repository subcommand') - repo_cmd_parser = repo_target_subparsers.add_parser('list', help='list repositories') - repo_cmd_parser.add_argument('--num', action='store', required=False, default=None, - help='the number of data to return') - - # tag target - tag_target_parser = subparsers.add_parser('tag', help='target tag') - tag_target_subparsers = tag_target_parser.add_subparsers(dest='action', - help='tag subcommand') - tag_list_parser = tag_target_subparsers.add_parser('list', help='list tags') - tag_list_parser.add_argument('--repo', action='store', required=True, help='list tags') - tag_delete_parser = tag_target_subparsers.add_parser('delete', help='delete tag') - tag_delete_parser.add_argument('--repo', action='store', required=True, help='delete tags') - tag_delete_parser.add_argument('--tag', action='store', required=True, - help='tag reference') - - # manifest target - manifest_target_parser = subparsers.add_parser('manifest', help='target manifest') - manifest_target_subparsers = manifest_target_parser.add_subparsers(dest='action', - help='manifest subcommand') - manifest_list_parser = manifest_target_subparsers.add_parser('list', help='list manifests') - manifest_list_parser.add_argument('--repo', action='store', required=True, - help='list manifests') - manifest_delete_parser = manifest_target_subparsers.add_parser('delete', help='delete manifest') - manifest_delete_parser.add_argument('--repo', action='store', required=True, - help='delete manifest') - manifest_delete_parser.add_argument('--ref', action='store', required=True, - help='manifest reference') - manifest_get_parser = manifest_target_subparsers.add_parser('get', help='get manifest content') - manifest_get_parser.add_argument('--repo', action='store', required=True, help='delete tags') - manifest_get_parser.add_argument('--tag', action='store', required=True, - help='manifest reference') - - return parser - - -def main(): - """ main entrance """ - parser = get_parser() - options = parser.parse_args(sys.argv[1:]) - registry = RegistryApi(options.username, options.password, options.registry_endpoint) - proxy = ApiProxy(registry, options) - proxy.execute(options.target, options.action) - - -if __name__ == '__main__': - main() diff --git a/contrib/registryapi/registry.py b/contrib/registryapi/registry.py deleted file mode 100644 index a0e1b465189..00000000000 --- a/contrib/registryapi/registry.py +++ /dev/null @@ -1,165 +0,0 @@ -#!/usr/bin/env python -# -*- coding:utf-8 -*- -# bug-report: feilengcui008@gmail.com - -""" api for docker registry """ - -import urllib2 -import urllib -import json -import base64 - - -class RegistryException(Exception): - """ registry api related exception """ - pass - - -class RegistryApi(object): - """ interact with docker registry and harbor """ - def __init__(self, username, password, registry_endpoint): - self.username = username - self.password = password - self.basic_token = base64.encodestring("%s:%s" % (str(username), str(password)))[0:-1] - self.registry_endpoint = registry_endpoint.rstrip('/') - auth = self.pingRegistry("%s/v2/_catalog" % (self.registry_endpoint,)) - if auth is None: - raise RegistryException("get token realm and service failed") - self.token_endpoint = auth[0] - self.service = auth[1] - - def pingRegistry(self, registry_endpoint): - """ ping v2 registry and get realm and service """ - headers = dict() - try: - res = urllib2.urlopen(registry_endpoint) - except urllib2.HTTPError as e: - headers = e.hdrs.dict - try: - (realm, service, _) = headers['www-authenticate'].split(',') - return (realm[14:-1:], service[9:-1]) - except Exception as e: - return None - - def getBearerTokenForScope(self, scope): - """ get bearer token from harbor """ - payload = urllib.urlencode({'service': self.service, 'scope': scope}) - url = "%s?%s" % (self.token_endpoint, payload) - req = urllib2.Request(url) - req.add_header('Authorization', 'Basic %s' % (self.basic_token,)) - try: - response = urllib2.urlopen(req) - return json.loads(response.read())["token"] - except Exception as e: - return None - - def getRepositoryList(self, n=None): - """ get repository list """ - scope = "registry:catalog:*" - bear_token = self.getBearerTokenForScope(scope) - if bear_token is None: - return None - url = "%s/v2/_catalog" % (self.registry_endpoint,) - if n is not None: - url = "%s?n=%s" % (url, str(n)) - req = urllib2.Request(url) - req.add_header('Authorization', r'Bearer %s' % (bear_token,)) - try: - response = urllib2.urlopen(req) - return json.loads(response.read()) - except Exception as e: - return None - - def getTagList(self, repository): - """ get tag list for repository """ - scope = "repository:%s:pull" % (repository,) - bear_token = self.getBearerTokenForScope(scope) - if bear_token is None: - return None - url = "%s/v2/%s/tags/list" % (self.registry_endpoint, repository) - req = urllib2.Request(url) - req.add_header('Authorization', r'Bearer %s' % (bear_token,)) - try: - response = urllib2.urlopen(req) - return json.loads(response.read()) - except Exception as e: - return None - - def getManifest(self, repository, reference="latest", v1=False): - """ get manifest for tag or digest """ - scope = "repository:%s:pull" % (repository,) - bear_token = self.getBearerTokenForScope(scope) - if bear_token is None: - return None - url = "%s/v2/%s/manifests/%s" % (self.registry_endpoint, repository, reference) - req = urllib2.Request(url) - req.get_method = lambda: 'GET' - req.add_header('Authorization', r'Bearer %s' % (bear_token,)) - req.add_header('Accept', 'application/vnd.docker.distribution.manifest.v2+json') - if v1: - req.add_header('Accept', 'application/vnd.docker.distribution.manifest.v1+json') - try: - response = urllib2.urlopen(req) - return json.loads(response.read()) - except Exception as e: - return None - - def existManifest(self, repository, reference, v1=False): - """ check to see it manifest exist """ - scope = "repository:%s:pull" % (repository,) - bear_token = self.getBearerTokenForScope(scope) - if bear_token is None: - raise RegistryException("manifestExist failed due to token error") - url = "%s/v2/%s/manifests/%s" % (self.registry_endpoint, repository, reference) - req = urllib2.Request(url) - req.get_method = lambda: 'HEAD' - req.add_header('Authorization', r'Bearer %s' % (bear_token,)) - req.add_header('Accept', 'application/vnd.docker.distribution.manifest.v2+json') - if v1: - req.add_header('Accept', 'application/vnd.docker.distribution.manifest.v1+json') - try: - response = urllib2.urlopen(req) - return (True, response.headers.dict["docker-content-digest"]) - except Exception as e: - return (False, None) - - def deleteManifest(self, repository, reference): - """ delete manifest by tag """ - (is_exist, digest) = self.existManifest(repository, reference) - if not is_exist: - raise RegistryException("manifest not exist") - scope = "repository:%s:pull,push" % (repository,) - bear_token = self.getBearerTokenForScope(scope) - if bear_token is None: - raise RegistryException("delete manifest failed due to token error") - url = "%s/v2/%s/manifests/%s" % (self.registry_endpoint, repository, digest) - req = urllib2.Request(url) - req.get_method = lambda: 'DELETE' - req.add_header('Authorization', r'Bearer %s' % (bear_token,)) - try: - urllib2.urlopen(req) - except Exception as e: - return False - return True - - def getManifestWithConf(self, repository, reference="latest"): - """ get manifest for tag or digest """ - manifest = self.getManifest(repository, reference) - if manifest is None: - raise RegistryException("manifest for %s %s not exist" % (repository, reference)) - config_digest = manifest["config"]["digest"] - scope = "repository:%s:pull" % (repository,) - bear_token = self.getBearerTokenForScope(scope) - if bear_token is None: - return None - url = "%s/v2/%s/blobs/%s" % (self.registry_endpoint, repository, config_digest) - req = urllib2.Request(url) - req.get_method = lambda: 'GET' - req.add_header('Authorization', r'Bearer %s' % (bear_token,)) - req.add_header('Accept', 'application/vnd.docker.distribution.manifest.v2+json') - try: - response = urllib2.urlopen(req) - manifest["configContent"] = json.loads(response.read()) - return manifest - except Exception as e: - return None