11# -*- coding: utf-8 -*-
22
3+ import re
4+
35import flask
46
57from docker_registry .core import compat
1315
1416from .app import app # noqa
1517
18+ RE_USER_AGENT = re .compile ('([^\s/]+)/([^\s/]+)' )
1619
1720store = storage .load ()
1821
@@ -51,7 +54,7 @@ def put_username(username):
5154 return toolkit .response ('' , 204 )
5255
5356
54- def update_index_images (namespace , repository , data_arg ):
57+ def update_index_images (namespace , repository , data_arg , arch , os ):
5558 path = store .index_images_path (namespace , repository )
5659 sender = flask .current_app ._get_current_object ()
5760 try :
@@ -70,13 +73,27 @@ def update_index_images(namespace, repository, data_arg):
7073 data = images .values ()
7174 # Note(dmp): unicode patch
7275 store .put_json (path , data )
76+
77+ # Get image arch and os from the json property, although
78+ # we have to do it safely in case this is an image with no
79+ # image data (e.g. testcase mock-up images)
80+ try :
81+ img_data = store .get_content (store .image_json_path (data [0 ]['id' ]))
82+ arch = json .loads (img_data )['architecture' ]
83+ os = json .loads (img_data )['os' ]
84+ except exceptions .FileNotFoundError :
85+ # no img data for this image, but it still exists
86+ # leave the default arch/os that were passed in
87+ pass
88+
7389 signals .repository_updated .send (
74- sender , namespace = namespace , repository = repository , value = data )
90+ sender , namespace = namespace , repository = repository ,
91+ value = data , arch = arch , os = os )
7592 except exceptions .FileNotFoundError :
7693 signals .repository_created .send (
7794 sender , namespace = namespace , repository = repository ,
7895 # Note(dmp): unicode patch
79- value = json .loads (data_arg .decode ('utf8' )))
96+ value = json .loads (data_arg .decode ('utf8' )), arch = arch , os = os )
8097 store .put_content (path , data_arg )
8198
8299
@@ -88,14 +105,25 @@ def update_index_images(namespace, repository, data_arg):
88105@toolkit .requires_auth
89106def put_repository (namespace , repository , images = False ):
90107 data = None
108+ # Default arch/os are amd64/linux
109+ arch = 'amd64'
110+ os = 'linux'
111+ # If caller is docker host, retrieve arch/os from user agent
112+ user_agent = flask .request .headers .get ('user-agent' , '' )
113+ ua = dict (RE_USER_AGENT .findall (user_agent ))
114+ if 'arch' in ua :
115+ arch = ua ['arch' ]
116+ if 'os' in ua :
117+ os = ua ['os' ]
118+
91119 try :
92120 # Note(dmp): unicode patch
93121 data = json .loads (flask .request .data .decode ('utf8' ))
94122 except ValueError :
95123 return toolkit .api_error ('Error Decoding JSON' , 400 )
96124 if not isinstance (data , list ):
97125 return toolkit .api_error ('Invalid data' )
98- update_index_images (namespace , repository , flask .request .data )
126+ update_index_images (namespace , repository , flask .request .data , arch , os )
99127 headers = generate_headers (namespace , repository , 'write' )
100128 code = 204 if images is True else 200
101129 return toolkit .response ('' , code , headers )
@@ -107,9 +135,37 @@ def put_repository(namespace, repository, images=False):
107135@mirroring .source_lookup (index_route = True )
108136def get_repository_images (namespace , repository ):
109137 data = None
138+ # Default arch/os are amd64/linux
139+ arch = 'amd64'
140+ os = 'linux'
141+ # If caller is docker host, retrieve arch/os from user agent
142+ user_agent = flask .request .headers .get ('user-agent' , '' )
143+ ua = dict (RE_USER_AGENT .findall (user_agent ))
144+ if 'arch' in ua :
145+ arch = ua ['arch' ]
146+ if 'os' in ua :
147+ os = ua ['os' ]
148+
110149 try :
111150 path = store .index_images_path (namespace , repository )
112- data = store .get_content (path )
151+ json_data = store .get_json (path )
152+ # we may not have image data (mocked up tests, etc.) so try/except
153+ # on parsing arch and os--and ignore/continue if this is an image
154+ # with no data
155+ try :
156+ img_data = store .get_content (store .image_json_path (
157+ json_data [0 ]['id' ]))
158+ # Get image arch and os from the json property
159+ img_arch = json .loads (img_data )['architecture' ]
160+ img_os = json .loads (img_data )['os' ]
161+ if arch != img_arch or os != img_os :
162+ return toolkit .api_error ('images not found for arch/os pair' ,
163+ 404 )
164+ else :
165+ data = store .get_content (path )
166+ except exceptions .FileNotFoundError :
167+ # simply return the data if image data does not exist
168+ data = store .get_content (path )
113169 except exceptions .FileNotFoundError :
114170 return toolkit .api_error ('images not found' , 404 )
115171 headers = generate_headers (namespace , repository , 'read' )
0 commit comments