Skip to content

Commit a8271b0

Browse files
committed
HOLY GUACAMOLE
Signed-off-by: itowlson <[email protected]>
1 parent 5df40b7 commit a8271b0

File tree

1 file changed

+39
-31
lines changed

1 file changed

+39
-31
lines changed

crates/environments/src/environment_definition.rs

+39-31
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use futures::future::try_join_all;
55
use spin_common::ui::quoted_path;
66
use spin_manifest::schema::v2::TargetEnvironmentRef2;
77

8-
const DEFAULT_REGISTRY: &str = "spinframework.dev";
8+
const DEFAULT_ENV_DEF_REGISTRY: &str = "ghcr.io/itowlson/envs";
9+
const DEFAULT_PACKAGE_REGISTRY: &str = "spinframework.dev";
910

1011
/// Serialisation format for the lockfile: registry -> env|pkg -> { name -> digest }
1112
#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
@@ -126,7 +127,7 @@ async fn load_environment(
126127
) -> anyhow::Result<TargetEnvironment2> {
127128
match env_id {
128129
TargetEnvironmentRef2::DefaultRegistry(id) => {
129-
load_environment_from_registry(DEFAULT_REGISTRY, id, cache, lockfile).await
130+
load_environment_from_registry(DEFAULT_ENV_DEF_REGISTRY, id, cache, lockfile).await
130131
}
131132
TargetEnvironmentRef2::Registry { registry, id } => {
132133
load_environment_from_registry(registry, id, cache, lockfile).await
@@ -165,7 +166,34 @@ async fn load_env_def_toml_from_registry(
165166
}
166167

167168
async fn download_env_def_file(registry: &str, env_id: &str) -> anyhow::Result<(Vec<u8>, String)> {
168-
todo!()
169+
// This implies env_id is in the format spin-up:3.2 which WHO KNOWS
170+
let reference = format!("{registry}/{env_id}");
171+
let reference = oci_distribution::Reference::try_from(reference)?;
172+
173+
let config = oci_distribution::client::ClientConfig::default();
174+
let client = oci_distribution::client::Client::new(config);
175+
let auth = oci_distribution::secrets::RegistryAuth::Anonymous;
176+
177+
let (manifest, digest) = client.pull_manifest(&reference, &auth).await?;
178+
179+
let im = match manifest {
180+
oci_distribution::manifest::OciManifest::Image(im) => im,
181+
oci_distribution::manifest::OciManifest::ImageIndex(_ind) => {
182+
anyhow::bail!("found image index instead of image manifest, get in the sea")
183+
}
184+
};
185+
186+
let count = im.layers.len();
187+
188+
if count != 1 {
189+
anyhow::bail!("artifact {reference} should have had exactly one layer");
190+
}
191+
192+
let the_layer = &im.layers[0];
193+
let mut out = Vec::with_capacity(the_layer.size.try_into().unwrap_or_default());
194+
client.pull_blob(&reference, the_layer, &mut out).await?;
195+
196+
Ok((out, digest))
169197
}
170198

171199
/// Loads the given `TargetEnvironment` from the given registry, or
@@ -253,7 +281,7 @@ async fn load_world(
253281
) -> anyhow::Result<CompatibleWorld> {
254282
match world_ref {
255283
WorldRef::DefaultRegistry(world) => {
256-
load_world_from_registry(DEFAULT_REGISTRY, world, cache, lockfile).await
284+
load_world_from_registry(DEFAULT_PACKAGE_REGISTRY, world, cache, lockfile).await
257285
}
258286
WorldRef::Registry { registry, world } => {
259287
load_world_from_registry(registry, world, cache, lockfile).await
@@ -282,7 +310,7 @@ async fn load_environment_from_toml(
282310
cache: &spin_loader::cache::Cache,
283311
lockfile: &std::sync::Arc<tokio::sync::RwLock<TargetEnvironmentLockfile>>,
284312
) -> anyhow::Result<TargetEnvironment2> {
285-
let env: EnvironmentDefinition = toml::from_str(&toml_text)?;
313+
let env: EnvironmentDefinition = toml::from_str(toml_text)?;
286314

287315
let mut trigger_worlds = HashMap::new();
288316

@@ -416,7 +444,7 @@ async fn load_world_from_registry(
416444
let version = world_name.package.version.as_ref().unwrap(); // TODO: surely we can cope with unversioned? surely?
417445

418446
let release = client
419-
.get_release(&package, &version)
447+
.get_release(&package, version)
420448
.await
421449
.with_context(|| format!("Failed to get {} release from registry", world_name.package))?;
422450
let stm = client
@@ -436,36 +464,16 @@ async fn load_world_from_registry(
436464
.await
437465
.set_package_digest(registry, &world_name.package, &digest);
438466

439-
CompatibleWorld::from_package_bytes(&world_name, bytes)
467+
CompatibleWorld::from_package_bytes(world_name, bytes)
440468
}
441469

442-
/// A parsed document representing a deployment environment, e.g. Spin 2.7,
470+
/// A fully realised deployment environment, e.g. Spin 2.7,
443471
/// SpinKube 3.1, Fermyon Cloud. The `TargetEnvironment` provides a mapping
444472
/// from the Spin trigger types supported in the environment to the Component Model worlds
445473
/// supported by that trigger type. (A trigger type may support more than one world,
446474
/// for example when it supports multiple versions of the Spin or WASI interfaces.)
447-
///
448-
/// In terms of implementation, internally the environment is represented by a
449-
/// WIT package that adheres to a specific naming convention - namely that the worlds for
450-
/// a given trigger type are exactly whose names begin with one of:
451-
///
452-
/// * `trigger-xxx`
453-
/// * `xxx-trigger`
454-
/// * `spin-xxx` (a convention used by some plugins)
455-
///
456-
/// where `xxx` is the Spin trigger type. This flexibility is intended to maximise
457-
/// reuse of existing WIT files rather than needing to create custom ones to
458-
/// define environments.
459-
// pub struct TargetEnvironment {
460-
// name: String,
461-
// decoded: wit_parser::decoding::DecodedWasm,
462-
// package: wit_parser::Package,
463-
// package_id: id_arena::Id<wit_parser::Package>,
464-
// package_bytes: Vec<u8>,
465-
// }
466-
467-
// The realised format
468-
475+
/// The structure stores all worlds (that is, the packages containing them) as binaries:
476+
/// no further download or resolution is required after this point.
469477
pub struct TargetEnvironment2 {
470478
name: String,
471479
trigger_worlds: HashMap<String, CompatibleWorlds>,
@@ -525,7 +533,7 @@ impl<'a> IntoIterator for &'a CompatibleWorlds {
525533
}
526534
}
527535

528-
const NO_COMPATIBLE_WORLDS: &'static CompatibleWorlds = &CompatibleWorlds { worlds: vec![] };
536+
const NO_COMPATIBLE_WORLDS: &CompatibleWorlds = &CompatibleWorlds { worlds: vec![] };
529537

530538
pub struct CompatibleWorld {
531539
world: WorldName,

0 commit comments

Comments
 (0)