1use crate::analyzer::kubelint::types::ObjectKind;
4use serde::{Deserialize, Serialize};
5use std::path::PathBuf;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct ObjectMetadata {
10 pub file_path: PathBuf,
12 pub raw: Option<Vec<u8>>,
14 pub line_number: Option<u32>,
16}
17
18impl ObjectMetadata {
19 pub fn from_file(path: impl Into<PathBuf>) -> Self {
21 Self {
22 file_path: path.into(),
23 raw: None,
24 line_number: None,
25 }
26 }
27
28 pub fn with_raw(mut self, raw: Vec<u8>) -> Self {
30 self.raw = Some(raw);
31 self
32 }
33
34 pub fn with_line(mut self, line: u32) -> Self {
36 self.line_number = Some(line);
37 self
38 }
39}
40
41#[derive(Debug, Clone)]
43pub struct Object {
44 pub metadata: ObjectMetadata,
46 pub k8s_object: K8sObject,
48}
49
50impl Object {
51 pub fn new(metadata: ObjectMetadata, k8s_object: K8sObject) -> Self {
53 Self {
54 metadata,
55 k8s_object,
56 }
57 }
58
59 pub fn kind(&self) -> ObjectKind {
61 self.k8s_object.kind()
62 }
63
64 pub fn name(&self) -> &str {
66 self.k8s_object.name()
67 }
68
69 pub fn namespace(&self) -> Option<&str> {
71 self.k8s_object.namespace()
72 }
73
74 pub fn annotations(&self) -> Option<&std::collections::BTreeMap<String, String>> {
76 self.k8s_object.annotations()
77 }
78}
79
80#[derive(Debug, Clone)]
82pub struct InvalidObject {
83 pub metadata: ObjectMetadata,
85 pub load_err: String,
87}
88
89impl InvalidObject {
90 pub fn new(metadata: ObjectMetadata, error: impl Into<String>) -> Self {
92 Self {
93 metadata,
94 load_err: error.into(),
95 }
96 }
97}
98
99#[derive(Debug, Clone)]
104pub enum K8sObject {
105 Deployment(Box<DeploymentData>),
107 StatefulSet(Box<StatefulSetData>),
108 DaemonSet(Box<DaemonSetData>),
109 ReplicaSet(Box<ReplicaSetData>),
110 Pod(Box<PodData>),
111 Job(Box<JobData>),
112 CronJob(Box<CronJobData>),
113
114 Service(Box<ServiceData>),
116 Ingress(Box<IngressData>),
117 NetworkPolicy(Box<NetworkPolicyData>),
118
119 Role(Box<RoleData>),
121 ClusterRole(Box<ClusterRoleData>),
122 RoleBinding(Box<RoleBindingData>),
123 ClusterRoleBinding(Box<ClusterRoleBindingData>),
124 ServiceAccount(Box<ServiceAccountData>),
125
126 HorizontalPodAutoscaler(Box<HpaData>),
128 PodDisruptionBudget(Box<PdbData>),
129
130 PersistentVolumeClaim(Box<PvcData>),
132
133 Unknown(Box<UnknownObject>),
135}
136
137impl K8sObject {
138 pub fn kind(&self) -> ObjectKind {
140 match self {
141 Self::Deployment(_) => ObjectKind::Deployment,
142 Self::StatefulSet(_) => ObjectKind::StatefulSet,
143 Self::DaemonSet(_) => ObjectKind::DaemonSet,
144 Self::ReplicaSet(_) => ObjectKind::ReplicaSet,
145 Self::Pod(_) => ObjectKind::Pod,
146 Self::Job(_) => ObjectKind::Job,
147 Self::CronJob(_) => ObjectKind::CronJob,
148 Self::Service(_) => ObjectKind::Service,
149 Self::Ingress(_) => ObjectKind::Ingress,
150 Self::NetworkPolicy(_) => ObjectKind::NetworkPolicy,
151 Self::Role(_) => ObjectKind::Role,
152 Self::ClusterRole(_) => ObjectKind::ClusterRole,
153 Self::RoleBinding(_) => ObjectKind::RoleBinding,
154 Self::ClusterRoleBinding(_) => ObjectKind::ClusterRoleBinding,
155 Self::ServiceAccount(_) => ObjectKind::ServiceAccount,
156 Self::HorizontalPodAutoscaler(_) => ObjectKind::HorizontalPodAutoscaler,
157 Self::PodDisruptionBudget(_) => ObjectKind::PodDisruptionBudget,
158 Self::PersistentVolumeClaim(_) => ObjectKind::PersistentVolumeClaim,
159 Self::Unknown(_) => ObjectKind::Any,
160 }
161 }
162
163 pub fn name(&self) -> &str {
165 match self {
166 Self::Deployment(d) => &d.name,
167 Self::StatefulSet(d) => &d.name,
168 Self::DaemonSet(d) => &d.name,
169 Self::ReplicaSet(d) => &d.name,
170 Self::Pod(d) => &d.name,
171 Self::Job(d) => &d.name,
172 Self::CronJob(d) => &d.name,
173 Self::Service(d) => &d.name,
174 Self::Ingress(d) => &d.name,
175 Self::NetworkPolicy(d) => &d.name,
176 Self::Role(d) => &d.name,
177 Self::ClusterRole(d) => &d.name,
178 Self::RoleBinding(d) => &d.name,
179 Self::ClusterRoleBinding(d) => &d.name,
180 Self::ServiceAccount(d) => &d.name,
181 Self::HorizontalPodAutoscaler(d) => &d.name,
182 Self::PodDisruptionBudget(d) => &d.name,
183 Self::PersistentVolumeClaim(d) => &d.name,
184 Self::Unknown(d) => &d.name,
185 }
186 }
187
188 pub fn namespace(&self) -> Option<&str> {
190 match self {
191 Self::Deployment(d) => d.namespace.as_deref(),
192 Self::StatefulSet(d) => d.namespace.as_deref(),
193 Self::DaemonSet(d) => d.namespace.as_deref(),
194 Self::ReplicaSet(d) => d.namespace.as_deref(),
195 Self::Pod(d) => d.namespace.as_deref(),
196 Self::Job(d) => d.namespace.as_deref(),
197 Self::CronJob(d) => d.namespace.as_deref(),
198 Self::Service(d) => d.namespace.as_deref(),
199 Self::Ingress(d) => d.namespace.as_deref(),
200 Self::NetworkPolicy(d) => d.namespace.as_deref(),
201 Self::Role(d) => d.namespace.as_deref(),
202 Self::ClusterRole(_) => None, Self::RoleBinding(d) => d.namespace.as_deref(),
204 Self::ClusterRoleBinding(_) => None, Self::ServiceAccount(d) => d.namespace.as_deref(),
206 Self::HorizontalPodAutoscaler(d) => d.namespace.as_deref(),
207 Self::PodDisruptionBudget(d) => d.namespace.as_deref(),
208 Self::PersistentVolumeClaim(d) => d.namespace.as_deref(),
209 Self::Unknown(d) => d.namespace.as_deref(),
210 }
211 }
212
213 pub fn annotations(&self) -> Option<&std::collections::BTreeMap<String, String>> {
215 match self {
216 Self::Deployment(d) => d.annotations.as_ref(),
217 Self::StatefulSet(d) => d.annotations.as_ref(),
218 Self::DaemonSet(d) => d.annotations.as_ref(),
219 Self::ReplicaSet(d) => d.annotations.as_ref(),
220 Self::Pod(d) => d.annotations.as_ref(),
221 Self::Job(d) => d.annotations.as_ref(),
222 Self::CronJob(d) => d.annotations.as_ref(),
223 Self::Service(d) => d.annotations.as_ref(),
224 Self::Ingress(d) => d.annotations.as_ref(),
225 Self::NetworkPolicy(d) => d.annotations.as_ref(),
226 Self::Role(d) => d.annotations.as_ref(),
227 Self::ClusterRole(d) => d.annotations.as_ref(),
228 Self::RoleBinding(d) => d.annotations.as_ref(),
229 Self::ClusterRoleBinding(d) => d.annotations.as_ref(),
230 Self::ServiceAccount(d) => d.annotations.as_ref(),
231 Self::HorizontalPodAutoscaler(d) => d.annotations.as_ref(),
232 Self::PodDisruptionBudget(d) => d.annotations.as_ref(),
233 Self::PersistentVolumeClaim(d) => d.annotations.as_ref(),
234 Self::Unknown(d) => d.annotations.as_ref(),
235 }
236 }
237}
238
239#[derive(Debug, Clone, Default)]
247pub struct CommonMeta {
248 pub name: String,
249 pub namespace: Option<String>,
250 pub labels: Option<std::collections::BTreeMap<String, String>>,
251 pub annotations: Option<std::collections::BTreeMap<String, String>>,
252}
253
254#[derive(Debug, Clone, Default)]
256pub struct ContainerSpec {
257 pub name: String,
258 pub image: Option<String>,
259 pub security_context: Option<SecurityContext>,
260 pub resources: Option<ResourceRequirements>,
261 pub liveness_probe: Option<Probe>,
262 pub readiness_probe: Option<Probe>,
263 pub startup_probe: Option<Probe>,
264 pub env: Vec<EnvVar>,
265 pub volume_mounts: Vec<VolumeMount>,
266 pub ports: Vec<ContainerPort>,
267}
268
269#[derive(Debug, Clone, Default)]
271pub struct SecurityContext {
272 pub privileged: Option<bool>,
273 pub allow_privilege_escalation: Option<bool>,
274 pub run_as_non_root: Option<bool>,
275 pub run_as_user: Option<i64>,
276 pub read_only_root_filesystem: Option<bool>,
277 pub capabilities: Option<Capabilities>,
278 pub proc_mount: Option<String>,
279}
280
281#[derive(Debug, Clone, Default)]
283pub struct Capabilities {
284 pub add: Vec<String>,
285 pub drop: Vec<String>,
286}
287
288#[derive(Debug, Clone, Default)]
290pub struct ResourceRequirements {
291 pub limits: Option<std::collections::BTreeMap<String, String>>,
292 pub requests: Option<std::collections::BTreeMap<String, String>>,
293}
294
295#[derive(Debug, Clone, Default)]
297pub struct Probe {
298 pub http_get: Option<HttpGetAction>,
299 pub tcp_socket: Option<TcpSocketAction>,
300 pub exec: Option<ExecAction>,
301}
302
303#[derive(Debug, Clone, Default)]
304pub struct HttpGetAction {
305 pub port: i32,
306 pub path: Option<String>,
307}
308
309#[derive(Debug, Clone, Default)]
310pub struct TcpSocketAction {
311 pub port: i32,
312}
313
314#[derive(Debug, Clone, Default)]
315pub struct ExecAction {
316 pub command: Vec<String>,
317}
318
319#[derive(Debug, Clone, Default)]
321pub struct EnvVar {
322 pub name: String,
323 pub value: Option<String>,
324 pub value_from: Option<EnvVarSource>,
325}
326
327#[derive(Debug, Clone)]
328pub enum EnvVarSource {
329 SecretKeyRef { name: String, key: String },
330 ConfigMapKeyRef { name: String, key: String },
331 FieldRef { field_path: String },
332}
333
334#[derive(Debug, Clone, Default)]
336pub struct VolumeMount {
337 pub name: String,
338 pub mount_path: String,
339 pub read_only: Option<bool>,
340}
341
342#[derive(Debug, Clone, Default)]
344pub struct ContainerPort {
345 pub container_port: i32,
346 pub protocol: Option<String>,
347 pub host_port: Option<i32>,
348}
349
350#[derive(Debug, Clone, Default)]
352pub struct PodSpec {
353 pub containers: Vec<ContainerSpec>,
354 pub init_containers: Vec<ContainerSpec>,
355 pub volumes: Vec<Volume>,
356 pub service_account_name: Option<String>,
357 pub host_network: Option<bool>,
358 pub host_pid: Option<bool>,
359 pub host_ipc: Option<bool>,
360 pub security_context: Option<PodSecurityContext>,
361 pub affinity: Option<Affinity>,
362 pub dns_config: Option<DnsConfig>,
363 pub restart_policy: Option<String>,
364 pub priority_class_name: Option<String>,
365}
366
367#[derive(Debug, Clone, Default)]
368pub struct PodSecurityContext {
369 pub run_as_non_root: Option<bool>,
370 pub run_as_user: Option<i64>,
371 pub sysctls: Vec<Sysctl>,
372}
373
374#[derive(Debug, Clone, Default)]
375pub struct Sysctl {
376 pub name: String,
377 pub value: String,
378}
379
380#[derive(Debug, Clone, Default)]
381pub struct Volume {
382 pub name: String,
383 pub host_path: Option<HostPathVolumeSource>,
384 pub secret: Option<SecretVolumeSource>,
385}
386
387#[derive(Debug, Clone, Default)]
388pub struct HostPathVolumeSource {
389 pub path: String,
390 pub type_: Option<String>,
391}
392
393#[derive(Debug, Clone, Default)]
394pub struct SecretVolumeSource {
395 pub secret_name: Option<String>,
396}
397
398#[derive(Debug, Clone, Default)]
399pub struct Affinity {
400 pub pod_anti_affinity: Option<PodAntiAffinity>,
401 pub node_affinity: Option<NodeAffinity>,
402}
403
404#[derive(Debug, Clone, Default)]
405pub struct PodAntiAffinity {
406 pub required_during_scheduling_ignored_during_execution: Vec<PodAffinityTerm>,
407 pub preferred_during_scheduling_ignored_during_execution: Vec<WeightedPodAffinityTerm>,
408}
409
410#[derive(Debug, Clone, Default)]
411pub struct PodAffinityTerm {
412 pub topology_key: String,
413}
414
415#[derive(Debug, Clone, Default)]
416pub struct WeightedPodAffinityTerm {
417 pub weight: i32,
418 pub pod_affinity_term: PodAffinityTerm,
419}
420
421#[derive(Debug, Clone, Default)]
422pub struct NodeAffinity {
423 pub required_during_scheduling_ignored_during_execution: Option<NodeSelector>,
424}
425
426#[derive(Debug, Clone, Default)]
427pub struct NodeSelector {
428 pub node_selector_terms: Vec<NodeSelectorTerm>,
429}
430
431#[derive(Debug, Clone, Default)]
432pub struct NodeSelectorTerm {
433 pub match_expressions: Vec<NodeSelectorRequirement>,
434}
435
436#[derive(Debug, Clone, Default)]
437pub struct NodeSelectorRequirement {
438 pub key: String,
439 pub operator: String,
440 pub values: Vec<String>,
441}
442
443#[derive(Debug, Clone, Default)]
444pub struct DnsConfig {
445 pub options: Vec<PodDnsConfigOption>,
446}
447
448#[derive(Debug, Clone, Default)]
449pub struct PodDnsConfigOption {
450 pub name: Option<String>,
451 pub value: Option<String>,
452}
453
454#[derive(Debug, Clone, Default)]
459pub struct DeploymentData {
460 pub name: String,
461 pub namespace: Option<String>,
462 pub annotations: Option<std::collections::BTreeMap<String, String>>,
463 pub labels: Option<std::collections::BTreeMap<String, String>>,
464 pub replicas: Option<i32>,
465 pub selector: Option<LabelSelector>,
466 pub pod_spec: Option<PodSpec>,
467 pub strategy: Option<DeploymentStrategy>,
468}
469
470#[derive(Debug, Clone, Default)]
471pub struct LabelSelector {
472 pub match_labels: Option<std::collections::BTreeMap<String, String>>,
473}
474
475#[derive(Debug, Clone, Default)]
476pub struct DeploymentStrategy {
477 pub type_: Option<String>,
478 pub rolling_update: Option<RollingUpdateDeployment>,
479}
480
481#[derive(Debug, Clone, Default)]
482pub struct RollingUpdateDeployment {
483 pub max_unavailable: Option<String>,
484 pub max_surge: Option<String>,
485}
486
487#[derive(Debug, Clone, Default)]
488pub struct StatefulSetData {
489 pub name: String,
490 pub namespace: Option<String>,
491 pub annotations: Option<std::collections::BTreeMap<String, String>>,
492 pub labels: Option<std::collections::BTreeMap<String, String>>,
493 pub replicas: Option<i32>,
494 pub selector: Option<LabelSelector>,
495 pub pod_spec: Option<PodSpec>,
496}
497
498#[derive(Debug, Clone, Default)]
499pub struct DaemonSetData {
500 pub name: String,
501 pub namespace: Option<String>,
502 pub annotations: Option<std::collections::BTreeMap<String, String>>,
503 pub labels: Option<std::collections::BTreeMap<String, String>>,
504 pub selector: Option<LabelSelector>,
505 pub pod_spec: Option<PodSpec>,
506 pub update_strategy: Option<DaemonSetUpdateStrategy>,
507}
508
509#[derive(Debug, Clone, Default)]
510pub struct DaemonSetUpdateStrategy {
511 pub type_: Option<String>,
512}
513
514#[derive(Debug, Clone, Default)]
515pub struct ReplicaSetData {
516 pub name: String,
517 pub namespace: Option<String>,
518 pub annotations: Option<std::collections::BTreeMap<String, String>>,
519 pub labels: Option<std::collections::BTreeMap<String, String>>,
520 pub replicas: Option<i32>,
521 pub selector: Option<LabelSelector>,
522 pub pod_spec: Option<PodSpec>,
523}
524
525#[derive(Debug, Clone, Default)]
526pub struct PodData {
527 pub name: String,
528 pub namespace: Option<String>,
529 pub annotations: Option<std::collections::BTreeMap<String, String>>,
530 pub labels: Option<std::collections::BTreeMap<String, String>>,
531 pub spec: Option<PodSpec>,
532}
533
534#[derive(Debug, Clone, Default)]
535pub struct JobData {
536 pub name: String,
537 pub namespace: Option<String>,
538 pub annotations: Option<std::collections::BTreeMap<String, String>>,
539 pub labels: Option<std::collections::BTreeMap<String, String>>,
540 pub pod_spec: Option<PodSpec>,
541 pub ttl_seconds_after_finished: Option<i32>,
542}
543
544#[derive(Debug, Clone, Default)]
545pub struct CronJobData {
546 pub name: String,
547 pub namespace: Option<String>,
548 pub annotations: Option<std::collections::BTreeMap<String, String>>,
549 pub labels: Option<std::collections::BTreeMap<String, String>>,
550 pub job_spec: Option<JobData>,
551}
552
553#[derive(Debug, Clone, Default)]
554pub struct ServiceData {
555 pub name: String,
556 pub namespace: Option<String>,
557 pub annotations: Option<std::collections::BTreeMap<String, String>>,
558 pub labels: Option<std::collections::BTreeMap<String, String>>,
559 pub selector: Option<std::collections::BTreeMap<String, String>>,
560 pub ports: Vec<ServicePort>,
561 pub type_: Option<String>,
562}
563
564#[derive(Debug, Clone, Default)]
565pub struct ServicePort {
566 pub port: i32,
567 pub target_port: Option<String>,
568 pub protocol: Option<String>,
569 pub name: Option<String>,
570}
571
572#[derive(Debug, Clone, Default)]
573pub struct IngressData {
574 pub name: String,
575 pub namespace: Option<String>,
576 pub annotations: Option<std::collections::BTreeMap<String, String>>,
577 pub labels: Option<std::collections::BTreeMap<String, String>>,
578 pub rules: Vec<IngressRule>,
579}
580
581#[derive(Debug, Clone, Default)]
582pub struct IngressRule {
583 pub host: Option<String>,
584 pub http: Option<HttpIngressRuleValue>,
585}
586
587#[derive(Debug, Clone, Default)]
588pub struct HttpIngressRuleValue {
589 pub paths: Vec<HttpIngressPath>,
590}
591
592#[derive(Debug, Clone, Default)]
593pub struct HttpIngressPath {
594 pub path: Option<String>,
595 pub backend: IngressBackend,
596}
597
598#[derive(Debug, Clone, Default)]
599pub struct IngressBackend {
600 pub service: Option<IngressServiceBackend>,
601}
602
603#[derive(Debug, Clone, Default)]
604pub struct IngressServiceBackend {
605 pub name: String,
606 pub port: Option<ServiceBackendPort>,
607}
608
609#[derive(Debug, Clone, Default)]
610pub struct ServiceBackendPort {
611 pub number: Option<i32>,
612 pub name: Option<String>,
613}
614
615#[derive(Debug, Clone, Default)]
616pub struct NetworkPolicyData {
617 pub name: String,
618 pub namespace: Option<String>,
619 pub annotations: Option<std::collections::BTreeMap<String, String>>,
620 pub labels: Option<std::collections::BTreeMap<String, String>>,
621 pub pod_selector: Option<LabelSelector>,
622}
623
624#[derive(Debug, Clone, Default)]
625pub struct RoleData {
626 pub name: String,
627 pub namespace: Option<String>,
628 pub annotations: Option<std::collections::BTreeMap<String, String>>,
629 pub labels: Option<std::collections::BTreeMap<String, String>>,
630 pub rules: Vec<PolicyRule>,
631}
632
633#[derive(Debug, Clone, Default)]
634pub struct ClusterRoleData {
635 pub name: String,
636 pub annotations: Option<std::collections::BTreeMap<String, String>>,
637 pub labels: Option<std::collections::BTreeMap<String, String>>,
638 pub rules: Vec<PolicyRule>,
639}
640
641#[derive(Debug, Clone, Default)]
642pub struct PolicyRule {
643 pub api_groups: Vec<String>,
644 pub resources: Vec<String>,
645 pub verbs: Vec<String>,
646}
647
648#[derive(Debug, Clone, Default)]
649pub struct RoleBindingData {
650 pub name: String,
651 pub namespace: Option<String>,
652 pub annotations: Option<std::collections::BTreeMap<String, String>>,
653 pub labels: Option<std::collections::BTreeMap<String, String>>,
654 pub role_ref: RoleRef,
655 pub subjects: Vec<Subject>,
656}
657
658#[derive(Debug, Clone, Default)]
659pub struct ClusterRoleBindingData {
660 pub name: String,
661 pub annotations: Option<std::collections::BTreeMap<String, String>>,
662 pub labels: Option<std::collections::BTreeMap<String, String>>,
663 pub role_ref: RoleRef,
664 pub subjects: Vec<Subject>,
665}
666
667#[derive(Debug, Clone, Default)]
668pub struct RoleRef {
669 pub api_group: String,
670 pub kind: String,
671 pub name: String,
672}
673
674#[derive(Debug, Clone, Default)]
675pub struct Subject {
676 pub kind: String,
677 pub name: String,
678 pub namespace: Option<String>,
679}
680
681#[derive(Debug, Clone, Default)]
682pub struct ServiceAccountData {
683 pub name: String,
684 pub namespace: Option<String>,
685 pub annotations: Option<std::collections::BTreeMap<String, String>>,
686 pub labels: Option<std::collections::BTreeMap<String, String>>,
687}
688
689#[derive(Debug, Clone, Default)]
690pub struct HpaData {
691 pub name: String,
692 pub namespace: Option<String>,
693 pub annotations: Option<std::collections::BTreeMap<String, String>>,
694 pub labels: Option<std::collections::BTreeMap<String, String>>,
695 pub min_replicas: Option<i32>,
696 pub max_replicas: i32,
697 pub scale_target_ref: CrossVersionObjectReference,
698}
699
700#[derive(Debug, Clone, Default)]
701pub struct CrossVersionObjectReference {
702 pub api_version: Option<String>,
703 pub kind: String,
704 pub name: String,
705}
706
707#[derive(Debug, Clone, Default)]
708pub struct PdbData {
709 pub name: String,
710 pub namespace: Option<String>,
711 pub annotations: Option<std::collections::BTreeMap<String, String>>,
712 pub labels: Option<std::collections::BTreeMap<String, String>>,
713 pub min_available: Option<String>,
714 pub max_unavailable: Option<String>,
715 pub selector: Option<LabelSelector>,
716 pub unhealthy_pod_eviction_policy: Option<String>,
717}
718
719#[derive(Debug, Clone, Default)]
720pub struct PvcData {
721 pub name: String,
722 pub namespace: Option<String>,
723 pub annotations: Option<std::collections::BTreeMap<String, String>>,
724 pub labels: Option<std::collections::BTreeMap<String, String>>,
725}
726
727#[derive(Debug, Clone, Default)]
728pub struct UnknownObject {
729 pub api_version: String,
730 pub kind: String,
731 pub name: String,
732 pub namespace: Option<String>,
733 pub annotations: Option<std::collections::BTreeMap<String, String>>,
734 pub labels: Option<std::collections::BTreeMap<String, String>>,
735 pub raw: serde_yaml::Value,
736}