use serde_json::Value;
const K8S_DEPLOYMENT: &str = r#"
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["apiVersion", "kind", "metadata", "spec"],
"properties": {
"apiVersion": { "type": "string", "const": "apps/v1" },
"kind": { "type": "string", "const": "Deployment" },
"metadata": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"namespace": { "type": "string" },
"labels": { "type": "object", "additionalProperties": { "type": "string" } },
"annotations": { "type": "object", "additionalProperties": { "type": "string" } }
}
},
"spec": {
"type": "object",
"required": ["selector", "template"],
"properties": {
"replicas": { "type": "integer", "minimum": 0 },
"selector": {
"type": "object",
"required": ["matchLabels"],
"properties": {
"matchLabels": { "type": "object", "additionalProperties": { "type": "string" } }
}
},
"template": {
"type": "object",
"required": ["metadata", "spec"],
"properties": {
"metadata": {
"type": "object",
"properties": {
"labels": { "type": "object", "additionalProperties": { "type": "string" } }
}
},
"spec": {
"type": "object",
"required": ["containers"],
"properties": {
"containers": {
"type": "array",
"items": {
"type": "object",
"required": ["name", "image"],
"properties": {
"name": { "type": "string" },
"image": { "type": "string" },
"ports": {
"type": "array",
"items": {
"type": "object",
"properties": {
"containerPort": { "type": "integer" },
"protocol": { "type": "string", "enum": ["TCP", "UDP"] }
}
}
},
"resources": {
"type": "object",
"properties": {
"limits": { "type": "object" },
"requests": { "type": "object" }
}
},
"env": {
"type": "array",
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"value": { "type": "string" }
}
}
},
"livenessProbe": { "type": "object" },
"readinessProbe": { "type": "object" }
}
}
},
"initContainers": { "type": "array" },
"volumes": { "type": "array" },
"restartPolicy": { "type": "string", "enum": ["Always", "OnFailure", "Never"] }
}
}
}
},
"strategy": {
"type": "object",
"properties": {
"type": { "type": "string", "enum": ["RollingUpdate", "Recreate"] }
}
}
}
}
}
}
"#;
const K8S_SERVICE: &str = r#"
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["apiVersion", "kind", "metadata", "spec"],
"properties": {
"apiVersion": { "type": "string", "const": "v1" },
"kind": { "type": "string", "const": "Service" },
"metadata": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"namespace": { "type": "string" }
}
},
"spec": {
"type": "object",
"required": ["ports"],
"properties": {
"type": { "type": "string", "enum": ["ClusterIP", "NodePort", "LoadBalancer", "ExternalName"] },
"selector": { "type": "object", "additionalProperties": { "type": "string" } },
"ports": {
"type": "array",
"items": {
"type": "object",
"required": ["port"],
"properties": {
"name": { "type": "string" },
"port": { "type": "integer", "minimum": 1, "maximum": 65535 },
"targetPort": { "oneOf": [{ "type": "integer" }, { "type": "string" }] },
"protocol": { "type": "string", "enum": ["TCP", "UDP", "SCTP"] },
"nodePort": { "type": "integer", "minimum": 30000, "maximum": 32767 }
}
}
},
"clusterIP": { "type": "string" },
"externalName": { "type": "string" }
}
}
}
}
"#;
const K8S_CONFIGMAP: &str = r#"
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["apiVersion", "kind", "metadata"],
"properties": {
"apiVersion": { "type": "string", "const": "v1" },
"kind": { "type": "string", "const": "ConfigMap" },
"metadata": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"namespace": { "type": "string" }
}
},
"data": { "type": "object", "additionalProperties": { "type": "string" } },
"binaryData": { "type": "object", "additionalProperties": { "type": "string" } },
"immutable": { "type": "boolean" }
}
}
"#;
const K8S_SECRET: &str = r#"
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["apiVersion", "kind", "metadata"],
"properties": {
"apiVersion": { "type": "string", "const": "v1" },
"kind": { "type": "string", "const": "Secret" },
"metadata": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"namespace": { "type": "string" }
}
},
"type": { "type": "string" },
"data": { "type": "object", "additionalProperties": { "type": "string" } },
"stringData": { "type": "object", "additionalProperties": { "type": "string" } },
"immutable": { "type": "boolean" }
}
}
"#;
const GITLAB_CI: &str = r#"
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"stages": {
"type": "array",
"items": { "type": "string" }
},
"variables": { "type": "object" },
"default": { "type": "object" },
"workflow": { "type": "object" }
},
"additionalProperties": {
"oneOf": [
{ "type": "object" },
{ "type": "array" }
]
},
"patternProperties": {
"^[a-zA-Z_][a-zA-Z0-9_-]*$": {
"type": "object",
"properties": {
"stage": { "type": "string" },
"script": {
"oneOf": [
{ "type": "string" },
{ "type": "array", "items": { "type": "string" } }
]
},
"image": { "type": "string" },
"only": { "type": "array" },
"except": { "type": "array" },
"rules": { "type": "array" },
"extends": { "type": "string" }
}
}
}
}
"#;
const DOCKER_COMPOSE: &str = r#"
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["services"],
"properties": {
"version": { "type": "string" },
"services": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"image": { "type": "string" },
"build": {
"oneOf": [
{ "type": "string" },
{ "type": "object" }
]
},
"ports": {
"type": "array",
"items": {
"oneOf": [
{ "type": "integer" },
{ "type": "string" }
]
}
},
"environment": {
"oneOf": [
{ "type": "array" },
{ "type": "object" }
]
},
"volumes": { "type": "array" },
"depends_on": {
"oneOf": [
{ "type": "array" },
{ "type": "object" }
]
},
"networks": { "type": "array" },
"restart": { "type": "string" }
}
}
},
"volumes": { "type": "object" },
"networks": { "type": "object" }
}
}
"#;
const GITHUB_ACTIONS: &str = r#"
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["on", "jobs"],
"properties": {
"name": { "type": "string" },
"on": {
"oneOf": [
{ "type": "string" },
{ "type": "array" },
{ "type": "object" }
]
},
"env": { "type": "object" },
"defaults": { "type": "object" },
"concurrency": { "type": "object" },
"jobs": {
"type": "object",
"additionalProperties": {
"type": "object",
"required": ["runs-on"],
"properties": {
"runs-on": {
"oneOf": [
{ "type": "string" },
{ "type": "array" }
]
},
"needs": {
"oneOf": [
{ "type": "string" },
{ "type": "array" }
]
},
"if": { "type": "string" },
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"run": { "type": "string" },
"uses": { "type": "string" },
"with": { "type": "object" },
"env": { "type": "object" },
"if": { "type": "string" }
}
}
},
"env": { "type": "object" },
"outputs": { "type": "object" },
"timeout-minutes": { "type": "integer" }
}
}
}
}
}
"#;
const BUNDLED_SCHEMAS: &[(&str, &str)] = &[
("k8s/deployment", K8S_DEPLOYMENT),
("k8s/service", K8S_SERVICE),
("k8s/configmap", K8S_CONFIGMAP),
("k8s/secret", K8S_SECRET),
("gitlab-ci", GITLAB_CI),
("docker-compose", DOCKER_COMPOSE),
("github-actions", GITHUB_ACTIONS),
];
pub fn get_bundled_schema(schema_type: &str) -> Option<Value> {
for (key, schema_str) in BUNDLED_SCHEMAS {
if *key == schema_type {
return serde_json::from_str(schema_str).ok();
}
}
None
}
pub fn list_bundled_schemas() -> Vec<&'static str> {
BUNDLED_SCHEMAS.iter().map(|(key, _)| *key).collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_bundled_schema_k8s_deployment() {
let schema = get_bundled_schema("k8s/deployment");
assert!(schema.is_some());
let schema = schema.unwrap();
assert_eq!(schema["properties"]["kind"]["const"], "Deployment");
}
#[test]
fn test_get_bundled_schema_gitlab_ci() {
let schema = get_bundled_schema("gitlab-ci");
assert!(schema.is_some());
let schema = schema.unwrap();
assert!(schema["properties"]["stages"].is_object());
}
#[test]
fn test_get_bundled_schema_unknown() {
let schema = get_bundled_schema("unknown/type");
assert!(schema.is_none());
}
#[test]
fn test_list_bundled_schemas() {
let schemas = list_bundled_schemas();
assert!(schemas.contains(&"k8s/deployment"));
assert!(schemas.contains(&"gitlab-ci"));
assert_eq!(schemas.len(), 7);
}
#[test]
fn test_all_schemas_valid_json() {
for (key, schema_str) in BUNDLED_SCHEMAS {
let result: Result<Value, _> = serde_json::from_str(schema_str);
assert!(result.is_ok(), "Schema {} is not valid JSON", key);
}
}
}