diff --git a/docs/src/bootc-via-api.md b/docs/src/bootc-via-api.md index b5fe2d40c..fdfdf7939 100644 --- a/docs/src/bootc-via-api.md +++ b/docs/src/bootc-via-api.md @@ -4,7 +4,7 @@ At the current time, bootc is primarily intended to be driven via a fork/exec model. The core CLI verbs are stable and will not change. -## Using `bootc edit` and `bootc status --json --format-version=0` +## Using `bootc edit` and `bootc status --json` While bootc does not depend on Kubernetes, it does currently also offere a Kubernetes *style* API, especially oriented @@ -12,17 +12,18 @@ towards the [spec and status and other conventions](https://kubernetes.io/docs/r In general, most use cases of driving bootc via API are probably most easily done by forking off `bootc upgrade` when desired, -and viewing `bootc status --json --format-version=0`. +and viewing `bootc status --json --format-version=1`. ## JSON Schema -The current API is classified as `org.containers.bootc/v1alpha1` but -it will likely be officially stabilized mostly as is. However, -you should still request the current "v0" format via an explicit -`--format-version=0` as referenced above. +The current API `org.containers.bootc/v1` is stable. +In order to support the future introduction of a v2 +or newer format, please change your code now to explicitly +request `--format-version=1` as referenced above. (Available +since bootc 0.1.15, `--format-version=0` in bootc 0.1.14). There is a [JSON schema](https://json-schema.org/) generated from -the Rust source code available here: [host-v0.schema.json](host-v0.schema.json). +the Rust source code available here: [host-v1.schema.json](host-v1.schema.json). A common way to use this is to run a code generator such as [go-jsonschema](https://github.com/omissis/go-jsonschema) on the diff --git a/docs/src/host-v0.schema.json b/docs/src/host-v1.schema.json similarity index 94% rename from docs/src/host-v0.schema.json rename to docs/src/host-v1.schema.json index ab4e70e98..85ec800ca 100644 --- a/docs/src/host-v0.schema.json +++ b/docs/src/host-v1.schema.json @@ -99,6 +99,18 @@ "pinned": { "description": "Whether this entry will be subject to garbage collection", "type": "boolean" + }, + "store": { + "description": "The container storage backend", + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/Store" + }, + { + "type": "null" + } + ] } } }, @@ -366,6 +378,18 @@ ] } } + }, + "Store": { + "description": "The container storage backend", + "oneOf": [ + { + "description": "Use the ostree-container storage backend.", + "type": "string", + "enum": [ + "ostreeContainer" + ] + } + ] } } } \ No newline at end of file diff --git a/lib/src/cli.rs b/lib/src/cli.rs index 1bde26ed9..4732c9051 100644 --- a/lib/src/cli.rs +++ b/lib/src/cli.rs @@ -132,9 +132,9 @@ pub(crate) struct StatusOpts { pub(crate) format: Option, /// The desired format version. There is currently one supported - /// version, which is version `0`. Pass this option to explicitly - /// request it; it is possible that multiple versions will be - /// supported in the future. + /// version, which is exposed as both `0` and `1`. Pass this + /// option to explicitly request it; it is possible that another future + /// version 2 or newer will be supported in the future. #[clap(long)] pub(crate) format_version: Option, diff --git a/lib/src/fixtures/spec-v1-null.json b/lib/src/fixtures/spec-v1-null.json new file mode 100644 index 000000000..afd801a9e --- /dev/null +++ b/lib/src/fixtures/spec-v1-null.json @@ -0,0 +1 @@ +{"apiVersion":"org.containers.bootc/v1","kind":"BootcHost","metadata":{"name":"host"},"spec":{"image":null,"bootOrder":"default"},"status":{"staged":null,"booted":null,"rollback":null,"rollbackQueued":false,"type":null}} \ No newline at end of file diff --git a/lib/src/fixtures/spec.yaml b/lib/src/fixtures/spec-v1a1-orig.yaml similarity index 100% rename from lib/src/fixtures/spec.yaml rename to lib/src/fixtures/spec-v1a1-orig.yaml diff --git a/lib/src/fixtures/spec-v1.yaml b/lib/src/fixtures/spec-v1a1.yaml similarity index 100% rename from lib/src/fixtures/spec-v1.yaml rename to lib/src/fixtures/spec-v1a1.yaml diff --git a/lib/src/spec.rs b/lib/src/spec.rs index 415a5ebf8..5a5dd0b1e 100644 --- a/lib/src/spec.rs +++ b/lib/src/spec.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use crate::k8sapitypes; -const API_VERSION: &str = "org.containers.bootc/v1alpha1"; +const API_VERSION: &str = "org.containers.bootc/v1"; const KIND: &str = "BootcHost"; /// The default object name we use; there's only one. pub(crate) const OBJECT_NAME: &str = "host"; @@ -226,8 +226,15 @@ mod tests { use super::*; #[test] - fn test_parse_spec_v0() { - const SPEC_FIXTURE: &str = include_str!("fixtures/spec.yaml"); + fn test_parse_spec_v1_null() { + const SPEC_FIXTURE: &str = include_str!("fixtures/spec-v1-null.json"); + let host: Host = serde_json::from_str(SPEC_FIXTURE).unwrap(); + assert_eq!(host.resource.api_version, "org.containers.bootc/v1"); + } + + #[test] + fn test_parse_spec_v1a1_orig() { + const SPEC_FIXTURE: &str = include_str!("fixtures/spec-v1a1-orig.yaml"); let host: Host = serde_yaml::from_str(SPEC_FIXTURE).unwrap(); assert_eq!( host.spec.image.as_ref().unwrap().image.as_str(), @@ -236,8 +243,8 @@ mod tests { } #[test] - fn test_parse_spec_v1() { - const SPEC_FIXTURE: &str = include_str!("fixtures/spec-v1.yaml"); + fn test_parse_spec_v1a1() { + const SPEC_FIXTURE: &str = include_str!("fixtures/spec-v1a1.yaml"); let host: Host = serde_yaml::from_str(SPEC_FIXTURE).unwrap(); assert_eq!( host.spec.image.as_ref().unwrap().image.as_str(), diff --git a/lib/src/status.rs b/lib/src/status.rs index 8f9a6999b..34377e8e4 100644 --- a/lib/src/status.rs +++ b/lib/src/status.rs @@ -285,7 +285,8 @@ pub(crate) fn get_status( #[context("Status")] pub(crate) async fn status(opts: super::cli::StatusOpts) -> Result<()> { match opts.format_version.unwrap_or_default() { - 0 => {} + // For historical reasons, both 0 and 1 mean "v1". + 0 | 1 => {} o => anyhow::bail!("Unsupported format version: {o}"), }; let host = if !Utf8Path::new("/run/ostree-booted").try_exists()? { diff --git a/tests/booted/readonly/001-test-status.nu b/tests/booted/readonly/001-test-status.nu index 3afe17fd6..fab4ce13b 100644 --- a/tests/booted/readonly/001-test-status.nu +++ b/tests/booted/readonly/001-test-status.nu @@ -4,9 +4,9 @@ use tap.nu tap begin "verify bootc status output formats" let st = bootc status --json | from json -assert equal $st.apiVersion org.containers.bootc/v1alpha1 +assert equal $st.apiVersion org.containers.bootc/v1 let st = bootc status --json --format-version=0 | from json -assert equal $st.apiVersion org.containers.bootc/v1alpha1 +assert equal $st.apiVersion org.containers.bootc/v1 let st = bootc status --format=yaml | from yaml -assert equal $st.apiVersion org.containers.bootc/v1alpha1 +assert equal $st.apiVersion org.containers.bootc/v1 tap ok diff --git a/tests/booted/readonly/basic.py b/tests/booted/readonly/basic.py index 18524eb8f..985e9b472 100644 --- a/tests/booted/readonly/basic.py +++ b/tests/booted/readonly/basic.py @@ -9,7 +9,11 @@ def run(*args): def test_bootc_status(): o = subprocess.check_output(["bootc", "status", "--json"]) st = json.loads(o) - assert st['apiVersion'] == 'org.containers.bootc/v1alpha1' + assert st['apiVersion'] == 'org.containers.bootc/v1' + for v in [0, 1]: + o = subprocess.check_output(["bootc", "status", "--json", f"--format-version={v}"]) + st = json.loads(o) + assert st['apiVersion'] == 'org.containers.bootc/v1' def test_bootc_status_invalid_version(): o = subprocess.call(["bootc", "status", "--json", "--format-version=42"]) diff --git a/xtask/src/xtask.rs b/xtask/src/xtask.rs index ab4c58e0c..f53db37bd 100644 --- a/xtask/src/xtask.rs +++ b/xtask/src/xtask.rs @@ -140,7 +140,7 @@ fn update_generated(sh: &Shell) -> Result<()> { .run()?; } let schema = cmd!(sh, "cargo run -q -- internals print-json-schema").read()?; - let target = "docs/src/host-v0.schema.json"; + let target = "docs/src/host-v1.schema.json"; std::fs::write(target, &schema)?; println!("Updated {target}"); Ok(())