Skip to content

Commit ec88981

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 ec88981

File tree

12 files changed

+245
-4
lines changed

12 files changed

+245
-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
@@ -183,6 +204,7 @@ pub(crate) fn rerun_for_envs(build_type: BuildType) {
183204
#[repr(u8)]
184205
#[derive(Debug, Clone, Copy)]
185206
enum BuildFlags {
207+
Repack = 0b00000000,
186208
Package = 0b00000001,
187209
Kit = 0b00000010,
188210
Variant = 0b00000100,
@@ -191,6 +213,7 @@ enum BuildFlags {
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(0));
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: 96 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,56 @@ impl VariantBuildArgs {
224223
}
225224
}
226225

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

233270
impl TargetBuildArgs {
234271
pub(crate) fn build_type(&self) -> BuildType {
235272
match self {
236273
TargetBuildArgs::Package(_) => BuildType::Package,
237274
TargetBuildArgs::Variant(_) => BuildType::Variant,
275+
TargetBuildArgs::Repack(_) => BuildType::Repack,
238276
}
239277
}
240278
}
@@ -384,6 +422,60 @@ impl DockerBuild {
384422
})
385423
}
386424

425+
/// Create a new `DockerBuild` that can repackage a variant image.
426+
pub(crate) fn repack_variant(args: RepackVariantArgs, manifest: &Manifest) -> Result<Self> {
427+
let image_layout = manifest.info().image_layout().cloned().unwrap_or_default();
428+
let ImageLayout { partition_plan, .. } = image_layout;
429+
430+
let (os_image_publish_size_gib, data_image_publish_size_gib) =
431+
image_layout.publish_image_sizes_gib();
432+
433+
Ok(Self {
434+
dockerfile: args.common.tools_dir.join("repack.Dockerfile"),
435+
context: args.common.root_dir.clone(),
436+
target: "repack".to_string(),
437+
tag: append_token(
438+
format!(
439+
"buildsys-repack-{variant}-{arch}",
440+
variant = args.variant,
441+
arch = args.common.arch
442+
),
443+
&args.common.root_dir,
444+
),
445+
root_dir: args.common.root_dir.clone(),
446+
artifacts_dir: args.common.image_arch_variant_dir,
447+
state_dir: args.common.state_dir,
448+
artifact_name: args.variant.clone(),
449+
common_build_args: CommonBuildArgs::new(
450+
&args.common.root_dir,
451+
args.common.sdk_image,
452+
args.common.arch,
453+
OutputCleanup::None,
454+
),
455+
target_build_args: TargetBuildArgs::Repack(VariantRepackArgs {
456+
data_image_publish_size_gib,
457+
image_features: manifest.info().image_features().unwrap_or_default(),
458+
image_format: match manifest.info().image_format() {
459+
Some(ImageFormat::Raw) | None => "raw",
460+
Some(ImageFormat::Qcow2) => "qcow2",
461+
Some(ImageFormat::Vmdk) => "vmdk",
462+
}
463+
.to_string(),
464+
name: args.name,
465+
os_image_publish_size_gib: os_image_publish_size_gib.to_string(),
466+
partition_plan: match partition_plan {
467+
PartitionPlan::Split => "split",
468+
PartitionPlan::Unified => "unified",
469+
}
470+
.to_string(),
471+
variant: args.variant,
472+
version_build: args.version_build,
473+
version_image: args.version_image,
474+
}),
475+
secrets_args: secrets_args()?,
476+
})
477+
}
478+
387479
pub(crate) fn build(&self) -> Result<()> {
388480
env::set_current_dir(&self.root_dir).context(error::DirectoryChangeSnafu {
389481
path: &self.root_dir,
@@ -468,6 +560,7 @@ impl DockerBuild {
468560
let mut args = match &self.target_build_args {
469561
TargetBuildArgs::Package(p) => p.build_args(),
470562
TargetBuildArgs::Variant(v) => v.build_args(),
563+
TargetBuildArgs::Repack(r) => r.build_args(),
471564
};
472565
args.build_arg("ARCH", self.common_build_args.arch.to_string());
473566
args.build_arg("GOARCH", self.common_build_args.arch.goarch());
@@ -571,6 +664,7 @@ fn create_marker_dir(
571664
BuildType::Package => "packages",
572665
BuildType::Kit => "kits",
573666
BuildType::Variant => "variants",
667+
BuildType::Repack => "repack",
574668
};
575669

576670
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: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,8 @@ impl ManifestInfo {
460460
Ok(BuildType::Kit)
461461
} else if self.build_variant().is_some() {
462462
Ok(BuildType::Variant)
463+
} else if self.repack_variant().is_some() {
464+
Ok(BuildType::Repack)
463465
} else {
464466
Err(Error(error::UnknownManifestTypeSnafu {}.build()))
465467
}
@@ -486,6 +488,13 @@ impl ManifestInfo {
486488
.as_ref()
487489
.and_then(|m| m.build_variant.as_ref())
488490
}
491+
492+
fn repack_variant(&self) -> Option<&RepackVariant> {
493+
self.package
494+
.metadata
495+
.as_ref()
496+
.and_then(|m| m.repack_variant.as_ref())
497+
}
489498
}
490499

491500
/// For the "top-level manifest", i.e. the thing that `buildsys` is building, only
@@ -504,6 +513,7 @@ fn is_manifest_type(pkg_metadata: &PackageMetadata, manifest_type: BuildType) ->
504513
BuildType::Package => metadata_table.get("build-package").is_some(),
505514
BuildType::Kit => metadata_table.get("build-kit").is_some(),
506515
BuildType::Variant => metadata_table.get("build-variant").is_some(),
516+
BuildType::Repack => metadata_table.get("repack-variant").is_some(),
507517
}
508518
}
509519

@@ -556,6 +566,7 @@ struct Metadata {
556566
build_package: Option<BuildPackage>,
557567
build_kit: Option<BuildKit>,
558568
build_variant: Option<BuildVariant>,
569+
repack_variant: Option<RepackVariant>,
559570
}
560571

561572
#[derive(Deserialize, Debug)]
@@ -606,6 +617,16 @@ pub struct BuildVariant {
606617
pub image_features: Option<HashMap<ImageFeature, bool>>,
607618
}
608619

620+
#[derive(Deserialize, Debug)]
621+
#[serde(rename_all = "kebab-case")]
622+
pub struct RepackVariant {
623+
pub image_format: Option<ImageFormat>,
624+
#[serde(default)]
625+
pub image_layout: ImageLayout,
626+
pub supported_arches: Option<HashSet<SupportedArch>>,
627+
pub image_features: Option<HashMap<ImageFeature, bool>>,
628+
}
629+
609630
#[derive(Deserialize, Debug)]
610631
#[serde(rename_all = "lowercase")]
611632
pub enum ImageFormat {

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

0 commit comments

Comments
 (0)