From 63eb2fb910a3f17c0ccdd06c4920fd45159d8654 Mon Sep 17 00:00:00 2001 From: Razz4780 Date: Tue, 10 Dec 2024 15:51:59 +0100 Subject: [PATCH 1/2] Moved MirrordPolicy to a separate module, added MirrordClusterPolicy --- changelog.d/+cluster-policy.added.md | 1 + mirrord/operator/src/crd.rs | 49 +--------------- mirrord/operator/src/crd/policy.rs | 88 ++++++++++++++++++++++++++++ mirrord/operator/src/setup.rs | 12 +++- 4 files changed, 100 insertions(+), 50 deletions(-) create mode 100644 changelog.d/+cluster-policy.added.md create mode 100644 mirrord/operator/src/crd/policy.rs diff --git a/changelog.d/+cluster-policy.added.md b/changelog.d/+cluster-policy.added.md new file mode 100644 index 00000000000..2725780086b --- /dev/null +++ b/changelog.d/+cluster-policy.added.md @@ -0,0 +1 @@ +Added custom resource definition for cluster-wide mirrord policy - `MirrordClusterPolicy`. diff --git a/mirrord/operator/src/crd.rs b/mirrord/operator/src/crd.rs index 8f7c770d074..bf103983ede 100644 --- a/mirrord/operator/src/crd.rs +++ b/mirrord/operator/src/crd.rs @@ -15,7 +15,6 @@ use schemars::JsonSchema; use semver::Version; use serde::{Deserialize, Serialize}; -use self::label_selector::LabelSelector; #[cfg(feature = "client")] use crate::client::error::OperatorApiError; use crate::types::LicenseInfoOwned; @@ -23,6 +22,7 @@ use crate::types::LicenseInfoOwned; pub mod kafka; pub mod kube_target; pub mod label_selector; +pub mod policy; pub const TARGETLESS_TARGET_NAME: &str = "targetless"; @@ -353,53 +353,6 @@ pub struct CopyTargetStatus { pub creator_session: Session, } -/// Features and operations that can be blocked by a `MirrordPolicy`. -#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, JsonSchema)] -#[serde(rename_all = "kebab-case")] // StealWithoutFilter -> steal-without-filter in yaml. -pub enum BlockedFeature { - /// Blocks stealing traffic in any way (without or without filter). - Steal, - - /// Blocks stealing traffic without specifying (any) filter. Client can still specify a - /// filter that matches anything. - StealWithoutFilter, - - /// Blocks mirroring traffic. - Mirror, - - /// So that the operator is able to list all policies with [`kube::Api`], - /// even if it doesn't recognize blocked features used in some of them. - #[schemars(skip)] - #[serde(other, skip_serializing)] - Unknown, -} - -/// Custom resource for policies that limit what mirrord features users can use. -#[derive(CustomResource, Clone, Debug, Deserialize, Serialize, JsonSchema)] -#[kube( - // The operator group is handled by the operator, we want policies to be handled by k8s. - group = "policies.mirrord.metalbear.co", - version = "v1alpha", - kind = "MirrordPolicy", - namespaced -)] -#[serde(rename_all = "camelCase")] // target_path -> targetPath in yaml. -pub struct MirrordPolicySpec { - /// Specify the targets for which this policy applies, in the pod/my-pod deploy/my-deploy - /// notation. Targets can be matched using `*` and `?` where `?` matches exactly one - /// occurrence of any character and `*` matches arbitrary many (including zero) occurrences - /// of any character. If not specified, this policy does not depend on the target's path. - pub target_path: Option, - - /// If specified in a policy, the policy will only apply to targets with labels that match all - /// of the selector's rules. - pub selector: Option, - - // TODO: make the k8s list type be set/map to prevent duplicates. - /// List of features and operations blocked by this policy. - pub block: Vec, -} - /// Set where the application reads the name of the queue from, so that mirrord can find that queue, /// split it, and temporarily change the name there to the name of the branch queue when splitting. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, JsonSchema)] diff --git a/mirrord/operator/src/crd/policy.rs b/mirrord/operator/src/crd/policy.rs new file mode 100644 index 00000000000..4560055da07 --- /dev/null +++ b/mirrord/operator/src/crd/policy.rs @@ -0,0 +1,88 @@ +use kube::CustomResource; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use super::label_selector::LabelSelector; + +/// Features and operations that can be blocked by `mirrordpolicies` and `mirrordclusterpolicies`. +#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, JsonSchema)] +#[serde(rename_all = "kebab-case")] // StealWithoutFilter -> steal-without-filter in yaml. +pub enum BlockedFeature { + /// Blocks stealing traffic in any way (without or without filter). + Steal, + + /// Blocks stealing traffic without specifying (any) filter. Client can still specify a + /// filter that matches anything. + StealWithoutFilter, + + /// Blocks mirroring traffic. + Mirror, + + /// So that the operator is able to list all policies with [`kube::Api`], + /// even if it doesn't recognize blocked features used in some of them. + #[schemars(skip)] + #[serde(other, skip_serializing)] + Unknown, +} + +/// Custom resource for policies that limit what mirrord features users can use. +/// +/// This policy applies only to resources living in the same namespace. +#[derive(CustomResource, Clone, Debug, Deserialize, Serialize, JsonSchema)] +#[kube( + // The operator group is handled by the operator, we want policies to be handled by k8s. + group = "policies.mirrord.metalbear.co", + version = "v1alpha", + kind = "MirrordPolicy", + namespaced +)] +#[serde(rename_all = "camelCase")] // target_path -> targetPath in yaml. +pub struct MirrordPolicySpec { + /// Specify the targets for which this policy applies, in the pod/my-pod deploy/my-deploy + /// notation. Targets can be matched using `*` and `?` where `?` matches exactly one + /// occurrence of any character and `*` matches arbitrary many (including zero) occurrences + /// of any character. If not specified, this policy does not depend on the target's path. + pub target_path: Option, + + /// If specified in a policy, the policy will only apply to targets with labels that match all + /// of the selector's rules. + pub selector: Option, + + // TODO: make the k8s list type be set/map to prevent duplicates. + /// List of features and operations blocked by this policy. + pub block: Vec, +} + +/// Custom cluster-wide resource for policies that limit what mirrord features users can use. +/// +/// This policy applies to resources across all namespaces in the cluster. +#[derive(CustomResource, Clone, Debug, Deserialize, Serialize, JsonSchema)] +#[kube( + // The operator group is handled by the operator, we want policies to be handled by k8s. + group = "policies.mirrord.metalbear.co", + version = "v1alpha", + kind = "MirrordClusterPolicy" +)] +#[serde(rename_all = "camelCase")] // target_path -> targetPath in yaml. +pub struct MirrordClusterPolicySpec { + /// Specify the targets for which this policy applies, in the pod/my-pod deploy/my-deploy + /// notation. Targets can be matched using `*` and `?` where `?` matches exactly one + /// occurrence of any character and `*` matches arbitrary many (including zero) occurrences + /// of any character. If not specified, this policy does not depend on the target's path. + pub target_path: Option, + + /// If specified in a policy, the policy will only apply to targets with labels that match all + /// of the selector's rules. + pub selector: Option, + + // TODO: make the k8s list type be set/map to prevent duplicates. + /// List of features and operations blocked by this policy. + pub block: Vec, +} + +#[test] +fn check_one_api_group() { + use kube::Resource; + + assert_eq!(MirrordPolicy::group(&()), MirrordClusterPolicy::group(&()),) +} diff --git a/mirrord/operator/src/setup.rs b/mirrord/operator/src/setup.rs index d3e49a8853d..acd2c2d7540 100644 --- a/mirrord/operator/src/setup.rs +++ b/mirrord/operator/src/setup.rs @@ -28,7 +28,8 @@ use thiserror::Error; use crate::crd::{ kafka::{MirrordKafkaClientConfig, MirrordKafkaEphemeralTopic, MirrordKafkaTopicsConsumer}, - MirrordOperatorUser, MirrordPolicy, MirrordSqsSession, MirrordWorkloadQueueRegistry, TargetCrd, + policy::{MirrordClusterPolicy, MirrordPolicy}, + MirrordOperatorUser, MirrordSqsSession, MirrordWorkloadQueueRegistry, TargetCrd, }; pub static OPERATOR_NAME: &str = "mirrord-operator"; @@ -230,6 +231,9 @@ impl OperatorSetup for Operator { writer.write_all(b"---\n")?; MirrordPolicy::crd().to_writer(&mut writer)?; + writer.write_all(b"---\n")?; + MirrordClusterPolicy::crd().to_writer(&mut writer)?; + if self.sqs_splitting { writer.write_all(b"---\n")?; MirrordWorkloadQueueRegistry::crd().to_writer(&mut writer)?; @@ -562,8 +566,12 @@ impl OperatorClusterRole { }, // Allow the operator to list+get mirrord policies. PolicyRule { + // Both namespaced and cluster-wide policies live in the same API group. api_groups: Some(vec![MirrordPolicy::group(&()).into_owned()]), - resources: Some(vec![MirrordPolicy::plural(&()).into_owned()]), + resources: Some(vec![ + MirrordPolicy::plural(&()).into_owned(), + MirrordClusterPolicy::plural(&()).into_owned(), + ]), verbs: vec!["list".to_owned(), "get".to_owned()], ..Default::default() }, From c60f6780c1aca5681fde1587778e48397ac4ff67 Mon Sep 17 00:00:00 2001 From: Razz4780 Date: Tue, 10 Dec 2024 18:24:55 +0100 Subject: [PATCH 2/2] Doc and test fix --- mirrord/operator/src/crd.rs | 4 +++- tests/src/operator/policies.rs | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mirrord/operator/src/crd.rs b/mirrord/operator/src/crd.rs index bf103983ede..b6c3ddd334b 100644 --- a/mirrord/operator/src/crd.rs +++ b/mirrord/operator/src/crd.rs @@ -52,7 +52,9 @@ impl TargetCrd { /// # Warning /// /// Do **not** change url paths here, even if the operator recognizes the other format. - /// It can break exisiting [`MirrordPolicy`]s (see [`MirrordPolicySpec::target_path`]). + /// It can break exisiting [`policy::MirrordPolicy`]s and [`policy::MirrordClusterPolicy`] + /// (see [`policy::MirrordPolicySpec::target_path`] and + /// [`policy::MirrordClusterPolicySpec::target_path`]). pub fn urlfied_name(target: &Target) -> String { let (type_name, target, container) = match target { Target::Deployment(target) => ("deploy", &target.deployment, &target.container), diff --git a/tests/src/operator/policies.rs b/tests/src/operator/policies.rs index fd59a500383..215bdc0e455 100644 --- a/tests/src/operator/policies.rs +++ b/tests/src/operator/policies.rs @@ -6,7 +6,8 @@ use std::{collections::BTreeMap, time::Duration}; use kube::Api; use mirrord_operator::crd::{ - label_selector::LabelSelector, BlockedFeature, MirrordPolicy, MirrordPolicySpec, + label_selector::LabelSelector, + policy::{BlockedFeature, MirrordPolicy, MirrordPolicySpec}, }; use rstest::{fixture, rstest};