66from getpass import getpass
77
88from rich import print
9+ from rich .table import Table
910
1011from crpy .common import HTTPConnectionError , UnauthorizedError
1112from crpy .registry import RegistryInfo
12- from crpy .storage import remove_credentials , save_credentials
13+ from crpy .storage import (
14+ decode_credentials ,
15+ get_config ,
16+ remove_credentials ,
17+ save_credentials ,
18+ )
1319
1420
1521async def _pull (args ):
16- ri = RegistryInfo .from_url (args .url [0 ])
22+ ri = RegistryInfo .from_url (args .url [0 ], proxy = args . proxy , insecure = args . insecure )
1723 filename = args .filename
1824 if not filename :
1925 # make file name compatible
@@ -22,7 +28,7 @@ async def _pull(args):
2228
2329
2430async def _push (args ):
25- ri = RegistryInfo .from_url (args .url [0 ])
31+ ri = RegistryInfo .from_url (args .url [0 ], proxy = args . proxy , insecure = args . insecure )
2632 await ri .push (args .filename [0 ])
2733
2834
@@ -31,7 +37,7 @@ async def _login(args):
3137 args .username = input ("Username: " )
3238 if args .password is None :
3339 args .password = getpass ("Password: " )
34- ri = RegistryInfo .from_url (args .url )
40+ ri = RegistryInfo .from_url (args .url , proxy = args . proxy , insecure = args . insecure )
3541 await ri .auth (username = args .username , password = args .password )
3642 save_credentials (ri .registry , args .username , args .password )
3743
@@ -50,13 +56,13 @@ async def _logout(args):
5056
5157
5258async def _inspect_manifest (args ):
53- ri = RegistryInfo .from_url (args .url [0 ])
59+ ri = RegistryInfo .from_url (args .url [0 ], proxy = args . proxy , insecure = args . insecure )
5460 manifest = await ri .get_manifest_from_architecture ()
5561 print (manifest )
5662
5763
5864async def _inspect_config (args ):
59- ri = RegistryInfo .from_url (args .url [0 ])
65+ ri = RegistryInfo .from_url (args .url [0 ], proxy = args . proxy , insecure = args . insecure )
6066 raw_config = await ri .get_config ()
6167 config = json .loads (raw_config .data )
6268 if not args .short :
@@ -67,7 +73,7 @@ async def _inspect_config(args):
6773
6874
6975async def _inspect_layer (args ):
70- ri = RegistryInfo .from_url (args .url [0 ])
76+ ri = RegistryInfo .from_url (args .url [0 ], proxy = args . proxy , insecure = args . insecure )
7177 layers = await ri .get_layers ()
7278 ref = args .layer_reference [0 ]
7379 try :
@@ -82,27 +88,43 @@ async def _inspect_layer(args):
8288
8389
8490async def _repositories (args ):
85- ri = RegistryInfo .from_url (args .url [0 ])
91+ ri = RegistryInfo .from_url (args .url [0 ], proxy = args . proxy , insecure = args . insecure )
8692 for entry in await ri .list_repositories ():
8793 print (entry )
8894
8995
9096async def _tags (args ):
91- ri = RegistryInfo .from_url (args .url [0 ])
97+ ri = RegistryInfo .from_url (args .url [0 ], proxy = args . proxy , insecure = args . insecure )
9298 if not ri .repository :
9399 raise ValueError ("Repository must be provided to list tags!" )
94100 for entry in await ri .list_tags ():
95101 print (entry )
96102
97103
98104async def _delete (args ):
99- ri = RegistryInfo .from_url (args .url [0 ])
105+ ri = RegistryInfo .from_url (args .url [0 ], proxy = args . proxy , insecure = args . insecure )
100106 if not ri .repository :
101107 raise ValueError ("Repository must be provided to list tags!" )
102108 r = await ri .delete_tag ()
103109 print (r .data )
104110
105111
112+ async def _auth (args ):
113+ config = get_config ()
114+
115+ table = Table (title = "Saved credentials" , title_style = "bold" )
116+ table .add_column ("Index" , style = "blue" )
117+ table .add_column ("Url" , style = "cyan" , no_wrap = True )
118+ table .add_column ("Username" , style = "magenta" )
119+ table .add_column ("Password" , style = "green" )
120+ for idx , (url , entry ) in enumerate (config ["auths" ].items ()):
121+ username , password = decode_credentials (entry ["auth" ])
122+ if not args .show_passwords :
123+ password = f"{ password [0 :2 ]} ***{ password [- 2 :]} "
124+ table .add_row (str (idx ), url , username , password )
125+ print (table )
126+
127+
106128def main (* args ):
107129 parser = argparse .ArgumentParser (
108130 prog = "crpy" ,
@@ -115,9 +137,16 @@ def main(*args):
115137 "--insecure" ,
116138 action = "store_true" ,
117139 help = "Use insecure registry. Ignores the validation of the certificate (useful for development registries)." ,
140+ default = False ,
141+ )
142+ parser .add_argument (
143+ "-p" ,
144+ "--proxy" ,
145+ nargs = 1 ,
146+ help = "Proxy for all requests. If your proxy contains authentication, pass it on the request in the usual "
147+ "format \" http://user:[email protected] \" " ,
118148 default = None ,
119149 )
120- parser .add_argument ("-p" , "--proxy" , nargs = 1 , help = "Proxy for all requests." , default = None )
121150 subparsers = parser .add_subparsers ()
122151 pull = subparsers .add_parser (
123152 "pull" ,
@@ -135,6 +164,7 @@ def main(*args):
135164 push .add_argument ("filename" , nargs = 1 , help = "File containing the docker image to be pushed." )
136165 push .add_argument ("url" , nargs = 1 , help = "Remote repository to push to." )
137166
167+ # authentication
138168 login = subparsers .add_parser ("login" , help = "Logs in on a remote repo" )
139169 login .set_defaults (func = _login )
140170 login .add_argument (
@@ -150,29 +180,34 @@ def main(*args):
150180 logout .add_argument ("url" , nargs = "?" , help = "Remote repository to logout from." , default = "index.docker.io" )
151181 logout .set_defaults (func = _logout )
152182
153- inspect = subparsers .add_parser (
154- "inspect" ,
155- help = "Inspects a docker registry metadata. It can inspect configs, manifests and layers." ,
183+ auth = subparsers .add_parser ("auth" , help = "Shows authenticated repositories" )
184+ auth .add_argument (
185+ "--show-passwords" ,
186+ "-s" ,
187+ action = "store_true" ,
188+ default = False ,
189+ help = "If the password or token should be shown in clear text." ,
156190 )
157- inspect_subparser = inspect .add_subparsers ()
191+ auth .set_defaults (func = _auth )
192+
158193 # manifest
159- manifest = inspect_subparser .add_parser ("manifest" , help = "Inspects a docker registry metadata." )
194+ manifest = subparsers .add_parser ("manifest" , help = "Inspects a docker registry metadata." )
160195 manifest .add_argument ("url" , nargs = 1 , help = "Remote repository url." )
161196 manifest .set_defaults (func = _inspect_manifest )
162197 # config
163- config = inspect_subparser .add_parser ("config" , help = "Inspects a docker registry metadata." )
198+ config = subparsers .add_parser ("config" , help = "Inspects a docker registry metadata." )
164199 config .add_argument ("url" , nargs = 1 , help = "Remote repository url." )
165200 config .set_defaults (func = _inspect_config , short = False )
166201 # commands
167- commands = inspect_subparser .add_parser (
202+ commands = subparsers .add_parser (
168203 "commands" ,
169204 help = "Inspects a docker registry build commands. "
170205 "These are the same as when you check individual image layers on Docker hub." ,
171206 )
172207 commands .add_argument ("url" , nargs = 1 , help = "Remote repository url." )
173208 commands .set_defaults (func = _inspect_config , short = True )
174209 # layer
175- layer = inspect_subparser .add_parser ("layer" , help = "Inspects a docker registry layer." )
210+ layer = subparsers .add_parser ("layer" , help = "Inspects a docker registry layer." )
176211 layer .add_argument ("url" , nargs = 1 , help = "Remote repository url." )
177212 layer .add_argument (
178213 "layer_reference" ,
0 commit comments