amalfra / docker-hub

Docker Hub in your terminal
MIT License
46 stars 18 forks source link

Is there a way to override DOCKER_HUB_API_ENDPOINT #21

Open chimmmpie opened 1 year ago

chimmmpie commented 1 year ago

As there are becoming more and more docker registries it would be nice to be able to query them as well. Is there a option to override the DOCKER_HUB_API_ENDPOINT and or would u consider it useful to make it configurable?

amalfra commented 1 year ago

@chimmmpie Thanks for the suggestion. That would be a good feature to have. It needs to be checked whether all these registries are also expected to have same API endpoints are the main registry.

chimmmpie commented 1 year ago

I expect docker (unverified) to use the same API to fetch data. So i would expect it to be the same. But ill test a few if i have some time.

chimmmpie commented 1 year ago

I did some digging around, From what i can find the tags api for docker registry is authenticated. For the web api used by dockerhub there does not seem to be a standard. That makes this case impossible.

https://docs.docker.com/registry/spec/api/#tags

chimmmpie commented 1 year ago

I did some digging around when i found some other specs that point me on how to do it. Here is some dirty code that should work for any docker compatible repo given you have credentials. Those credentials we could be taken from the docker config. $HOME/.docker/config.json

USERNAME = 'someusername'
PASSWORD = 'somepassword'
# Define the authentication URL and registry URL
REGISTRY = "https://registry-1.docker.io/"
CI_PROJECT_PATH = "yuzutech/kroki-bpmn"

# Get the image tag list
response = requests.get(
    f"{REGISTRY}/v2/{CI_PROJECT_PATH}/tags/list"
)
token = None
if 'Www-Authenticate' in response.headers:
    www_authenticate = response.headers['Www-Authenticate']
    first = www_authenticate.split(',')[0]
    realm = first.split('"')[1]
    print('authenticate url', realm)
    services_raw = www_authenticate.split(',')[1]
    services = services_raw.split('"')[1]
    scope_raw = www_authenticate.split(',')[2]
    scope = scope_raw.split('"')[1]
    url = f"{realm}?service={services}&scope={scope}"
    print(url)
    response = requests.get(url, auth=(USERNAME, PASSWORD))
    token = response.json()['token']
    print(response.json())
    print(token)
    print()

if token is not None:
    headers = {
        'Authorization': f'Bearer {token}'
    }
else:
    headers = {}
print('headers:', headers)
response = requests.get(
    f"{REGISTRY}/v2/{CI_PROJECT_PATH}/tags/list", headers=headers
)
# print(response.headers['Www-Authenticate'])
REGISTRY_TAG_LIST = response.json()
print(REGISTRY_TAG_LIST)
tags = REGISTRY_TAG_LIST.get('tags', [])
print(tags)

I would keep the current code and add something like this as a fallback for other docker compatible registries.