Files
harmony/ROADMAP/03-assets-crate.md

5.5 KiB

Phase 3: Complete harmony_assets, Refactor Consumers

Goal

Make harmony_assets the single way to manage downloadable binaries and images across Harmony. Eliminate k3d::DownloadableAsset duplication, implement Url::Url in OPNsense infra, remove LFS-tracked files from git.

Current State

  • harmony_assets exists with Asset, LocalCache, LocalStore, S3Store (behind feature flag). CLI with upload, download, checksum, verify commands. No tests. Zero consumers.
  • k3d/src/downloadable_asset.rs has the same functionality with full test coverage (httptest mock server, checksum verification, cache hit, 404 handling, checksum failure).
  • Url::Url variant in harmony_types/src/net.rs exists but is todo!() in OPNsense TFTP and HTTP infra layers.
  • OKD modules hardcode ./data/... paths (bootstrap_02_bootstrap.rs:84-88, ipxe.rs:73).
  • data/ directory contains ~3GB of LFS-tracked files (OKD binaries, PXE images, SCOS images).

Tasks

3.1 Port k3d tests to harmony_assets

The k3d crate has 5 well-written tests in downloadable_asset.rs. Port them to test harmony_assets::LocalStore:

// harmony_assets/tests/local_store.rs (or in src/ as unit tests)

#[tokio::test]
async fn test_fetch_downloads_and_verifies_checksum() {
    // Start httptest server serving a known file
    // Create Asset with URL pointing to mock server
    // Fetch via LocalStore
    // Assert file exists at expected cache path
    // Assert checksum matches
}

#[tokio::test]
async fn test_fetch_returns_cached_file_when_present() {
    // Pre-populate cache with correct file
    // Fetch — assert no HTTP request made (mock server not hit)
}

#[tokio::test]
async fn test_fetch_fails_on_404() { ... }

#[tokio::test]
async fn test_fetch_fails_on_checksum_mismatch() { ... }

#[tokio::test]
async fn test_fetch_with_progress_callback() {
    // Assert progress callback is called with (bytes_received, total_size)
}

Add httptest to [dev-dependencies] of harmony_assets.

3.2 Refactor k3d to use harmony_assets

Replace k3d/src/downloadable_asset.rs with calls to harmony_assets:

// k3d/src/lib.rs — in download_latest_release()
use harmony_assets::{Asset, LocalCache, LocalStore, ChecksumAlgo};

let asset = Asset::new(
    binary_url,
    checksum,
    ChecksumAlgo::SHA256,
    K3D_BIN_FILE_NAME.to_string(),
);
let cache = LocalCache::new(self.base_dir.clone());
let store = LocalStore::new();
let path = store.fetch(&asset, &cache, None).await
    .map_err(|e| format!("Failed to download k3d: {}", e))?;

Delete k3d/src/downloadable_asset.rs. Update k3d's Cargo.toml to depend on harmony_assets.

3.3 Define asset metadata as config structs

Following plan.md Phase 2, create typed config for OKD assets using harmony_config:

// harmony/src/modules/okd/config.rs
#[derive(Config, Serialize, Deserialize, JsonSchema, InteractiveParse)]
struct OkdInstallerConfig {
    pub openshift_install_url: String,
    pub openshift_install_sha256: String,
    pub scos_kernel_url: String,
    pub scos_kernel_sha256: String,
    pub scos_initramfs_url: String,
    pub scos_initramfs_sha256: String,
    pub scos_rootfs_url: String,
    pub scos_rootfs_sha256: String,
}

First run prompts for URLs/checksums (or uses compiled-in defaults). Values persist to SQLite. Can be overridden via env vars or OpenBao.

3.4 Implement Url::Url in OPNsense infra layer

In harmony/src/infra/opnsense/http.rs and tftp.rs, implement the Url::Url(url) match arm:

// Instead of SCP-ing files to OPNsense:
// SSH into OPNsense, run: fetch -o /usr/local/http/{path} {url}
// (FreeBSD-native HTTP client, no extra deps on OPNsense)

This eliminates the manual scp workaround and the inquire::Confirm prompts in ipxe.rs:126 and bootstrap_02_bootstrap.rs:230.

3.5 Refactor OKD modules to use assets + config

In bootstrap_02_bootstrap.rs:

  • openshift-install: Resolve OkdInstallerConfig from harmony_config, download via harmony_assets, invoke from cache.
  • SCOS images: Pass Url::Url(scos_kernel_url) etc. to StaticFilesHttpScore. OPNsense fetches from S3 directly.
  • Remove oc and kubectl from data/okd/bin/ (never used by code).

In ipxe.rs:

  • Replace the folder-to-serve SCP workaround with individual Url::Url entries.
  • Remove the inquire::Confirm SCP prompts.

3.6 Upload assets to S3

  • Upload all current data/ binaries to Ceph S3 bucket with path scheme: harmony-assets/okd/v{version}/openshift-install, harmony-assets/pxe/centos-stream-9/install.img, etc.
  • Set public-read ACL or configure presigned URL generation.
  • Record S3 URLs and SHA256 checksums as defaults in the config structs.

3.7 Remove LFS, clean git

  • Remove all LFS-tracked files from the repo.
  • Update .gitattributes to remove LFS filters.
  • Keep data/ in .gitignore (it becomes a local cache directory).
  • Optionally use git filter-repo or BFG to strip LFS objects from history (required before Phase 4 GitHub publish).

Deliverables

  • harmony_assets has tests ported from k3d pattern (5+ tests with httptest)
  • k3d::DownloadableAsset replaced by harmony_assets usage
  • OkdInstallerConfig struct using harmony_config
  • Url::Url implemented in OPNsense HTTP and TFTP infra
  • OKD bootstrap refactored to use lazy-download pattern
  • Assets uploaded to S3 with documented URLs/checksums
  • LFS removed, git history cleaned
  • Repo size small enough for GitHub (~code + templates only)