@@ -28,13 +28,24 @@ struct GetBlobOpts {
28
28
size : u64 ,
29
29
}
30
30
31
+ #[ derive( clap:: Parser , Debug ) ]
32
+ struct FetchContainerToDevNullOpts {
33
+ #[ clap( flatten) ]
34
+ metaopts : GetMetadataOpts ,
35
+
36
+ /// Use the "raw" path for fetching blobs
37
+ #[ clap( long) ]
38
+ raw_blobs : bool ,
39
+ }
40
+
31
41
/// Simple program to greet a person
32
42
#[ derive( clap:: Parser , Debug ) ]
33
43
#[ command( version, about, long_about = None ) ]
34
44
enum Opt {
35
45
GetMetadata ( GetMetadataOpts ) ,
36
46
GetBlob ( GetBlobOpts ) ,
37
- FetchContainerToDevNull ( GetMetadataOpts ) ,
47
+ GetBlobRaw ( GetBlobOpts ) ,
48
+ FetchContainerToDevNull ( FetchContainerToDevNullOpts ) ,
38
49
}
39
50
40
51
#[ derive( serde:: Serialize , Debug ) ]
@@ -86,18 +97,49 @@ async fn get_blob(o: GetBlobOpts) -> Result<()> {
86
97
Ok ( ( ) )
87
98
}
88
99
89
- async fn fetch_container_to_devnull ( o : GetMetadataOpts ) -> Result < ( ) > {
90
- let config = o. proxy_opts ( ) ;
100
+ async fn get_blob_raw ( o : GetBlobOpts ) -> Result < ( ) > {
101
+ let proxy = containers_image_proxy:: ImageProxy :: new ( ) . await ?;
102
+ let img = proxy. open_image ( & o. reference ) . await ?;
103
+ let ( _, mut datafd, err) = proxy. get_raw_blob ( & img, & o. digest ) . await ?;
104
+
105
+ let mut stdout = std:: io:: stdout ( ) . lock ( ) ;
106
+ let reader = async move {
107
+ let mut buffer = [ 0u8 ; 8192 ] ;
108
+ loop {
109
+ let n = datafd. read ( & mut buffer) . await ?;
110
+ if n == 0 {
111
+ return anyhow:: Ok ( ( ) ) ;
112
+ }
113
+ stdout. write_all ( & buffer[ ..n] ) ?;
114
+ }
115
+ } ;
116
+
117
+ let ( a, b) = tokio:: join!( reader, err) ;
118
+ a?;
119
+ b?;
120
+ Ok ( ( ) )
121
+ }
122
+
123
+ async fn fetch_container_to_devnull ( o : FetchContainerToDevNullOpts ) -> Result < ( ) > {
124
+ let config = o. metaopts . proxy_opts ( ) ;
91
125
let proxy = containers_image_proxy:: ImageProxy :: new_with_config ( config) . await ?;
92
- let img = & proxy. open_image ( & o. reference ) . await ?;
126
+ let img = & proxy. open_image ( & o. metaopts . reference ) . await ?;
93
127
let manifest = proxy. fetch_manifest ( img) . await ?. 1 ;
94
128
for layer in manifest. layers ( ) {
95
- let ( mut blob, driver) = proxy. get_descriptor ( img, layer) . await ?;
96
129
let mut devnull = tokio:: io:: sink ( ) ;
97
- let copier = tokio:: io:: copy ( & mut blob, & mut devnull) ;
98
- let ( copier, driver) = tokio:: join!( copier, driver) ;
99
- copier?;
100
- driver?;
130
+ if o. raw_blobs {
131
+ let ( _, mut blob, err) = proxy. get_raw_blob ( img, layer. digest ( ) ) . await ?;
132
+ let copier = tokio:: io:: copy ( & mut blob, & mut devnull) ;
133
+ let ( copier, err) = tokio:: join!( copier, err) ;
134
+ copier?;
135
+ err?;
136
+ } else {
137
+ let ( mut blob, driver) = proxy. get_descriptor ( img, layer) . await ?;
138
+ let copier = tokio:: io:: copy ( & mut blob, & mut devnull) ;
139
+ let ( copier, driver) = tokio:: join!( copier, driver) ;
140
+ copier?;
141
+ driver?;
142
+ }
101
143
}
102
144
Ok ( ( ) )
103
145
}
@@ -106,6 +148,7 @@ async fn run() -> Result<()> {
106
148
match Opt :: parse ( ) {
107
149
Opt :: GetMetadata ( o) => get_metadata ( o) . await ,
108
150
Opt :: GetBlob ( o) => get_blob ( o) . await ,
151
+ Opt :: GetBlobRaw ( o) => get_blob_raw ( o) . await ,
109
152
Opt :: FetchContainerToDevNull ( o) => fetch_container_to_devnull ( o) . await ,
110
153
}
111
154
}
0 commit comments