28
28
29
29
__all__ = ["fetch" , "available" , "Base" ]
30
30
31
+ import functools
31
32
import logging
32
33
import pkgutil
34
+ import urllib
33
35
34
36
import docker_registry .drivers
35
37
39
41
logger = logging .getLogger (__name__ )
40
42
41
43
44
+ def check (value ):
45
+ value = str (value )
46
+ if value == '..' :
47
+ value = '%2E%2E'
48
+ return urllib .quote_plus (value )
49
+
50
+
51
+ def filter_args (f ):
52
+ @functools .wraps (f )
53
+ def wrapper (* args , ** kwargs ):
54
+ args = list (args )
55
+ ref = args .pop (0 )
56
+ args = [check (arg ) for arg in args ]
57
+ args .insert (0 , ref )
58
+ for key , value in kwargs .iteritems ():
59
+ kwargs [key ] = check (value )
60
+ return f (* args , ** kwargs )
61
+ return wrapper
62
+
63
+
42
64
class Base (object ):
43
65
44
66
"""Storage is a convenience class...
@@ -59,6 +81,10 @@ class Base(object):
59
81
repositories = 'repositories'
60
82
images = 'images'
61
83
84
+ def _repository_path (self , namespace , repository ):
85
+ return '{0}/{1}/{2}' .format (
86
+ self .repositories , namespace , repository )
87
+
62
88
# Set the IO buffer to 128kB
63
89
buffer_size = 128 * 1024
64
90
# By default no storage plugin supports it
@@ -68,60 +94,74 @@ def __init__(self, path=None, config=None):
68
94
pass
69
95
70
96
# FIXME(samalba): Move all path resolver in each module (out of the base)
97
+ @filter_args
71
98
def images_list_path (self , namespace , repository ):
72
- repository_path = self .repository_path (
99
+ repository_path = self ._repository_path (
73
100
namespace = namespace , repository = repository )
74
101
return '{0}/_images_list' .format (repository_path )
75
102
103
+ @filter_args
76
104
def image_json_path (self , image_id ):
77
105
return '{0}/{1}/json' .format (self .images , image_id )
78
106
107
+ @filter_args
79
108
def image_mark_path (self , image_id ):
80
109
return '{0}/{1}/_inprogress' .format (self .images , image_id )
81
110
111
+ @filter_args
82
112
def image_checksum_path (self , image_id ):
83
113
return '{0}/{1}/_checksum' .format (self .images , image_id )
84
114
115
+ @filter_args
85
116
def image_layer_path (self , image_id ):
86
117
return '{0}/{1}/layer' .format (self .images , image_id )
87
118
119
+ @filter_args
88
120
def image_ancestry_path (self , image_id ):
89
121
return '{0}/{1}/ancestry' .format (self .images , image_id )
90
122
123
+ @filter_args
91
124
def image_files_path (self , image_id ):
92
125
return '{0}/{1}/_files' .format (self .images , image_id )
93
126
127
+ @filter_args
94
128
def image_diff_path (self , image_id ):
95
129
return '{0}/{1}/_diff' .format (self .images , image_id )
96
130
131
+ @filter_args
97
132
def repository_path (self , namespace , repository ):
98
133
return '{0}/{1}/{2}' .format (
99
134
self .repositories , namespace , repository )
100
135
136
+ @filter_args
101
137
def tag_path (self , namespace , repository , tagname = None ):
102
- repository_path = self .repository_path (
138
+ repository_path = self ._repository_path (
103
139
namespace = namespace , repository = repository )
104
140
if not tagname :
105
141
return repository_path
106
142
return '{0}/tag_{1}' .format (repository_path , tagname )
107
143
144
+ @filter_args
108
145
def repository_json_path (self , namespace , repository ):
109
- repository_path = self .repository_path (
146
+ repository_path = self ._repository_path (
110
147
namespace = namespace , repository = repository )
111
148
return '{0}/json' .format (repository_path )
112
149
150
+ @filter_args
113
151
def repository_tag_json_path (self , namespace , repository , tag ):
114
- repository_path = self .repository_path (
152
+ repository_path = self ._repository_path (
115
153
namespace = namespace , repository = repository )
116
154
return '{0}/tag{1}_json' .format (repository_path , tag )
117
155
156
+ @filter_args
118
157
def index_images_path (self , namespace , repository ):
119
- repository_path = self .repository_path (
158
+ repository_path = self ._repository_path (
120
159
namespace = namespace , repository = repository )
121
160
return '{0}/_index_images' .format (repository_path )
122
161
162
+ @filter_args
123
163
def private_flag_path (self , namespace , repository ):
124
- repository_path = self .repository_path (
164
+ repository_path = self ._repository_path (
125
165
namespace = namespace , repository = repository )
126
166
return '{0}/_private' .format (repository_path )
127
167
0 commit comments