1
+ //! # Implementation of "logically bound" container images
2
+ //!
3
+ //! This module implements the design in <https://github.com/containers/bootc/issues/128>
4
+ //! for "logically bound" container images. These container images are
5
+ //! pre-pulled (and in the future, pinned) before a new image root
6
+ //! is considered ready.
7
+
1
8
use crate :: task:: Task ;
2
9
use anyhow:: { Context , Result } ;
3
10
use camino:: Utf8Path ;
@@ -6,18 +13,14 @@ use cap_std_ext::dirext::CapStdExtDirExt;
6
13
use fn_error_context:: context;
7
14
use ostree_ext:: ostree:: Deployment ;
8
15
use ostree_ext:: sysroot:: SysrootLock ;
9
- use rustix:: fd:: BorrowedFd ;
10
16
17
+ /// The path in a root for bound images; this directory should only contain
18
+ /// symbolic links to `.container` or `.image` files.
11
19
const BOUND_IMAGE_DIR : & str = "usr/lib/bootc-experimental/bound-images.d" ;
12
20
13
- // Access the file descriptor for a sysroot
14
- #[ allow( unsafe_code) ]
15
- pub ( crate ) fn sysroot_fd ( sysroot : & ostree_ext:: ostree:: Sysroot ) -> BorrowedFd {
16
- unsafe { BorrowedFd :: borrow_raw ( sysroot. fd ( ) ) }
17
- }
18
-
21
+ /// Given a deployment, pull all container images it references.
19
22
pub ( crate ) fn pull_bound_images ( sysroot : & SysrootLock , deployment : & Deployment ) -> Result < ( ) > {
20
- let sysroot_fd = sysroot_fd ( & sysroot) ;
23
+ let sysroot_fd = crate :: utils :: sysroot_fd ( & sysroot) ;
21
24
let sysroot_fd = Dir :: reopen_dir ( & sysroot_fd) ?;
22
25
let deployment_root_path = sysroot. deployment_dirpath ( & deployment) ;
23
26
let deployment_root = & sysroot_fd. open_dir ( & deployment_root_path) ?;
@@ -31,6 +34,7 @@ pub(crate) fn pull_bound_images(sysroot: &SysrootLock, deployment: &Deployment)
31
34
#[ context( "parse bound image spec dir" ) ]
32
35
fn parse_spec_dir ( root : & Dir , spec_dir : & str ) -> Result < Vec < BoundImage > > {
33
36
let Some ( bound_images_dir) = root. open_dir_optional ( spec_dir) ? else {
37
+ tracing:: debug!( "Missing {spec_dir}" ) ;
34
38
return Ok ( Default :: default ( ) ) ;
35
39
} ;
36
40
// And open a view of the dir that uses RESOLVE_IN_ROOT so we
@@ -104,6 +108,7 @@ fn parse_container_file(file_contents: &tini::Ini) -> Result<BoundImage> {
104
108
105
109
#[ context( "pull bound images" ) ]
106
110
fn pull_images ( _deployment_root : & Dir , bound_images : Vec < BoundImage > ) -> Result < ( ) > {
111
+ tracing:: debug!( "Pulling bound images: {}" , bound_images. len( ) ) ;
107
112
//TODO: do this in parallel
108
113
for bound_image in bound_images {
109
114
let mut task = Task :: new ( "Pulling bound image" , "/usr/bin/podman" )
@@ -118,6 +123,11 @@ fn pull_images(_deployment_root: &Dir, bound_images: Vec<BoundImage>) -> Result<
118
123
Ok ( ( ) )
119
124
}
120
125
126
+ /// A subset of data parsed from a `.image` or `.container` file with
127
+ /// the minimal information necessary to fetch the image.
128
+ ///
129
+ /// In the future this may be extended to include e.g. certificates or
130
+ /// other pull options.
121
131
#[ derive( PartialEq , Eq ) ]
122
132
struct BoundImage {
123
133
image : String ,
@@ -138,6 +148,10 @@ impl BoundImage {
138
148
}
139
149
}
140
150
151
+ /// Given a string, parse it in a way similar to how systemd would do it.
152
+ /// The primary thing here is that we reject any "specifiers" such as `%a`
153
+ /// etc. We do allow a quoted `%%` to appear in the string, which will
154
+ /// result in a single unquoted `%`.
141
155
fn parse_spec_value ( value : & str ) -> Result < String > {
142
156
let mut it = value. chars ( ) ;
143
157
let mut ret = String :: new ( ) ;
0 commit comments