import yaml
import requests
import tempfile
import subprocess
def pascal_to_snake(s):
return "".join(["_" + c.lower() if c.isupper() else c for c in s]).lstrip("_")
rust_lib = """//! Kubernetes CRDs for the Gateway API
//!
//! This library provides automatically generated types for the [Kubernetes Gateway API CRDs]. It is
//! intended to be used with the [Kube-rs] library.
//!
//! [Kubernetes Gateway API CRDs]: https://github.com/kubernetes-sigs/gateway-api/tree/main/config/crd/standard
//! [Kube-rs]: https://kube.rs/
"""
crds = []
crd_sources = [
"https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.0.0/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml",
"https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.0.0/config/crd/standard/gateway.networking.k8s.io_gateways.yaml",
"https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.0.0/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml",
"https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.0.0/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml",
]
not_defaulted = [
"GatewayClassStatusConditions",
"GatewayStatusConditions",
"HTTPRouteRulesBackendRefsFiltersUrlRewritePath",
"HTTPRouteRulesFilters",
"HTTPRouteRulesBackendRefsFiltersRequestRedirectPath",
"GatewayStatusListenersConditions",
"HTTPRouteRulesFiltersRequestRedirectPath",
"HTTPRouteRulesBackendRefsFilters",
"HTTPRouteRulesFiltersUrlRewritePath",
"HTTPRouteStatusParentsConditions",
]
for source in crd_sources:
crds.append(yaml.safe_load(requests.get(source).text))
for crd in crds:
file_name = crd["metadata"]["name"].removesuffix(".gateway.networking.k8s.io")
rust_code = ""
with tempfile.NamedTemporaryFile(mode="w") as f:
yaml.dump(crd, f)
tmp_file = f.name
rust_code = subprocess.run(
["kopium", "-f", tmp_file, "--schema=derived", "--docs", "-b"],
capture_output=True,
)
if rust_code.returncode != 0:
print(rust_code.stderr.decode("utf-8"))
exit(1)
rust_code = rust_code.stdout.decode("utf-8")
rust_code = rust_code.replace(
f"// kopium command: kopium -f {tmp_file} --schema=derived --docs -b",
f"// kopium command: kopium -f {file_name}.yml --schema=derived --docs -b",
)
rust_code = "\n".join(
[
line.replace("#[builder(", '#[cfg_attr(feature = "builder", builder(')
.strip()
.removesuffix("]")
+ ")]"
if "#[builder(" in line
else line
for line in rust_code.split("\n")
]
)
rust_code = (
rust_code.replace(
", TypedBuilder, JsonSchema)]\npub struct",
", PartialEq, Default, TypedBuilder, JsonSchema)]\npub struct",
)
.replace(
", TypedBuilder, JsonSchema)]\n#[kube",
", PartialEq, Default, TypedBuilder, JsonSchema)]\n#[kube",
)
.replace(
", TypedBuilder, JsonSchema)]\npub enum",
", PartialEq, TypedBuilder, JsonSchema)]\npub enum",
)
)
for not_defaulted_field in not_defaulted:
rust_code = rust_code.replace(
f"Default, TypedBuilder, JsonSchema)]\npub struct {not_defaulted_field}",
f"TypedBuilder, JsonSchema)]\npub struct {not_defaulted_field}",
)
rust_code = "\n".join(
[
line.replace(
", TypedBuilder, JsonSchema)]",
')]\n#[cfg_attr(feature = "builder", derive(TypedBuilder))]\n#[cfg_attr(feature = "schemars", derive(JsonSchema))]\n#[cfg_attr(not(feature = "schemars"), kube(schema="disabled"))]',
)
if line.startswith("#[derive(") and "CustomResource" in line
else line.replace(
", TypedBuilder, JsonSchema)]",
')]\n#[cfg_attr(feature = "builder", derive(TypedBuilder))]\n#[cfg_attr(feature = "schemars", derive(JsonSchema))]',
)
if line.startswith("#[derive(")
else line
for line in rust_code.split("\n")
]
)
rust_code = (
rust_code.replace(
"use typed_builder::TypedBuilder;",
'#[cfg(feature = "builder")]\nuse typed_builder::TypedBuilder;',
)
.replace(
"use schemars::JsonSchema;",
'#[cfg(feature = "schemars")]\nuse schemars::JsonSchema;',
)
.replace("use kube::CustomResource;", "use kube_derive::CustomResource;")
.replace(
'#[cfg_attr(feature = "builder", derive(TypedBuilder))]\n#[cfg_attr(feature = "schemars", derive(JsonSchema))]\npub enum',
'#[cfg_attr(feature = "schemars", derive(JsonSchema))]\npub enum',
)
)
rust_file = f"./src/{file_name}.rs"
with open(rust_file, "w") as f:
f.write(rust_code)
subprocess.run(["rustfmt", rust_file])
rust_lib += f"pub mod {file_name};\npub use {file_name}::*;\n"
with open("./src/lib.rs", "w") as f:
f.write(rust_lib)