k8s-openapi can compile with multiple features enabled, but it isn't clear if it makes sense to allow it.
If someone writes a crate for their own cluster, they'd just enable the single feature that matches their cluster.
If someone writes a crate that would work with an arbitrary range of versions but wants to use something available in all of them like core::v1::Pod, currently they have to import each version's Pod anyway. This won't compile if more than one feature is enabled.
I originally thought the multiple features would be enabled simultaneously because lib crates would take hard dependencies on particular versions that have what they need. For example, if a lib crate wanted apps::v1 that was introduced in 1.9, it would depend on features = ["v1_9"] and use k8s_openapi::v1_9::api::apps::v1 as apps;"). This would work but would bloat compilation time for each library that chose a different feature, and would complicate passing types between multiple libraries that depend on different versions but didn't care about the difference (eg a PodSpec from crate foo that depends on v1_9 can't be passed to crate bar that depends on v1_10).
That's why I introduced the conditional compilation macros so that lib crates would not depend on a particular version but use whatever's available. But the version-specific module imports mean the lib crates still need to have different imports for each version in the crate, or they won't compile. In fact this means that adding support for a new version is currently a semver-incompatible change, since all crates would stop compiling until they added a new k8s_if_{version}! { use k8s_openapi::v1_{version}::foo::bar; }
It seems to make more sense to:
Have a way of importing types from that version without explicitly writing the module name out.
k8s_if_le_1_8! {
compile_error!("Only Kubernetes 1.9 and above are supported");
}
k8s_if_ge_1_9! {
use k8s_openapi:: k8s_version!() ::api::apps::v1 as apps;
}
Assert that only one feature is enabled. This would prevent building docs for all the versions at the same time though, so only enforce it if #[cfg(feature(not(dox)))]
The counterpoint is that an API that has the same import between different versions isn't necessarily semver-compatible anyway.
k8s-openapi can compile with multiple features enabled, but it isn't clear if it makes sense to allow it.
If someone writes a crate for their own cluster, they'd just enable the single feature that matches their cluster.
If someone writes a crate that would work with an arbitrary range of versions but wants to use something available in all of them like
core::v1::Pod
, currently they have to import each version'sPod
anyway. This won't compile if more than one feature is enabled.If someone writes a crate that uses different things on different versions like
apps::v1beta1
vsapps::v1beta2
vsapps::v1
, they still have to import each version's corresponding thing anyway. This also won't compile if more than one feature is enabled.I originally thought the multiple features would be enabled simultaneously because lib crates would take hard dependencies on particular versions that have what they need. For example, if a lib crate wanted
apps::v1
that was introduced in 1.9, it would depend onfeatures = ["v1_9"]
anduse k8s_openapi::v1_9::api::apps::v1 as apps;
"). This would work but would bloat compilation time for each library that chose a different feature, and would complicate passing types between multiple libraries that depend on different versions but didn't care about the difference (eg aPodSpec
from crate foo that depends onv1_9
can't be passed to crate bar that depends onv1_10
).That's why I introduced the conditional compilation macros so that lib crates would not depend on a particular version but use whatever's available. But the version-specific module imports mean the lib crates still need to have different imports for each version in the crate, or they won't compile. In fact this means that adding support for a new version is currently a semver-incompatible change, since all crates would stop compiling until they added a new
k8s_if_{version}! { use k8s_openapi::v1_{version}::foo::bar; }
It seems to make more sense to:
Have a way of importing types from that version without explicitly writing the module name out.
Assert that only one feature is enabled. This would prevent building docs for all the versions at the same time though, so only enforce it if
#[cfg(feature(not(dox)))]
The counterpoint is that an API that has the same import between different versions isn't necessarily semver-compatible anyway.
For example, if there had been a point where this crate only supported v1.7 and v1.8, someone would write code against
apiextensions::CreateApiextensionsV1beta1CustomResourceDefinitionResponse
expecting it to returnOther
on success. But this would break when a new release added support for v1.9 and the user enabled thev1_9
feature since it would now returnCreated