Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stabilize the current schema #744

Merged
merged 1 commit into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions docs/src/bootc-via-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,26 @@ 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
towards the [spec and status and other conventions](https://kubernetes.io/docs/reference/using-api/api-concepts/).

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
Expand Down
24 changes: 24 additions & 0 deletions docs/src/host-v0.schema.json → docs/src/host-v1.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
]
}
}
},
Expand Down Expand Up @@ -366,6 +378,18 @@
]
}
}
},
"Store": {
"description": "The container storage backend",
"oneOf": [
{
"description": "Use the ostree-container storage backend.",
"type": "string",
"enum": [
"ostreeContainer"
]
}
]
}
}
}
6 changes: 3 additions & 3 deletions lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ pub(crate) struct StatusOpts {
pub(crate) format: Option<OutputFormat>,

/// 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<u32>,

Expand Down
1 change: 1 addition & 0 deletions lib/src/fixtures/spec-v1-null.json
Original file line number Diff line number Diff line change
@@ -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}}
File renamed without changes.
File renamed without changes.
17 changes: 12 additions & 5 deletions lib/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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(),
Expand All @@ -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(),
Expand Down
3 changes: 2 additions & 1 deletion lib/src/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()? {
Expand Down
6 changes: 3 additions & 3 deletions tests/booted/readonly/001-test-status.nu
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 5 additions & 1 deletion tests/booted/readonly/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"])
Expand Down
2 changes: 1 addition & 1 deletion xtask/src/xtask.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
Expand Down