142 lines
5.5 KiB
Markdown
142 lines
5.5 KiB
Markdown
# 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`:
|
|
|
|
```rust
|
|
// 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`:
|
|
|
|
```rust
|
|
// 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`:
|
|
|
|
```rust
|
|
// 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:
|
|
|
|
```rust
|
|
// 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)
|