# Network Schema - Network configurations for provisioning
# Version: 1.0.0

{
  # IPAM (IP Address Management) configuration
  IpamConfig = {
    subnet
      | String
      | doc "Subnet in CIDR notation (e.g., '172.28.0.0/16')"
      | {
        label = "valid subnet",
        predicate = fun s =>
          std.string.is_match "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$" s
      },

    gateway
      | String
      | doc "Gateway IP address (e.g., '172.28.0.1')"
      | {
        label = "valid IP",
        predicate = fun s =>
          std.string.is_match "^([0-9]{1,3}\\.){3}[0-9]{1,3}$" s
      }
      | optional,

    ip_range
      | String
      | doc "IP range in CIDR notation"
      | {
        label = "valid IP range",
        predicate = fun s =>
          std.string.is_match "^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$" s
      }
      | optional,

    aux_addresses
      | {_: String}
      | doc "Auxiliary IPv4 or IPv6 addresses"
      | default = {},
  },

  # Docker network configuration
  DockerNetwork = {
    name
      | String
      | doc "Network name"
      | {
        label = "valid network name",
        predicate = fun s =>
          std.string.is_match "^[a-z0-9-]+$" s &&
          std.string.length s >= 1 && std.string.length s <= 64
      },

    driver
      | [| 'bridge, 'host, 'overlay, 'macvlan, 'none |]
      | doc "Network driver type"
      | default = 'bridge,

    driver_opts
      | {_: String}
      | doc "Driver-specific options"
      | default = {},

    ipam
      | {
        driver
          | String
          | doc "IPAM driver name"
          | default = "default",

        config
          | Array IpamConfig
          | doc "IPAM configuration"
          | default = [],
      }
      | doc "IP Address Management configuration"
      | optional,

    internal
      | Bool
      | doc "Restrict external access to network"
      | default = false,

    attachable
      | Bool
      | doc "Enable manual container attachment"
      | default = false,

    enable_ipv6
      | Bool
      | doc "Enable IPv6 networking"
      | default = false,

    labels
      | {_: String}
      | doc "Network labels for metadata"
      | default = {},
  },

  # Kubernetes network policy
  NetworkPolicyPort = {
    port
      | Number
      | doc "Port number"
      | {
        label = "valid port",
        predicate = fun p => p >= 1 && p <= 65535
      },

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

  NetworkPolicyPeer = {
    pod_selector
      | {
        matchLabels
          | {_: String}
          | doc "Label selector for pods"
          | optional,

        matchExpressions
          | Array {
            key | String,
            operator | [| 'In, 'NotIn, 'Exists, 'DoesNotExist |],
            values | Array String | optional,
          }
          | doc "Label selector expressions"
          | optional,
      }
      | doc "Pod selector"
      | optional,

    namespace_selector
      | {
        matchLabels
          | {_: String}
          | doc "Label selector for namespaces"
          | optional,
      }
      | doc "Namespace selector"
      | optional,

    ip_block
      | {
        cidr
          | String
          | doc "CIDR block (e.g., '172.17.0.0/16')",

        except
          | Array String
          | doc "Exceptions to the CIDR block"
          | default = [],
      }
      | doc "IP block selector"
      | optional,
  },

  NetworkPolicyIngressRule = {
    from
      | Array NetworkPolicyPeer
      | doc "Sources from which traffic is allowed"
      | default = [],

    ports
      | Array NetworkPolicyPort
      | doc "Ports on which traffic is allowed"
      | default = [],
  },

  NetworkPolicyEgressRule = {
    to
      | Array NetworkPolicyPeer
      | doc "Destinations to which traffic is allowed"
      | default = [],

    ports
      | Array NetworkPolicyPort
      | doc "Ports on which traffic is allowed"
      | default = [],
  },

  KubernetesNetworkPolicy = {
    name
      | String
      | doc "Network policy name"
      | {
        label = "valid name",
        predicate = fun s =>
          std.string.is_match "^[a-z0-9-]+$" s &&
          std.string.length s >= 1 && std.string.length s <= 64
      },

    pod_selector
      | {
        matchLabels
          | {_: String}
          | doc "Label selector for pods"
      }
      | doc "Selector for pods to which this policy applies",

    policy_types
      | Array ([| 'Ingress, 'Egress |])
      | doc "Types of traffic this policy affects"
      | default = ['Ingress],

    ingress
      | Array NetworkPolicyIngressRule
      | doc "Ingress rules"
      | default = [],

    egress
      | Array NetworkPolicyEgressRule
      | doc "Egress rules"
      | default = [],
  },

  # Main network configuration
  NetworkConfig = {
    docker_networks
      | {_: DockerNetwork}
      | doc "Docker networks definition"
      | default = {},

    kubernetes_policies
      | Array KubernetesNetworkPolicy
      | doc "Kubernetes network policies"
      | default = [],

    dns_servers
      | Array String
      | doc "Custom DNS servers"
      | default = [],

    dns_search
      | Array String
      | doc "DNS search domains"
      | default = [],
  },
}
