diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a7147b5..c80fa5f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 22.1.0 + rev: 22.3.0 hooks: - id: black args: ['--skip-string-normalization'] diff --git a/lain_cli/cluster_values/values-test.yaml b/lain_cli/cluster_values/values-test.yaml index b6e52e6..751db86 100644 --- a/lain_cli/cluster_values/values-test.yaml +++ b/lain_cli/cluster_values/values-test.yaml @@ -10,6 +10,8 @@ # 镜像仓库 registry: docker.io/timfeirg +# 默认使用 http 访问 registry ,可以配置为使用 https +# registry_endpoint_use_https: yes # 有一些 PaaS 提供内网镜像加速, 集群内外用的镜像 tag 不一样 # internalRegistry: registry.in.example.com @@ -25,6 +27,10 @@ secrets_env: dockerhub_username: DOCKERHUB_USERNAME dockerhub_password: DOCKERHUB_PASSWORD +# 或者提供获取访问 registry api 需要的 access token 的获取命令。如 AWS ECR ,可以这样配置: +# registry_token_fetch_cmd: "aws ecr get-authorization-token --output text --query 'authorizationData[].authorizationToken'" +# registry_token_type: "Basic" + extra_docs: | 在这里书写额外的欢迎信息 diff --git a/lain_cli/registry.py b/lain_cli/registry.py index 051006c..5230d2d 100644 --- a/lain_cli/registry.py +++ b/lain_cli/registry.py @@ -3,7 +3,12 @@ import requests from tenacity import retry, stop_after_attempt, wait_fixed -from lain_cli.utils import RegistryUtils, RequestClientMixin, tell_cluster_config +from lain_cli.utils import ( + RegistryUtils, + RequestClientMixin, + subprocess_run, + tell_cluster_config, +) class Registry(RequestClientMixin, RegistryUtils): @@ -25,27 +30,45 @@ def __init__(self, registry=None, **kwargs): api_host = 'index.docker.io' self.endpoint = f'http://{api_host}' else: - self.endpoint = f'http://{registry}' + https = kwargs.get('registry_endpoint_use_https', False) + protocol = 'https' if https else 'http' + self.endpoint = f'{protocol}://{registry}' self.dockerhub_password = kwargs.get('dockerhub_password') self.dockerhub_username = kwargs.get('dockerhub_username') + self.token_fetch_cmd = kwargs.get('registry_token_fetch_cmd') + self.token_type = kwargs.get('registry_token_type', 'Bearer') + def prepare_token(self, scope): - if not all([self.dockerhub_password, self.dockerhub_username]): - return - res = requests.post( - 'https://auth.docker.io/token', - data={ - 'grant_type': 'password', - 'service': 'registry.docker.io', - 'scope': scope, - 'client_id': 'dockerengine', - 'username': self.dockerhub_username, - 'password': self.dockerhub_password, - }, - ) - access_token = res.json()['access_token'] - self.headers['Authorization'] = f'Bearer {access_token}' + if self.token_fetch_cmd: + res = subprocess_run( + self.token_fetch_cmd, + shell=True, + check=True, + capture_output=True, + ) + token = res.stdout.decode().strip() + + elif all([self.dockerhub_password, self.dockerhub_username]): + res = requests.post( + 'https://auth.docker.io/token', + data={ + 'grant_type': 'password', + 'service': 'registry.docker.io', + 'scope': scope, + 'client_id': 'dockerengine', + 'username': self.dockerhub_username, + 'password': self.dockerhub_password, + }, + ) + token = res.json()['access_token'] + + else: + token = None + + if token: + self.headers['Authorization'] = f'{self.token_type} {token}' def request(self, *args, **kwargs): res = super().request(*args, **kwargs) @@ -79,7 +102,7 @@ def list_tags(self, repo_name, n=None, timeout=90): repo = f'{self.namespace}/{repo_name}' if self.namespace else repo_name path = f'/v2/{repo}/tags/list' self.prepare_token(scope=f'repository:{repo}:pull,push') - responson = self.get(path, params={'n': 99999}, timeout=timeout).json() + responson = self.get(path, params={'n': 1000}, timeout=timeout).json() if 'tags' not in responson: return [] tags = self.sort_and_filter(responson.get('tags') or [], n=n)