Skip to content

Commit 0d3cb8d

Browse files
sionsmithclaude
andcommitted
fix: Fix CRD schema, clippy warnings, and formatting
- Add explicit object type schema for affinity and securityContext fields - Replace manual modulo check with is_multiple_of() - Replace format! with to_string() for static strings - Run cargo fmt to fix all formatting issues 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 58afd3b commit 0d3cb8d

File tree

10 files changed

+60
-40
lines changed

10 files changed

+60
-40
lines changed

deploy/crds/all.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ spec:
305305
properties:
306306
affinity:
307307
description: Affinity rules (JSON/YAML format matching k8s affinity)
308-
nullable: true
308+
type: object
309309
annotations:
310310
additionalProperties:
311311
type: string
@@ -355,7 +355,7 @@ spec:
355355
type: object
356356
securityContext:
357357
description: Security context (JSON/YAML format matching k8s pod security context)
358-
nullable: true
358+
type: object
359359
serviceAccountName:
360360
description: Service account name
361361
nullable: true
@@ -388,6 +388,9 @@ spec:
388388
type: string
389389
type: object
390390
type: array
391+
required:
392+
- affinity
393+
- securityContext
391394
type: object
392395
replicas:
393396
default: 1

deploy/helm/kafka-partition-remapper-operator/crds/all.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ spec:
305305
properties:
306306
affinity:
307307
description: Affinity rules (JSON/YAML format matching k8s affinity)
308-
nullable: true
308+
type: object
309309
annotations:
310310
additionalProperties:
311311
type: string
@@ -355,7 +355,7 @@ spec:
355355
type: object
356356
securityContext:
357357
description: Security context (JSON/YAML format matching k8s pod security context)
358-
nullable: true
358+
type: object
359359
serviceAccountName:
360360
description: Service account name
361361
nullable: true
@@ -388,6 +388,9 @@ spec:
388388
type: string
389389
type: object
390390
type: array
391+
required:
392+
- affinity
393+
- securityContext
391394
type: object
392395
replicas:
393396
default: 1

src/adapters/deployment_builder.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
33
use k8s_openapi::api::apps::v1::{Deployment, DeploymentSpec};
44
use k8s_openapi::api::core::v1::{
5-
Container, ContainerPort, EnvVar, PodSpec, PodTemplateSpec, Probe, TCPSocketAction,
6-
Volume, VolumeMount, ConfigMapVolumeSource, LocalObjectReference,
5+
ConfigMapVolumeSource, Container, ContainerPort, EnvVar, LocalObjectReference, PodSpec,
6+
PodTemplateSpec, Probe, TCPSocketAction, Volume, VolumeMount,
77
};
88
use k8s_openapi::apimachinery::pkg::apis::meta::v1::{LabelSelector, ObjectMeta, OwnerReference};
99
use k8s_openapi::apimachinery::pkg::util::intstr::IntOrString;
@@ -278,9 +278,7 @@ fn build_pod_spec(spec: &KafkaPartitionRemapperSpec, config_map_name: &str) -> P
278278
pod_spec.image_pull_secrets = Some(
279279
pt.image_pull_secrets
280280
.iter()
281-
.map(|s| LocalObjectReference {
282-
name: s.clone(),
283-
})
281+
.map(|s| LocalObjectReference { name: s.clone() })
284282
.collect(),
285283
);
286284
}

src/adapters/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Adapters for configuration transformation and Kubernetes resource building
22
3-
pub mod secrets;
4-
pub mod remapper_config;
53
pub mod deployment_builder;
4+
pub mod remapper_config;
5+
pub mod secrets;
66
pub mod service_builder;

src/adapters/secrets.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub fn get_secret_key(secret: &Secret, key: &str) -> Result<String> {
1919
let data = secret
2020
.data
2121
.as_ref()
22-
.ok_or_else(|| Error::SecretError(format!("Secret has no data")))?;
22+
.ok_or_else(|| Error::SecretError("Secret has no data".to_string()))?;
2323

2424
let value = data
2525
.get(key)

src/controllers/remapper_controller.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use tracing::{error, info, instrument};
1515

1616
use crate::controllers::Context;
1717
use crate::crd::KafkaPartitionRemapper;
18-
use crate::metrics::prometheus::{RECONCILIATIONS, RECONCILE_DURATION, RECONCILIATION_ERRORS};
18+
use crate::metrics::prometheus::{RECONCILE_DURATION, RECONCILIATIONS, RECONCILIATION_ERRORS};
1919
use crate::reconcilers::remapper;
2020
use crate::Error;
2121

@@ -53,7 +53,9 @@ async fn reconcile(
5353
let ns = remapper.namespace().unwrap_or_default();
5454
let name = remapper.name_any();
5555

56-
RECONCILIATIONS.with_label_values(&["KafkaPartitionRemapper"]).inc();
56+
RECONCILIATIONS
57+
.with_label_values(&["KafkaPartitionRemapper"])
58+
.inc();
5759

5860
let remappers: Api<KafkaPartitionRemapper> = Api::namespaced(ctx.client.clone(), &ns);
5961

@@ -100,7 +102,8 @@ async fn apply(remapper: &KafkaPartitionRemapper, ctx: &Context) -> Result<Actio
100102
let config_map_name = remapper::reconcile_config_map(remapper, &ctx.client, &ns).await?;
101103

102104
// Reconcile Deployment
103-
let deployment_name = remapper::reconcile_deployment(remapper, &ctx.client, &ns, &config_map_name).await?;
105+
let deployment_name =
106+
remapper::reconcile_deployment(remapper, &ctx.client, &ns, &config_map_name).await?;
104107

105108
// Reconcile Service
106109
let service_name = remapper::reconcile_service(remapper, &ctx.client, &ns).await?;
@@ -138,15 +141,14 @@ fn error_policy(remapper: Arc<KafkaPartitionRemapper>, err: &Error, _ctx: Arc<Co
138141
let ns = remapper.namespace().unwrap_or_default();
139142
let name = remapper.name_any();
140143

141-
error!(
142-
"Reconciliation error for {}/{}: {:?}",
143-
ns, name, err
144-
);
144+
error!("Reconciliation error for {}/{}: {:?}", ns, name, err);
145145

146146
// Requeue with exponential backoff based on error type
147147
match err {
148148
Error::KubeError(_) => Action::requeue(Duration::from_secs(30)),
149-
Error::ConfigError(_) | Error::ValidationError(_) => Action::requeue(Duration::from_secs(300)),
149+
Error::ConfigError(_) | Error::ValidationError(_) => {
150+
Action::requeue(Duration::from_secs(300))
151+
}
150152
_ => Action::requeue(Duration::from_secs(60)),
151153
}
152154
}

src/crd/kafka_partition_remapper.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,7 @@ pub struct PodTemplateSpec {
439439

440440
/// Affinity rules (JSON/YAML format matching k8s affinity)
441441
#[serde(skip_serializing_if = "Option::is_none")]
442+
#[schemars(schema_with = "any_object_schema")]
442443
pub affinity: Option<serde_json::Value>,
443444

444445
/// Resource requirements
@@ -467,9 +468,18 @@ pub struct PodTemplateSpec {
467468

468469
/// Security context (JSON/YAML format matching k8s pod security context)
469470
#[serde(skip_serializing_if = "Option::is_none")]
471+
#[schemars(schema_with = "any_object_schema")]
470472
pub security_context: Option<serde_json::Value>,
471473
}
472474

475+
/// Generate a schema for arbitrary JSON objects
476+
fn any_object_schema(_gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
477+
schemars::schema::Schema::Object(schemars::schema::SchemaObject {
478+
instance_type: Some(schemars::schema::InstanceType::Object.into()),
479+
..Default::default()
480+
})
481+
}
482+
473483
/// Toleration specification
474484
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
475485
#[serde(rename_all = "camelCase")]

src/main.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ async fn main() -> anyhow::Result<()> {
5656

5757
/// Initialize tracing subscriber
5858
fn init_tracing() {
59-
let env_filter = EnvFilter::try_from_default_env()
60-
.unwrap_or_else(|_| EnvFilter::new("info,kafka_partition_remapper_operator=debug,kube=warn,hyper=warn"));
59+
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
60+
EnvFilter::new("info,kafka_partition_remapper_operator=debug,kube=warn,hyper=warn")
61+
});
6162

6263
tracing_subscriber::registry()
6364
.with(env_filter)

src/reconcilers/remapper.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub fn validate(remapper: &KafkaPartitionRemapper) -> Result<()> {
3838
));
3939
}
4040

41-
if spec.mapping.virtual_partitions % spec.mapping.physical_partitions != 0 {
41+
if !spec.mapping.virtual_partitions.is_multiple_of(spec.mapping.physical_partitions) {
4242
return Err(Error::ValidationError(
4343
"mapping.virtualPartitions must be evenly divisible by mapping.physicalPartitions"
4444
.to_string(),
@@ -56,9 +56,7 @@ pub fn validate(remapper: &KafkaPartitionRemapper) -> Result<()> {
5656

5757
// Validate replicas
5858
if spec.replicas < 0 {
59-
return Err(Error::ValidationError(
60-
"replicas must be >= 0".to_string(),
61-
));
59+
return Err(Error::ValidationError("replicas must be >= 0".to_string()));
6260
}
6361

6462
// Validate security protocol
@@ -254,13 +252,18 @@ pub async fn update_status(
254252
type_: "DeploymentAvailable".to_string(),
255253
status: if ready_replicas > 0 { "True" } else { "False" }.to_string(),
256254
last_transition_time: now,
257-
reason: Some(if ready_replicas > 0 {
258-
"ReplicasAvailable"
259-
} else {
260-
"NoReplicasAvailable"
261-
}
262-
.to_string()),
263-
message: Some(format!("{}/{} replicas ready", ready_replicas, spec.replicas)),
255+
reason: Some(
256+
if ready_replicas > 0 {
257+
"ReplicasAvailable"
258+
} else {
259+
"NoReplicasAvailable"
260+
}
261+
.to_string(),
262+
),
263+
message: Some(format!(
264+
"{}/{} replicas ready",
265+
ready_replicas, spec.replicas
266+
)),
264267
});
265268

266269
conditions.push(Condition {

tests/reconciler_validation_tests.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
66
use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta;
77
use kafka_partition_remapper_operator::crd::{
8-
KafkaClusterSpec, KafkaPartitionRemapper, KafkaPartitionRemapperSpec, ListenSpec,
9-
LoggingSpec, MappingSpec, MetricsSpec, ServiceSpec,
8+
KafkaClusterSpec, KafkaPartitionRemapper, KafkaPartitionRemapperSpec, ListenSpec, LoggingSpec,
9+
MappingSpec, MetricsSpec, ServiceSpec,
1010
};
1111
use kafka_partition_remapper_operator::reconcilers::remapper;
1212

@@ -172,11 +172,11 @@ fn remapper_virtual_not_divisible_by_physical_fails_validation() {
172172
#[test]
173173
fn remapper_valid_partition_ratios_pass_validation() {
174174
let valid_ratios = vec![
175-
(100, 100), // 1:1
176-
(100, 200), // 1:2
177-
(100, 1000), // 1:10
178-
(50, 500), // 1:10
179-
(10, 100), // 1:10
175+
(100, 100), // 1:1
176+
(100, 200), // 1:2
177+
(100, 1000), // 1:10
178+
(50, 500), // 1:10
179+
(10, 100), // 1:10
180180
];
181181

182182
for (physical, virtual_p) in valid_ratios {

0 commit comments

Comments
 (0)