Skip to content

Commit 17a20cb

Browse files
committed
buildsys: add repack-variant target
Add the the initial target for repackaging a Bottlerocket variant. This target will skip the traditional workflow of building packages and using `rpm2img`. Instead the build system will point to a yet to be implemented `img2img` tool. Signed-off-by: Patrick J.P. Culp <jpculp@amazon.com>
1 parent 7ac52f8 commit 17a20cb

File tree

12 files changed

+240
-4
lines changed

12 files changed

+240
-4
lines changed

docs/design/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ These will not be available and need to be added to the Bottlerocket SDK:
278278
The existing build system relies on certain binaries, scripts and static files, such as
279279

280280
- buildsys, pubsys, testsys, etc.
281-
- rpm2img, the Dockerfile, and Makefile.toml
281+
- rpm2img, the Dockerfiles, and Makefile.toml
282282

283283
These tools and files will be embedded into the Twoliter binary and installed on-the-fly when Twoliter runs.
284284
The binaries will be built and embedded using the unstable Cargo feature [bindeps].

tools/buildsys/src/args.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,15 @@ pub(crate) struct Buildsys {
4141
pub(crate) enum Command {
4242
BuildPackage(Box<BuildPackageArgs>),
4343
BuildVariant(Box<BuildVariantArgs>),
44+
RepackVariant(Box<RepackVariantArgs>),
4445
}
4546

4647
impl Command {
4748
pub(crate) fn build_type(&self) -> BuildType {
4849
match self {
4950
Command::BuildPackage(_) => BuildType::Package,
5051
Command::BuildVariant(_) => BuildType::Variant,
52+
Command::RepackVariant(_) => BuildType::Repack,
5153
}
5254
}
5355
}
@@ -160,6 +162,25 @@ pub(crate) struct BuildVariantArgs {
160162
pub(crate) common: Common,
161163
}
162164

165+
/// Repack variant from prebuilt images.
166+
#[derive(Debug, Parser)]
167+
pub(crate) struct RepackVariantArgs {
168+
#[arg(long, env = "BUILDSYS_NAME")]
169+
pub(crate) name: String,
170+
171+
#[arg(long, env = "BUILDSYS_VARIANT")]
172+
pub(crate) variant: String,
173+
174+
#[arg(long, env = "BUILDSYS_VERSION_BUILD")]
175+
pub(crate) version_build: String,
176+
177+
#[arg(long, env = "BUILDSYS_VERSION_IMAGE")]
178+
pub(crate) version_image: String,
179+
180+
#[command(flatten)]
181+
pub(crate) common: Common,
182+
}
183+
163184
/// Returns the environment variables that need to be watched for a given `[BuildType]`.
164185
fn sensitive_env_vars(build_type: BuildFlags) -> impl Iterator<Item = &'static str> {
165186
REBUILD_VARS
@@ -186,11 +207,13 @@ enum BuildFlags {
186207
Package = 0b00000001,
187208
Kit = 0b00000010,
188209
Variant = 0b00000100,
210+
Repack = 0b0001000,
189211
}
190212

191213
impl From<BuildType> for BuildFlags {
192214
fn from(value: BuildType) -> Self {
193215
match value {
216+
BuildType::Repack => BuildFlags::Repack,
194217
BuildType::Package => BuildFlags::Package,
195218
BuildType::Kit => BuildFlags::Kit,
196219
BuildType::Variant => BuildFlags::Variant,
@@ -212,11 +235,14 @@ const VARIANT: u8 = BuildFlags::Variant as u8;
212235
#[test]
213236
fn build_type_includes_test() {
214237
// true
238+
assert!(BuildFlags::Repack.includes(8));
215239
assert!(BuildFlags::Package.includes(PACKAGE | VARIANT));
216240
assert!(BuildFlags::Variant.includes(VARIANT));
217241
assert!(BuildFlags::Variant.includes(VARIANT | PACKAGE));
218242

219243
// false
244+
assert!(!BuildFlags::Repack.includes(PACKAGE));
245+
assert!(!BuildFlags::Repack.includes(VARIANT));
220246
assert!(!BuildFlags::Package.includes(VARIANT));
221247
assert!(!BuildFlags::Variant.includes(PACKAGE));
222248
assert!(!BuildFlags::Variant.includes(32));

tools/buildsys/src/builder.rs

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ the repository's top-level Dockerfile.
66
*/
77
pub(crate) mod error;
88

9-
use crate::args::{BuildPackageArgs, BuildVariantArgs};
9+
use crate::args::{BuildPackageArgs, BuildVariantArgs, RepackVariantArgs};
1010
use buildsys::manifest::{
1111
ImageFeature, ImageFormat, ImageLayout, Manifest, PartitionPlan, SupportedArch,
1212
};
@@ -86,7 +86,6 @@ lazy_static! {
8686

8787
static DOCKER_BUILD_MAX_ATTEMPTS: NonZeroU16 = nonzero!(10u16);
8888

89-
#[allow(dead_code)]
9089
enum OutputCleanup {
9190
BeforeBuild,
9291
None,
@@ -224,17 +223,60 @@ impl VariantBuildArgs {
224223
}
225224
}
226225

226+
struct VariantRepackArgs {
227+
data_image_publish_size_gib: i32,
228+
data_image_size_gib: String,
229+
image_features: HashSet<ImageFeature>,
230+
image_format: String,
231+
name: String,
232+
os_image_publish_size_gib: String,
233+
os_image_size_gib: String,
234+
partition_plan: String,
235+
variant: String,
236+
version_build: String,
237+
version_image: String,
238+
}
239+
240+
impl VariantRepackArgs {
241+
fn build_args(&self) -> Vec<String> {
242+
let mut args = Vec::new();
243+
args.push("--network".into());
244+
args.push("host".into());
245+
args.build_arg(
246+
"DATA_IMAGE_PUBLISH_SIZE_GIB",
247+
self.data_image_publish_size_gib.to_string(),
248+
);
249+
args.build_arg("DATA_IMAGE_SIZE_GIB", &self.data_image_size_gib);
250+
args.build_arg("IMAGE_FORMAT", &self.image_format);
251+
args.build_arg("IMAGE_NAME", &self.name);
252+
args.build_arg("OS_IMAGE_PUBLISH_SIZE_GIB", &self.os_image_publish_size_gib);
253+
args.build_arg("OS_IMAGE_SIZE_GIB", &self.os_image_size_gib);
254+
args.build_arg("PARTITION_PLAN", &self.partition_plan);
255+
args.build_arg("VARIANT", &self.variant);
256+
args.build_arg("BUILD_ID", &self.version_build);
257+
args.build_arg("VERSION_ID", &self.version_image);
258+
259+
for image_feature in self.image_features.iter() {
260+
args.build_arg(format!("{}", image_feature), "1");
261+
}
262+
263+
args
264+
}
265+
}
266+
227267
#[allow(clippy::large_enum_variant)]
228268
enum TargetBuildArgs {
229269
Package(PackageBuildArgs),
230270
Variant(VariantBuildArgs),
271+
Repack(VariantRepackArgs),
231272
}
232273

233274
impl TargetBuildArgs {
234275
pub(crate) fn build_type(&self) -> BuildType {
235276
match self {
236277
TargetBuildArgs::Package(_) => BuildType::Package,
237278
TargetBuildArgs::Variant(_) => BuildType::Variant,
279+
TargetBuildArgs::Repack(_) => BuildType::Repack,
238280
}
239281
}
240282
}
@@ -384,6 +426,67 @@ impl DockerBuild {
384426
})
385427
}
386428

429+
/// Create a new `DockerBuild` that can repackage a variant image.
430+
pub(crate) fn repack_variant(args: RepackVariantArgs, manifest: &Manifest) -> Result<Self> {
431+
let image_layout = manifest.info().image_layout().cloned().unwrap_or_default();
432+
let ImageLayout {
433+
os_image_size_gib,
434+
data_image_size_gib,
435+
partition_plan,
436+
..
437+
} = image_layout;
438+
439+
let (os_image_publish_size_gib, data_image_publish_size_gib) =
440+
image_layout.publish_image_sizes_gib();
441+
442+
Ok(Self {
443+
dockerfile: args.common.tools_dir.join("repack.Dockerfile"),
444+
context: args.common.root_dir.clone(),
445+
target: "repack".to_string(),
446+
tag: append_token(
447+
format!(
448+
"buildsys-repack-{variant}-{arch}",
449+
variant = args.variant,
450+
arch = args.common.arch
451+
),
452+
&args.common.root_dir,
453+
),
454+
root_dir: args.common.root_dir.clone(),
455+
artifacts_dir: args.common.image_arch_variant_dir,
456+
state_dir: args.common.state_dir,
457+
artifact_name: args.variant.clone(),
458+
common_build_args: CommonBuildArgs::new(
459+
&args.common.root_dir,
460+
args.common.sdk_image,
461+
args.common.arch,
462+
OutputCleanup::None,
463+
),
464+
target_build_args: TargetBuildArgs::Repack(VariantRepackArgs {
465+
data_image_publish_size_gib,
466+
data_image_size_gib: data_image_size_gib.to_string(),
467+
image_features: manifest.info().image_features().unwrap_or_default(),
468+
image_format: match manifest.info().image_format() {
469+
Some(ImageFormat::Raw) | None => "raw",
470+
Some(ImageFormat::Qcow2) => "qcow2",
471+
Some(ImageFormat::Vmdk) => "vmdk",
472+
}
473+
.to_string(),
474+
name: args.name,
475+
os_image_publish_size_gib: os_image_publish_size_gib.to_string(),
476+
os_image_size_gib: os_image_size_gib.to_string(),
477+
partition_plan: match partition_plan {
478+
PartitionPlan::Split => "split",
479+
PartitionPlan::Unified => "unified",
480+
}
481+
.to_string(),
482+
variant: args.variant,
483+
version_build: args.version_build,
484+
version_image: args.version_image,
485+
}),
486+
secrets_args: secrets_args()?,
487+
})
488+
}
489+
387490
pub(crate) fn build(&self) -> Result<()> {
388491
env::set_current_dir(&self.root_dir).context(error::DirectoryChangeSnafu {
389492
path: &self.root_dir,
@@ -468,6 +571,7 @@ impl DockerBuild {
468571
let mut args = match &self.target_build_args {
469572
TargetBuildArgs::Package(p) => p.build_args(),
470573
TargetBuildArgs::Variant(v) => v.build_args(),
574+
TargetBuildArgs::Repack(r) => r.build_args(),
471575
};
472576
args.build_arg("ARCH", self.common_build_args.arch.to_string());
473577
args.build_arg("GOARCH", self.common_build_args.arch.goarch());
@@ -571,6 +675,7 @@ fn create_marker_dir(
571675
BuildType::Package => "packages",
572676
BuildType::Kit => "kits",
573677
BuildType::Variant => "variants",
678+
BuildType::Repack => "variants",
574679
};
575680

576681
let path = [&state_dir.display().to_string(), arch, prefix, name]

tools/buildsys/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ pub enum BuildType {
66
Package,
77
Kit,
88
Variant,
9+
Repack,
910
}

tools/buildsys/src/main.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ mod gomod;
1515
mod project;
1616
mod spec;
1717

18-
use crate::args::{BuildPackageArgs, BuildVariantArgs, Buildsys, Command};
18+
use crate::args::{BuildPackageArgs, BuildVariantArgs, Buildsys, Command, RepackVariantArgs};
1919
use crate::builder::DockerBuild;
2020
use buildsys::manifest::{BundleModule, Manifest, ManifestInfo, SupportedArch};
2121
use cache::LookasideCache;
@@ -103,6 +103,7 @@ fn run(args: Buildsys) -> Result<()> {
103103
match args.command {
104104
Command::BuildPackage(args) => build_package(*args),
105105
Command::BuildVariant(args) => build_variant(*args),
106+
Command::RepackVariant(args) => repack_variant(*args),
106107
}
107108
}
108109

@@ -256,6 +257,23 @@ fn build_variant(args: BuildVariantArgs) -> Result<()> {
256257
.context(error::BuildAttemptSnafu)
257258
}
258259

260+
fn repack_variant(args: RepackVariantArgs) -> Result<()> {
261+
let manifest_file = "Cargo.toml";
262+
263+
let manifest = Manifest::new(
264+
args.common.cargo_manifest_dir.join(manifest_file),
265+
&args.common.cargo_metadata_path,
266+
)
267+
.context(error::ManifestParseSnafu)?;
268+
269+
supported_arch(manifest.info(), args.common.arch)?;
270+
271+
DockerBuild::repack_variant(args, &manifest)
272+
.context(error::BuilderInstantiationSnafu)?
273+
.build()
274+
.context(error::BuildAttemptSnafu)
275+
}
276+
259277
/// Ensure that the current arch is supported by the current variant
260278
fn supported_arch(manifest: &ManifestInfo, arch: SupportedArch) -> Result<()> {
261279
if let Some(supported_arches) = manifest.supported_arches() {

tools/buildsys/src/manifest.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ fn is_manifest_type(pkg_metadata: &PackageMetadata, manifest_type: BuildType) ->
504504
BuildType::Package => metadata_table.get("build-package").is_some(),
505505
BuildType::Kit => metadata_table.get("build-kit").is_some(),
506506
BuildType::Variant => metadata_table.get("build-variant").is_some(),
507+
BuildType::Repack => metadata_table.get("build-variant").is_some(),
507508
}
508509
}
509510

twoliter/build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ fn main() {
3030
paths.copy_file("build.Dockerfile");
3131
paths.copy_file("build.Dockerfile.dockerignore");
3232
paths.copy_file("docker-go");
33+
paths.copy_file("img2img");
3334
paths.copy_file("partyplanner");
35+
paths.copy_file("repack.Dockerfile");
36+
paths.copy_file("repack.Dockerfile.dockerignore");
3437
paths.copy_file("rpm2img");
3538
paths.copy_file("rpm2kmodkit");
3639
paths.copy_file("rpm2migrations");

twoliter/embedded/Makefile.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,20 @@ ln -snf "${BUILDSYS_VERSION_FULL}" "${BUILDSYS_OUTPUT_DIR}/latest"
811811
'''
812812
]
813813

814+
[tasks.repack-variant]
815+
dependencies = ["fetch-sdk", "build-sbkeys", "publish-setup"]
816+
script = [
817+
'''
818+
export PATH="${TWOLITER_TOOLS_DIR}:${PATH}"
819+
820+
# Parse the variant into its components and set additional variables.
821+
eval "$(bottlerocket-variant)"
822+
823+
buildsys repack-variant \
824+
--cargo-manifest-dir variants/${BUILDSYS_VARIANT}
825+
'''
826+
]
827+
814828
[tasks.check-licenses]
815829
dependencies = ["fetch"]
816830
script = [

twoliter/embedded/img2img

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env bash
2+
3+
echo "img2img not yet implemented" >&2 ; exit 1
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# syntax=docker/dockerfile:1.4.3
2+
#
3+
# Several commands start with RUN --mount=target=/host, which mounts the docker build
4+
# context (which in practice is the root of the Bottlerocket repository) as a read-only
5+
# filesystem at /host.
6+
ARG SDK
7+
8+
FROM ${SDK} as imgrepack
9+
10+
ARG ARCH
11+
ARG VERSION_ID
12+
ARG BUILD_ID
13+
ARG NOCACHE
14+
ARG VARIANT
15+
ARG IMAGE_NAME
16+
ARG IMAGE_FORMAT
17+
ARG OS_IMAGE_SIZE_GIB
18+
ARG DATA_IMAGE_SIZE_GIB
19+
ARG PARTITION_PLAN
20+
ARG OS_IMAGE_PUBLISH_SIZE_GIB
21+
ARG DATA_IMAGE_PUBLISH_SIZE_GIB
22+
ARG UEFI_SECURE_BOOT
23+
ENV VARIANT=${VARIANT} VERSION_ID=${VERSION_ID} BUILD_ID=${BUILD_ID}
24+
WORKDIR /root
25+
26+
USER root
27+
RUN --mount=target=/host \
28+
--mount=type=secret,id=PK.crt,target=/root/sbkeys/PK.crt \
29+
--mount=type=secret,id=KEK.crt,target=/root/sbkeys/KEK.crt \
30+
--mount=type=secret,id=db.crt,target=/root/sbkeys/db.crt \
31+
--mount=type=secret,id=vendor.crt,target=/root/sbkeys/vendor.crt \
32+
--mount=type=secret,id=shim-sign.key,target=/root/sbkeys/shim-sign.key \
33+
--mount=type=secret,id=shim-sign.crt,target=/root/sbkeys/shim-sign.crt \
34+
--mount=type=secret,id=code-sign.key,target=/root/sbkeys/code-sign.key \
35+
--mount=type=secret,id=code-sign.crt,target=/root/sbkeys/code-sign.crt \
36+
--mount=type=secret,id=config-sign.key,target=/root/sbkeys/config-sign.key \
37+
--mount=type=secret,id=kms-sign.json,target=/root/.config/aws-kms-pkcs11/config.json \
38+
--mount=type=secret,id=aws-access-key-id.env,target=/root/.aws/aws-access-key-id.env \
39+
--mount=type=secret,id=aws-secret-access-key.env,target=/root/.aws/aws-secret-access-key.env \
40+
--mount=type=secret,id=aws-session-token.env,target=/root/.aws/aws-session-token.env \
41+
/host/build/tools/img2img \
42+
--input-dir="/host/build/images/${ARCH}-${VARIANT}/${VERSION_ID}-${BUILD_ID}" \
43+
--output-dir=/local/output \
44+
--output-fmt="${IMAGE_FORMAT}" \
45+
--os-image-size-gib="${OS_IMAGE_SIZE_GIB}" \
46+
--data-image-size-gib="${DATA_IMAGE_SIZE_GIB}" \
47+
--os-image-publish-size-gib="${OS_IMAGE_PUBLISH_SIZE_GIB}" \
48+
--data-image-publish-size-gib="${DATA_IMAGE_PUBLISH_SIZE_GIB}" \
49+
--partition-plan="${PARTITION_PLAN}" \
50+
--ovf-template="/host/variants/${VARIANT}/template.ovf" \
51+
${UEFI_SECURE_BOOT:+--with-uefi-secure-boot=yes} \
52+
&& echo ${NOCACHE}
53+
54+
# =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^=
55+
# Copies the repackaged artifacts to their expected location so that buildsys can find them
56+
# and copy them out.
57+
FROM scratch AS repack
58+
COPY --from=imgrepack /local/output/. /output/

0 commit comments

Comments
 (0)