# Network Validator - Network configuration validation
# Version: 1.0.0
#
# Validates network, IPAM, and network policy configurations

let Common = import "common-validator.ncl" in

{
  # Validate network name
  validate_network_name = fun name =>
    Common.validate_pattern "^[a-z0-9-]+$" name &&
    Common.validate_string_length 1 64 name,

  # Validate network driver
  validate_network_driver = fun driver =>
    Common.validate_one_of ['bridge, 'host, 'overlay, 'macvlan, 'none] driver,

  # Validate CIDR notation
  validate_cidr = fun cidr =>
    Common.validate_cidr cidr,

  # Validate IP address
  validate_ip = fun ip =>
    Common.validate_ipv4 ip,

  # IPAM configuration validation
  validate_ipam_config = {
    subnet
      | String
      | {
        label = "valid subnet",
        predicate = validate_cidr
      },

    gateway
      | String
      | {
        label = "valid IP",
        predicate = validate_ip
      }
      | optional,

    ip_range
      | String
      | {
        label = "valid IP range",
        predicate = validate_cidr
      }
      | optional,

    aux_addresses
      | {_: String}
      | default = {},
  },

  # Docker network validation
  validate_docker_network = {
    name
      | String
      | {
        label = "valid network name",
        predicate = validate_network_name
      },

    driver
      | {
        label = "valid driver",
        predicate = validate_network_driver
      }
      | default = 'bridge,

    driver_opts
      | {_: String}
      | default = {},

    ipam
      | {
        driver | String | default = "default",
        config | Array validate_ipam_config | default = [],
      }
      | optional,

    internal | Bool | default = false,

    attachable | Bool | default = false,

    enable_ipv6 | Bool | default = false,

    labels
      | {_: String}
      | default = {},
  },

  # Network policy port validation
  validate_network_policy_port = {
    port
      | Number
      | {
        label = "valid port",
        predicate = Common.validate_port
      },

    protocol
      | [| 'TCP, 'UDP, 'SCTP |]
      | default = 'TCP,
  },

  # Network policy peer validation
  validate_network_policy_peer = {
    pod_selector
      | {
        matchLabels | {_: String} | optional,
        matchExpressions | Array {
          key | String,
          operator | [| 'In, 'NotIn, 'Exists, 'DoesNotExist |],
          values | Array String | optional,
        } | optional,
      }
      | optional,

    namespace_selector
      | {
        matchLabels | {_: String} | optional,
      }
      | optional,

    ip_block
      | {
        cidr
          | String
          | {
            label = "valid CIDR",
            predicate = validate_cidr
          },
        except | Array String | default = [],
      }
      | optional,
  },

  # Network policy ingress rule validation
  validate_ingress_rule = {
    from
      | Array validate_network_policy_peer
      | default = [],

    ports
      | Array validate_network_policy_port
      | default = [],
  },

  # Network policy egress rule validation
  validate_egress_rule = {
    to
      | Array validate_network_policy_peer
      | default = [],

    ports
      | Array validate_network_policy_port
      | default = [],
  },

  # Kubernetes network policy validation
  validate_k8s_network_policy = {
    name
      | String
      | {
        label = "valid name",
        predicate = Common.validate_k8s_name
      },

    pod_selector
      | {
        matchLabels | {_: String}
      },

    policy_types
      | Array ([| 'Ingress, 'Egress |])
      | default = ['Ingress],

    ingress
      | Array validate_ingress_rule
      | default = [],

    egress
      | Array validate_egress_rule
      | default = [],
  },

  # Complete network configuration validation
  validate_network_config = {
    docker_networks
      | {_: validate_docker_network}
      | default = {},

    kubernetes_policies
      | Array validate_k8s_network_policy
      | default = [],

    dns_servers
      | Array String
      | default = [],

    dns_search
      | Array String
      | default = [],
  },
}
