@@ -184,7 +184,7 @@ impl Client {
184184 self . auth ( image, auth, & RegistryOperation :: Pull ) . await ?;
185185 }
186186
187- let ( manifest, digest) = self . pull_manifest ( image) . await ?;
187+ let ( manifest, digest) = self . _pull_manifest ( image) . await ?;
188188
189189 self . validate_layers ( & manifest, accepted_media_types)
190190 . await ?;
@@ -402,11 +402,30 @@ impl Client {
402402 Ok ( ( ) )
403403 }
404404
405+ /// Pull a manifest from the remote OCI Distribution service.
406+ ///
407+ /// The client will check if it's already been authenticated and if
408+ /// not will attempt to do.
409+ ///
410+ /// A Tuple is returned containing the [OciManifest](crate::manifest::OciManifest)
411+ /// and the manifest content digest hash.
412+ pub async fn pull_manifest (
413+ & mut self ,
414+ image : & Reference ,
415+ auth : & RegistryAuth ,
416+ ) -> anyhow:: Result < ( OciManifest , String ) > {
417+ if !self . tokens . contains_key ( image. registry ( ) ) {
418+ self . auth ( image, auth, & RegistryOperation :: Pull ) . await ?;
419+ }
420+
421+ self . _pull_manifest ( image) . await
422+ }
423+
405424 /// Pull a manifest from the remote OCI Distribution service.
406425 ///
407426 /// If the connection has already gone through authentication, this will
408427 /// use the bearer token. Otherwise, this will attempt an anonymous pull.
409- async fn pull_manifest ( & self , image : & Reference ) -> anyhow:: Result < ( OciManifest , String ) > {
428+ async fn _pull_manifest ( & self , image : & Reference ) -> anyhow:: Result < ( OciManifest , String ) > {
410429 let url = self . to_v2_manifest_url ( image) ;
411430 debug ! ( "Pulling image manifest from {}" , url) ;
412431 let request = self . client . get ( & url) ;
@@ -467,6 +486,40 @@ impl Client {
467486 Ok ( ( ) )
468487 }
469488
489+ /// Pull a manifest and its config from the remote OCI Distribution service.
490+ ///
491+ /// The client will check if it's already been authenticated and if
492+ /// not will attempt to do.
493+ ///
494+ /// A Tuple is returned containing the [OciManifest](crate::manifest::OciManifest),
495+ /// the manifest content digest hash and the contents of the manifests config layer
496+ /// as a String.
497+ pub async fn pull_manifest_and_config (
498+ & mut self ,
499+ image : & Reference ,
500+ auth : & RegistryAuth ,
501+ ) -> anyhow:: Result < ( OciManifest , String , String ) > {
502+ if !self . tokens . contains_key ( image. registry ( ) ) {
503+ self . auth ( image, auth, & RegistryOperation :: Pull ) . await ?;
504+ }
505+
506+ self . _pull_manifest_and_config ( image) . await
507+ }
508+
509+ async fn _pull_manifest_and_config (
510+ & mut self ,
511+ image : & Reference ,
512+ ) -> anyhow:: Result < ( OciManifest , String , String ) > {
513+ let ( manifest, digest) = self . _pull_manifest ( image) . await ?;
514+
515+ let mut out: Vec < u8 > = Vec :: new ( ) ;
516+ debug ! ( "Pulling config layer" ) ;
517+ self . pull_layer ( image, & manifest. config . digest , & mut out)
518+ . await ?;
519+
520+ Ok ( ( manifest, digest, String :: from_utf8 ( out) ?) )
521+ }
522+
470523 /// Pull a single layer from an OCI registry.
471524 ///
472525 /// This pulls the layer for a particular image that is identified by
@@ -1189,12 +1242,12 @@ mod test {
11891242 }
11901243
11911244 #[ tokio:: test]
1192- async fn test_pull_manifest ( ) {
1245+ async fn test_pull_manifest_private ( ) {
11931246 for & image in TEST_IMAGES {
11941247 let reference = Reference :: try_from ( image) . expect ( "failed to parse reference" ) ;
11951248 // Currently, pull_manifest does not perform Authz, so this will fail.
11961249 let c = Client :: default ( ) ;
1197- c. pull_manifest ( & reference)
1250+ c. _pull_manifest ( & reference)
11981251 . await
11991252 . expect_err ( "pull manifest should fail" ) ;
12001253
@@ -1208,7 +1261,23 @@ mod test {
12081261 . await
12091262 . expect ( "authenticated" ) ;
12101263 let ( manifest, _) = c
1211- . pull_manifest ( & reference)
1264+ . _pull_manifest ( & reference)
1265+ . await
1266+ . expect ( "pull manifest should not fail" ) ;
1267+
1268+ // The test on the manifest checks all fields. This is just a brief sanity check.
1269+ assert_eq ! ( manifest. schema_version, 2 ) ;
1270+ assert ! ( !manifest. layers. is_empty( ) ) ;
1271+ }
1272+ }
1273+
1274+ #[ tokio:: test]
1275+ async fn test_pull_manifest_public ( ) {
1276+ for & image in TEST_IMAGES {
1277+ let reference = Reference :: try_from ( image) . expect ( "failed to parse reference" ) ;
1278+ let mut c = Client :: default ( ) ;
1279+ let ( manifest, _) = c
1280+ . pull_manifest ( & reference, & RegistryAuth :: Anonymous )
12121281 . await
12131282 . expect ( "pull manifest should not fail" ) ;
12141283
@@ -1218,6 +1287,23 @@ mod test {
12181287 }
12191288 }
12201289
1290+ #[ tokio:: test]
1291+ async fn pull_manifest_and_config_public ( ) {
1292+ for & image in TEST_IMAGES {
1293+ let reference = Reference :: try_from ( image) . expect ( "failed to parse reference" ) ;
1294+ let mut c = Client :: default ( ) ;
1295+ let ( manifest, _, config) = c
1296+ . pull_manifest_and_config ( & reference, & RegistryAuth :: Anonymous )
1297+ . await
1298+ . expect ( "pull manifest and config should not fail" ) ;
1299+
1300+ // The test on the manifest checks all fields. This is just a brief sanity check.
1301+ assert_eq ! ( manifest. schema_version, 2 ) ;
1302+ assert ! ( !manifest. layers. is_empty( ) ) ;
1303+ assert ! ( !config. is_empty( ) ) ;
1304+ }
1305+ }
1306+
12211307 #[ tokio:: test]
12221308 async fn test_fetch_digest ( ) {
12231309 let mut c = Client :: default ( ) ;
@@ -1264,7 +1350,7 @@ mod test {
12641350 . await
12651351 . expect ( "authenticated" ) ;
12661352 let ( manifest, _) = c
1267- . pull_manifest ( & reference)
1353+ . _pull_manifest ( & reference)
12681354 . await
12691355 . expect ( "failed to pull manifest" ) ;
12701356
@@ -1485,7 +1571,7 @@ mod test {
14851571 . expect ( "authenticated" ) ;
14861572
14871573 let ( manifest, _digest) = c
1488- . pull_manifest ( & image)
1574+ . _pull_manifest ( & image)
14891575 . await
14901576 . expect ( "failed to pull manifest" ) ;
14911577
@@ -1537,7 +1623,7 @@ mod test {
15371623 . expect ( "failed to pull pushed image" ) ;
15381624
15391625 let ( pulled_manifest, _digest) = c
1540- . pull_manifest ( & push_image)
1626+ . _pull_manifest ( & push_image)
15411627 . await
15421628 . expect ( "failed to pull pushed image manifest" ) ;
15431629
0 commit comments