Skip to content

Commit

Permalink
Split ObjectMeta into ObjectMeta, ClusterObjectMeta and SubObjectMeta.
Browse files Browse the repository at this point in the history
Ref: #134
  • Loading branch information
Arnavion committed Feb 25, 2023
1 parent 9c2838e commit 3a3a02f
Show file tree
Hide file tree
Showing 305 changed files with 7,963 additions and 340 deletions.
59 changes: 38 additions & 21 deletions k8s-openapi-codegen-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,35 +415,35 @@ pub fn run(
("{name}", Some(url_path_segment), Some("{namespace}"), Some("namespaces")) =>
(
format!("{url_path_segment:?}"),
format!("{local}NamespaceResourceScope"),
templates::ResourceScope::Namespace { local: &local },
&mut namespace_or_cluster_scoped_url_path_segment_and_scope,
),

("{name}", Some(url_path_segment), _, _) =>
(
format!("{url_path_segment:?}"),
format!("{local}ClusterResourceScope"),
templates::ResourceScope::Cluster { local: &local },
&mut namespace_or_cluster_scoped_url_path_segment_and_scope,
),

(url_path_segment, Some("{name}"), _, _) =>
(
format!("{url_path_segment:?}"),
format!("{local}SubResourceScope"),
templates::ResourceScope::Sub { local: &local },
&mut subresource_url_path_segment_and_scope,
),

(url_path_segment, Some("{namespace}"), Some("namespaces"), _) =>
(
format!("{url_path_segment:?}"),
format!("{local}NamespaceResourceScope"),
templates::ResourceScope::Namespace { local: &local },
&mut namespace_or_cluster_scoped_url_path_segment_and_scope,
),

(url_path_segment, _, _, _) =>
(
format!("{url_path_segment:?}"),
format!("{local}ClusterResourceScope"),
templates::ResourceScope::Cluster { local: &local },
&mut namespace_or_cluster_scoped_url_path_segment_and_scope,
),
};
Expand All @@ -465,9 +465,9 @@ pub fn run(
"io.k8s.apimachinery.pkg.apis.meta.v1.APIGroupList" |
"io.k8s.apimachinery.pkg.apis.meta.v1.APIResourceList" |
"io.k8s.apimachinery.pkg.apis.meta.v1.APIVersions" =>
namespace_or_cluster_scoped_url_path_segment_and_scope.push((r#""""#.to_owned(), format!("{local}ClusterResourceScope"))),
namespace_or_cluster_scoped_url_path_segment_and_scope.push((r#""""#.to_owned(), templates::ResourceScope::Cluster { local: &local })),
"io.k8s.apimachinery.pkg.apis.meta.v1.Status" =>
subresource_url_path_segment_and_scope.push((r#""status""#.to_owned(), format!("{local}SubResourceScope"))),
subresource_url_path_segment_and_scope.push((r#""status""#.to_owned(), templates::ResourceScope::Sub { local: &local })),
_ => (),
}

Expand All @@ -478,25 +478,42 @@ pub fn run(
(
Some((api_version, group, kind, version, list_kind)),
Some((metadata_ty, templates::PropertyRequired::Required { is_default: _ })),
) => Some(templates::ResourceMetadata {
api_version,
group,
kind,
version,
list_kind: list_kind.as_deref(),
metadata_ty: Some(metadata_ty),
url_path_segment_and_scope: match (&*namespace_or_cluster_scoped_url_path_segment_and_scope, &*subresource_url_path_segment_and_scope) {
) => {
let url_path_segment_and_scope = match (&*namespace_or_cluster_scoped_url_path_segment_and_scope, &*subresource_url_path_segment_and_scope) {
([(url_path_segment, scope)], _) |
([], [(url_path_segment, scope)]) => (&**url_path_segment, &**scope),
([], [(url_path_segment, scope)]) => (&**url_path_segment, *scope),

([], []) => return Err(format!(
"definition {definition_path} is a Resource but its URL path segment and scope could not be inferred").into()),
([_, ..], _) => return Err(format!(
"definition {definition_path} is a Resource but was inferred to have multiple scopes {namespace_or_cluster_scoped_url_path_segment_and_scope:?}").into()),
([], [_, ..]) => return Err(format!(
"definition {definition_path} is a Resource but was inferred to have multiple scopes {subresource_url_path_segment_and_scope:?}").into()),
},
}),
};

let metadata_ty: std::borrow::Cow<'_, str> =
if *metadata_ty == *format!("{local}apimachinery::pkg::apis::meta::v1::ObjectMeta") {
match url_path_segment_and_scope.1 {
templates::ResourceScope::Cluster { local } => format!("{local}apimachinery::pkg::apis::meta::v1::ClusterObjectMeta").into(),
templates::ResourceScope::Inherit { ty: _ } => unreachable!(),
templates::ResourceScope::Namespace { local: _ } => (&**metadata_ty).into(),
templates::ResourceScope::Sub { local } => format!("{local}apimachinery::pkg::apis::meta::v1::SubObjectMeta").into(),
}
}
else {
(&**metadata_ty).into()
};

Some(templates::ResourceMetadata {
api_version,
group,
kind,
version,
list_kind: list_kind.as_deref(),
metadata_ty: Some(metadata_ty),
url_path_segment_and_scope,
})
},

(Some(_), Some((_, templates::PropertyRequired::Optional | templates::PropertyRequired::OptionalDefault))) =>
return Err(format!("definition {definition_path} has optional metadata").into()),
Expand All @@ -513,7 +530,7 @@ pub fn run(
metadata_ty: None,
url_path_segment_and_scope: match (&*namespace_or_cluster_scoped_url_path_segment_and_scope, &*subresource_url_path_segment_and_scope) {
([(url_path_segment, scope)], _) |
([], [(url_path_segment, scope)]) => (&**url_path_segment, &**scope),
([], [(url_path_segment, scope)]) => (&**url_path_segment, *scope),

([], []) => return Err(format!(
"definition {definition_path} is a Resource but its URL path segment and scope could not be inferred").into()),
Expand Down Expand Up @@ -692,8 +709,8 @@ pub fn run(
kind: "<T as crate::ListableResource>::LIST_KIND",
version: "<T as crate::Resource>::VERSION",
list_kind: None,
metadata_ty: Some(&metadata_rust_type),
url_path_segment_and_scope: (r#""""#, "<T as crate::Resource>::Scope"),
metadata_ty: Some(metadata_rust_type),
url_path_segment_and_scope: (r#""""#, templates::ResourceScope::Inherit { ty: "T" }),
};

templates::r#struct::generate(
Expand Down
27 changes: 23 additions & 4 deletions k8s-openapi-codegen-common/src/templates/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub(crate) struct Property<'a> {
pub(crate) is_flattened: bool,
}

#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
pub(crate) enum PropertyRequired {
Required { is_default: bool },
Optional,
Expand All @@ -57,15 +57,15 @@ pub(crate) enum PropertyRequired {
OptionalDefault,
}

#[derive(Clone, Copy)]
#[derive(Clone)]
pub(crate) struct ResourceMetadata<'a> {
pub(crate) api_version: &'a str,
pub(crate) group: &'a str,
pub(crate) kind: &'a str,
pub(crate) version: &'a str,
pub(crate) list_kind: Option<&'a str>,
pub(crate) metadata_ty: Option<&'a str>,
pub(crate) url_path_segment_and_scope: (&'a str, &'a str),
pub(crate) metadata_ty: Option<std::borrow::Cow<'a, str>>,
pub(crate) url_path_segment_and_scope: (&'a str, ResourceScope<'a>),
}

#[derive(Clone, Copy)]
Expand All @@ -74,3 +74,22 @@ pub(crate) enum DateTimeSerializationFormat {
SixDecimalDigits,
ZeroDecimalDigits,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum ResourceScope<'a> {
Cluster { local: &'a str },
Inherit { ty: &'static str },
Namespace { local: &'a str },
Sub { local: &'a str },
}

impl std::fmt::Display for ResourceScope<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ResourceScope::Cluster { local } => write!(f, "{local}ClusterResourceScope"),
ResourceScope::Inherit { ty } => write!(f, "<{ty} as crate::Resource>::Scope"),
ResourceScope::Namespace { local } => write!(f, "{local}NamespaceResourceScope"),
ResourceScope::Sub { local } => write!(f, "{local}SubResourceScope"),
}
}
}
64 changes: 64 additions & 0 deletions k8s-openapi-codegen/src/fixups/special.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1139,3 +1139,67 @@ pub(crate) fn resource_metadata_not_optional(spec: &mut crate::swagger20::Spec)
Err("never applied override to make resource metadata non-optional".into())
}
}

// The default `apimachinery::pkg::apis::meta::v1::ObjectMeta` type has a `namespace: Option<String>` field because it handles both
// namespaced resources and non-namespaced resources. But it's a pain for Rust code to have to deal with the `Option`-ality for namespaced resources,
// especially since namespaced resources are far more common than non-namespaced resources.
//
// This fixup splits the type into `ObjectMeta`, `ClusterObjectMeta` and `SubObjectMeta`.
//
// - `ObjectMeta` has a `namespace: String` field. Namespace-scoped resources will use this as their `metadata` field type.
// - `ClusterObjectMeta` has no `namespace` field. Cluster-scoped resources will use this as their `metadata` field type.
// - `SubObjectMeta` has a `namespace: Option<String>` field. Sub resources will use this as their `metadata` field type.
pub(crate) fn resource_namespace_not_optional_for_namespaced(spec: &mut crate::swagger20::Spec) -> Result<(), crate::Error> {
let default_object_meta_definition =
spec.definitions
.get_mut("io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta")
.ok_or("could not find ObjectMeta definition")?;

let crate::swagger20::SchemaKind::Properties(properties) = &mut default_object_meta_definition.kind else {
return Err("ObjectMeta does not have SchemaKind::Properties kind".into());
};

let (_, namespace_property_required) = properties.get_mut("namespace").ok_or("ObjectMeta does not have namespace property")?;
if *namespace_property_required {
return Err("ObjectMeta::namespace is already required".into());
}

*namespace_property_required = true;

let default_object_meta_definition = default_object_meta_definition.clone();

{
let mut cluster_object_meta_definition = default_object_meta_definition.clone();

let crate::swagger20::SchemaKind::Properties(properties) = &mut cluster_object_meta_definition.kind else { unreachable!(); };

properties.remove("namespace");

let default_cluster_object_meta_definition =
spec.definitions.insert(
crate::swagger20::DefinitionPath("io.k8s.apimachinery.pkg.apis.meta.v1.ClusterObjectMeta".to_owned()),
cluster_object_meta_definition);
if let Some(default_cluster_object_meta_definition) = default_cluster_object_meta_definition {
return Err(format!("spec already had definition for ClusterObjectMeta: {default_cluster_object_meta_definition:?}").into());
}
}

{
let mut sub_object_meta_definition = default_object_meta_definition;

let crate::swagger20::SchemaKind::Properties(properties) = &mut sub_object_meta_definition.kind else { unreachable!(); };

let Some((_, namespace_property_required)) = properties.get_mut("namespace") else { unreachable!(); };
*namespace_property_required = false;

let default_sub_object_meta_definition =
spec.definitions.insert(
crate::swagger20::DefinitionPath("io.k8s.apimachinery.pkg.apis.meta.v1.SubObjectMeta".to_owned()),
sub_object_meta_definition);
if let Some(default_sub_object_meta_definition) = default_sub_object_meta_definition {
return Err(format!("spec already had definition for SubObjectMeta: {default_sub_object_meta_definition:?}").into());
}
}

Ok(())
}
1 change: 1 addition & 0 deletions k8s-openapi-codegen/src/supported_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ impl SupportedVersion {
crate::fixups::special::list, // Must run after separate_watch_from_list_operations
crate::fixups::special::response_types,
crate::fixups::special::resource_metadata_not_optional,
crate::fixups::special::resource_namespace_not_optional_for_namespaced,
];

for fixup in upstream_bugs_fixups.iter().chain(special_fixups) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ impl crate::ListableResource for MutatingWebhookConfiguration {
}

impl crate::Metadata for MutatingWebhookConfiguration {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ impl crate::ListableResource for ValidatingWebhookConfiguration {
}

impl crate::Metadata for ValidatingWebhookConfiguration {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ impl crate::ListableResource for MutatingWebhookConfiguration {
}

impl crate::Metadata for MutatingWebhookConfiguration {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ impl crate::ListableResource for ValidatingWebhookConfiguration {
}

impl crate::Metadata for ValidatingWebhookConfiguration {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ impl crate::ListableResource for StorageVersion {
}

impl crate::Metadata for StorageVersion {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
2 changes: 1 addition & 1 deletion src/v1_20/api/authentication/v1/token_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl crate::Resource for TokenRequest {
}

impl crate::Metadata for TokenRequest {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::SubObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
2 changes: 1 addition & 1 deletion src/v1_20/api/authentication/v1/token_review.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl crate::Resource for TokenReview {
}

impl crate::Metadata for TokenReview {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
2 changes: 1 addition & 1 deletion src/v1_20/api/authentication/v1beta1/token_review.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl crate::Resource for TokenReview {
}

impl crate::Metadata for TokenReview {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl crate::Resource for SelfSubjectAccessReview {
}

impl crate::Metadata for SelfSubjectAccessReview {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl crate::Resource for SelfSubjectRulesReview {
}

impl crate::Metadata for SelfSubjectRulesReview {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
2 changes: 1 addition & 1 deletion src/v1_20/api/authorization/v1/subject_access_review.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl crate::Resource for SubjectAccessReview {
}

impl crate::Metadata for SubjectAccessReview {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl crate::Resource for SelfSubjectAccessReview {
}

impl crate::Metadata for SelfSubjectAccessReview {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl crate::Resource for SelfSubjectRulesReview {
}

impl crate::Metadata for SelfSubjectRulesReview {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl crate::Resource for SubjectAccessReview {
}

impl crate::Metadata for SubjectAccessReview {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
2 changes: 1 addition & 1 deletion src/v1_20/api/autoscaling/v1/scale.rs
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ impl crate::Resource for Scale {
}

impl crate::Metadata for Scale {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::SubObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ impl crate::ListableResource for CertificateSigningRequest {
}

impl crate::Metadata for CertificateSigningRequest {
type Ty = crate::apimachinery::pkg::apis::meta::v1::ObjectMeta;
type Ty = crate::apimachinery::pkg::apis::meta::v1::ClusterObjectMeta;

fn metadata(&self) -> &<Self as crate::Metadata>::Ty {
&self.metadata
Expand Down
Loading

0 comments on commit 3a3a02f

Please sign in to comment.