Skip to content

Commit

Permalink
add sdk to project schema
Browse files Browse the repository at this point in the history
Add the ability to specify the desired Bottlerocket SDK in
Twoliter.toml.
  • Loading branch information
webern committed Sep 29, 2023
1 parent 88ddea6 commit 9e1f8db
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 17 deletions.
6 changes: 3 additions & 3 deletions twoliter/src/cmd/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::docker;
use crate::project::{Project, Sdk};
use crate::project::{ImageName, Project};
use anyhow::Result;
use clap::Parser;
use log::debug;
Expand Down Expand Up @@ -44,8 +44,8 @@ impl BuildVariant {
Some(p) => Project::load(p).await?,
};
// TODO - get smart about sdk: https://github.com/bottlerocket-os/twoliter/issues/11
let sdk = Sdk::default();
let _ = docker::create_twoliter_image_if_not_exists(&sdk.uri(&self.arch)).await?;
let sdk = ImageName::default();
let _ = docker::create_twoliter_image_if_not_exists(&sdk.uri("sdk", &self.arch)).await?;
Ok(())
}
}
8 changes: 8 additions & 0 deletions twoliter/src/docker/image.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::fmt::{Display, Formatter};

/// Represents a docker image URI such as `public.ecr.aws/myregistry/myrepo:v0.1.0`. The registry is
/// optional as it is when using `docker`. That is, it will be looked for locally first, then at
/// `dockerhub.io` when the registry is absent.
Expand Down Expand Up @@ -93,6 +95,12 @@ impl ImageArchUri {
}
}

impl Display for ImageArchUri {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Display::fmt(&self.uri(), f)
}
}

#[test]
fn image_arch_uri_no_registry() {
let uri = ImageArchUri::new(None, "my-sdk", "i386", "v0.33.1");
Expand Down
5 changes: 0 additions & 5 deletions twoliter/src/docker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,3 @@ mod twoliter;
pub(crate) use self::commands::DockerBuild;
pub(crate) use self::image::{ImageArchUri, ImageUri};
pub(crate) use self::twoliter::create_twoliter_image_if_not_exists;

pub(super) const DEFAULT_REGISTRY: &str = "public.ecr.aws/bottlerocket";
pub(super) const DEFAULT_SDK_NAME: &str = "bottlerocket-sdk";
// TODO - get this from lock file: https://github.com/bottlerocket-os/twoliter/issues/11
pub(super) const DEFAULT_SDK_VERSION: &str = "v0.33.0";
92 changes: 85 additions & 7 deletions twoliter/src/project.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::docker::{ImageArchUri, DEFAULT_REGISTRY, DEFAULT_SDK_NAME, DEFAULT_SDK_VERSION};
use crate::docker::ImageArchUri;
use anyhow::{ensure, Context, Result};
use async_recursion::async_recursion;
use log::{debug, trace};
Expand All @@ -8,6 +8,10 @@ use std::fmt;
use std::path::{Path, PathBuf};
use tokio::fs;

const DEFAULT_REGISTRY: &str = "public.ecr.aws/bottlerocket";
const DEFAULT_SDK_NAME: &str = "bottlerocket";
const DEFAULT_SDK_VERSION: &str = "v0.34.1";

/// Common functionality in commands, if the user gave a path to the `Twoliter.toml` file,
/// we use it, otherwise we search for the file. Returns the `Project` and the path at which it was
/// found (this is the same as `user_path` if provided).
Expand All @@ -31,7 +35,12 @@ pub(crate) struct Project {
filepath: PathBuf,
#[serde(skip)]
project_dir: PathBuf,
pub(crate) schema_version: SchemaVersion<1>,

/// The version of this schema struct.
schema_version: SchemaVersion<1>,

/// The Bottlerocket SDK container image to use.
sdk: Option<ImageName>,
}

impl Project {
Expand Down Expand Up @@ -90,17 +99,39 @@ impl Project {
pub(crate) fn project_dir(&self) -> PathBuf {
self.project_dir.clone()
}

pub(crate) fn sdk_name(&self) -> Option<&ImageName> {
self.sdk.as_ref()
}

pub(crate) fn sdk(&self, arch: &str) -> Option<ImageArchUri> {
self.sdk_name().map(|s| s.uri("sdk", arch))
}

pub(crate) fn toolchain(&self, arch: &str) -> Option<ImageArchUri> {
self.sdk_name().map(|s| s.uri("toolchain", arch))
}
}

/// A base name for an image that can be suffixed using a naming convention. For example,
/// `registry=public.ecr.aws/bottlerocket`, `name=bottlerocket`, `version=v0.50.0` can be suffixed
/// via naming convention to produce:
/// - `registry=public.ecr.aws/bottlerocket/bottlerocket-sdk-x86_64:v0.50.0`
/// - `registry=public.ecr.aws/bottlerocket/bottlerocket-toolchain-aarch64:v0.50.0`
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub(crate) struct Sdk {
pub(crate) struct ImageName {
/// The registry, e.g. `public.ecr.aws/bottlerocket`. Optional because locally cached images may
/// not specify a registry.
pub(crate) registry: Option<String>,
/// The base name of the image that can be suffixed. For example `bottlerocket` can become
/// `bottlerocket-sdk` or `bottlerocket-toolchain`.
pub(crate) name: String,
/// The version tag, for example `v0.50.0`
pub(crate) version: String,
}

impl Default for Sdk {
impl Default for ImageName {
fn default() -> Self {
Self {
registry: Some(DEFAULT_REGISTRY.to_string()),
Expand All @@ -110,9 +141,18 @@ impl Default for Sdk {
}
}

impl Sdk {
pub(crate) fn uri<S: Into<String>>(&self, arch: S) -> ImageArchUri {
ImageArchUri::new(self.registry.clone(), &self.name, arch, &self.version)
impl ImageName {
pub(crate) fn uri<S1, S2>(&self, suffix: S1, arch: S2) -> ImageArchUri
where
S1: AsRef<str>,
S2: AsRef<str>,
{
ImageArchUri::new(
self.registry.clone(),
format!("{}-{}", self.name, suffix.as_ref()),
arch.as_ref(),
&self.version,
)
}
}

Expand Down Expand Up @@ -192,6 +232,21 @@ mod test {

// Add checks here as desired to validate deserialization.
assert_eq!(SchemaVersion::<1>::default(), deserialized.schema_version);
assert_eq!(
"example.com/my-repos",
deserialized
.sdk
.as_ref()
.unwrap()
.registry
.as_ref()
.unwrap()
);
assert_eq!(
"my-bottlerocket-sdk",
deserialized.sdk.as_ref().unwrap().name
);
assert_eq!("v1.2.3", deserialized.sdk.as_ref().unwrap().version);
}

/// Ensure that a `Twoliter.toml` cannot be serialized if the `schema_version` is incorrect.
Expand Down Expand Up @@ -222,4 +277,27 @@ mod test {
// Ensure that the file we loaded was the one we expected to load.
assert_eq!(project.filepath(), twoliter_toml_path);
}

#[test]
fn test_sdk_toolchain_uri() {
let project = Project {
filepath: Default::default(),
project_dir: Default::default(),
schema_version: Default::default(),
sdk: Some(ImageName {
registry: Some("example.com".to_string()),
name: "foo".to_string(),
version: "fakever".to_string(),
}),
};

assert_eq!(
"example.com/foo-sdk-fakearch:fakever",
project.sdk("fakearch").unwrap().to_string()
);
assert_eq!(
"example.com/foo-toolchain-fakearch:fakever",
project.toolchain("fakearch").unwrap().to_string()
);
}
}
2 changes: 1 addition & 1 deletion twoliter/src/test/data/Twoliter-1.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ project-version = "v1.0.0"
[sdk]
registry = "example.com/my-repos"
name = "my-bottlerocket-sdk"
version = "1.2.3"
version = "v1.2.3"
2 changes: 1 addition & 1 deletion twoliter/src/test/data/Twoliter-invalid-version.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ project-version = "v1.0.0"
[sdk]
registry = "example.com/my-repos"
name = "my-bottlerocket-sdk"
version = "1.2.3"
version = "v1.2.3"

0 comments on commit 9e1f8db

Please sign in to comment.