use crate::prelude::*;

// WARNING: generated by kopium - manual changes will be overwritten
// kopium command: kopium -f /home/mmoreiradj/git/crd-rs/crds/cilium/v2/ciliumlocalredirectpolicies.yaml --schema=derived -d --hide-prelude
// kopium version: 0.22.5

/// Spec is the desired behavior of the local redirect policy.
#[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema)]
#[kube(
    group = "cilium.io",
    version = "v2",
    kind = "CiliumLocalRedirectPolicy",
    plural = "ciliumlocalredirectpolicies"
)]
#[kube(namespaced)]
#[kube(status = "CiliumLocalRedirectPolicyStatus")]
pub struct CiliumLocalRedirectPolicySpec {
    /// Description can be used by the creator of the policy to describe the
    /// purpose of this policy.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    /// RedirectBackend specifies backend configuration to redirect traffic to.
    /// It can not be empty.
    #[serde(rename = "redirectBackend")]
    pub redirect_backend: CiliumLocalRedirectPolicyRedirectBackend,
    /// RedirectFrontend specifies frontend configuration to redirect traffic from.
    /// It can not be empty.
    #[serde(rename = "redirectFrontend")]
    pub redirect_frontend: CiliumLocalRedirectPolicyRedirectFrontend,
    /// SkipRedirectFromBackend indicates whether traffic matching RedirectFrontend
    /// from RedirectBackend should skip redirection, and hence the traffic will
    /// be forwarded as-is.
    ///
    /// The default is false which means traffic matching RedirectFrontend will
    /// get redirected from all pods, including the RedirectBackend(s).
    ///
    /// Example: If RedirectFrontend is configured to "169.254.169.254:80" as the traffic
    /// that needs to be redirected to backends selected by RedirectBackend, if
    /// SkipRedirectFromBackend is set to true, traffic going to "169.254.169.254:80"
    /// from such backends will not be redirected back to the backends. Instead,
    /// the matched traffic from the backends will be forwarded to the original
    /// destination "169.254.169.254:80".
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "skipRedirectFromBackend"
    )]
    pub skip_redirect_from_backend: Option<bool>,
}

/// RedirectBackend specifies backend configuration to redirect traffic to.
/// It can not be empty.
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub struct CiliumLocalRedirectPolicyRedirectBackend {
    /// LocalEndpointSelector selects node local pod(s) where traffic is redirected to.
    #[serde(rename = "localEndpointSelector")]
    pub local_endpoint_selector: CiliumLocalRedirectPolicyRedirectBackendLocalEndpointSelector,
    /// ToPorts is a list of L4 ports with protocol of node local pod(s) where traffic
    /// is redirected to.
    /// When multiple ports are specified, the ports must be named.
    #[serde(rename = "toPorts")]
    pub to_ports: Vec<CiliumLocalRedirectPolicyRedirectBackendToPorts>,
}

/// LocalEndpointSelector selects node local pod(s) where traffic is redirected to.
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub struct CiliumLocalRedirectPolicyRedirectBackendLocalEndpointSelector {
    /// matchExpressions is a list of label selector requirements. The requirements are ANDed.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "matchExpressions"
    )]
    pub match_expressions:
        Option<Vec<CiliumLocalRedirectPolicyRedirectBackendLocalEndpointSelectorMatchExpressions>>,
    /// matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
    /// map is equivalent to an element of matchExpressions, whose key field is "key", the
    /// operator is "In", and the values array contains only "value". The requirements are ANDed.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "matchLabels"
    )]
    pub match_labels: Option<BTreeMap<String, String>>,
}

/// A label selector requirement is a selector that contains values, a key, and an operator that
/// relates the key and values.
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub struct CiliumLocalRedirectPolicyRedirectBackendLocalEndpointSelectorMatchExpressions {
    /// key is the label key that the selector applies to.
    pub key: String,
    /// operator represents a key's relationship to a set of values.
    /// Valid operators are In, NotIn, Exists and DoesNotExist.
    pub operator:
        CiliumLocalRedirectPolicyRedirectBackendLocalEndpointSelectorMatchExpressionsOperator,
    /// values is an array of string values. If the operator is In or NotIn,
    /// the values array must be non-empty. If the operator is Exists or DoesNotExist,
    /// the values array must be empty. This array is replaced during a strategic
    /// merge patch.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub values: Option<Vec<String>>,
}

/// A label selector requirement is a selector that contains values, a key, and an operator that
/// relates the key and values.
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub enum CiliumLocalRedirectPolicyRedirectBackendLocalEndpointSelectorMatchExpressionsOperator {
    In,
    NotIn,
    Exists,
    DoesNotExist,
}

/// PortInfo specifies L4 port number and name along with the transport protocol
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub struct CiliumLocalRedirectPolicyRedirectBackendToPorts {
    /// Name is a port name, which must contain at least one [a-z],
    /// and may also contain [0-9] and '-' anywhere except adjacent to another
    /// '-' or in the beginning or the end.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// Port is an L4 port number. The string will be strictly parsed as a single uint16.
    pub port: String,
    /// Protocol is the L4 protocol.
    /// Accepted values: "TCP", "UDP"
    pub protocol: CiliumLocalRedirectPolicyRedirectBackendToPortsProtocol,
}

/// PortInfo specifies L4 port number and name along with the transport protocol
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub enum CiliumLocalRedirectPolicyRedirectBackendToPortsProtocol {
    #[serde(rename = "TCP")]
    Tcp,
    #[serde(rename = "UDP")]
    Udp,
}

/// RedirectFrontend specifies frontend configuration to redirect traffic from.
/// It can not be empty.
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub struct CiliumLocalRedirectPolicyRedirectFrontend {
    /// AddressMatcher is a tuple {IP, port, protocol} that matches traffic to be
    /// redirected.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "addressMatcher"
    )]
    pub address_matcher: Option<CiliumLocalRedirectPolicyRedirectFrontendAddressMatcher>,
    /// ServiceMatcher specifies Kubernetes service and port that matches
    /// traffic to be redirected.
    #[serde(
        default,
        skip_serializing_if = "Option::is_none",
        rename = "serviceMatcher"
    )]
    pub service_matcher: Option<CiliumLocalRedirectPolicyRedirectFrontendServiceMatcher>,
}

/// AddressMatcher is a tuple {IP, port, protocol} that matches traffic to be
/// redirected.
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub struct CiliumLocalRedirectPolicyRedirectFrontendAddressMatcher {
    /// IP is a destination ip address for traffic to be redirected.
    ///
    /// Example:
    /// When it is set to "169.254.169.254", traffic destined to
    /// "169.254.169.254" is redirected.
    pub ip: String,
    /// ToPorts is a list of destination L4 ports with protocol for traffic
    /// to be redirected.
    /// When multiple ports are specified, the ports must be named.
    ///
    /// Example:
    /// When set to Port: "53" and Protocol: UDP, traffic destined to port '53'
    /// with UDP protocol is redirected.
    #[serde(rename = "toPorts")]
    pub to_ports: Vec<CiliumLocalRedirectPolicyRedirectFrontendAddressMatcherToPorts>,
}

/// PortInfo specifies L4 port number and name along with the transport protocol
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub struct CiliumLocalRedirectPolicyRedirectFrontendAddressMatcherToPorts {
    /// Name is a port name, which must contain at least one [a-z],
    /// and may also contain [0-9] and '-' anywhere except adjacent to another
    /// '-' or in the beginning or the end.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// Port is an L4 port number. The string will be strictly parsed as a single uint16.
    pub port: String,
    /// Protocol is the L4 protocol.
    /// Accepted values: "TCP", "UDP"
    pub protocol: CiliumLocalRedirectPolicyRedirectFrontendAddressMatcherToPortsProtocol,
}

/// PortInfo specifies L4 port number and name along with the transport protocol
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub enum CiliumLocalRedirectPolicyRedirectFrontendAddressMatcherToPortsProtocol {
    #[serde(rename = "TCP")]
    Tcp,
    #[serde(rename = "UDP")]
    Udp,
}

/// ServiceMatcher specifies Kubernetes service and port that matches
/// traffic to be redirected.
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub struct CiliumLocalRedirectPolicyRedirectFrontendServiceMatcher {
    /// Namespace is the Kubernetes service namespace.
    /// The service namespace must match the namespace of the parent Local
    /// Redirect Policy.  For Cluster-wide Local Redirect Policy, this
    /// can be any namespace.
    pub namespace: String,
    /// Name is the name of a destination Kubernetes service that identifies traffic
    /// to be redirected.
    /// The service type needs to be ClusterIP.
    ///
    /// Example:
    /// When this field is populated with 'serviceName:myService', all the traffic
    /// destined to the cluster IP of this service at the (specified)
    /// service port(s) will be redirected.
    #[serde(rename = "serviceName")]
    pub service_name: String,
    /// ToPorts is a list of destination service L4 ports with protocol for
    /// traffic to be redirected. If not specified, traffic for all the service
    /// ports will be redirected.
    /// When multiple ports are specified, the ports must be named.
    #[serde(default, skip_serializing_if = "Option::is_none", rename = "toPorts")]
    pub to_ports: Option<Vec<CiliumLocalRedirectPolicyRedirectFrontendServiceMatcherToPorts>>,
}

/// PortInfo specifies L4 port number and name along with the transport protocol
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub struct CiliumLocalRedirectPolicyRedirectFrontendServiceMatcherToPorts {
    /// Name is a port name, which must contain at least one [a-z],
    /// and may also contain [0-9] and '-' anywhere except adjacent to another
    /// '-' or in the beginning or the end.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    /// Port is an L4 port number. The string will be strictly parsed as a single uint16.
    pub port: String,
    /// Protocol is the L4 protocol.
    /// Accepted values: "TCP", "UDP"
    pub protocol: CiliumLocalRedirectPolicyRedirectFrontendServiceMatcherToPortsProtocol,
}

/// PortInfo specifies L4 port number and name along with the transport protocol
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub enum CiliumLocalRedirectPolicyRedirectFrontendServiceMatcherToPortsProtocol {
    #[serde(rename = "TCP")]
    Tcp,
    #[serde(rename = "UDP")]
    Udp,
}

/// Status is the most recent status of the local redirect policy.
/// It is a read-only field.
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)]
pub struct CiliumLocalRedirectPolicyStatus {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub ok: Option<bool>,
}
