# Info: KCL Upcloud provider defaults schemas for provisioning (Provisioning)
# Author: JesusPerezLorenzo
# Release: 0.0.4
# Date: 15-12-2023
import regex
import provisioning.lib as lib
import provisioning.defaults as defaults

schema Storage_backup_upcloud:
    """
    Upcloud storage backup
    """
    #The time when to create a backup in HH:MM. Empty value means no backups.
    time: str
    # The interval of the backup. Available: daily,mon,tue,wed,thu,fri,sat,sun Default: daily
    interval: "daily" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun" = "daily"
    # How long to store the backups in days. The accepted range is 1-1095 Default: 7
    retention: int = 7

    check:
        (retention) > 0 and (retention) <= 1095, "Retention greater range 1-1095"

schema Storage_upcloud(lib.Storage):
    """
    Upcloud storage settings
    """
    volname: str = ""

    # The volume type. This parameter can be one of the following values:
    # - General Purpose SSD: gp2 | gp3
    # - Provisioned IOPS SSD: io1 | io2
    # - Throughput Optimized HDD: st1
    # - Cold HDD: sc1
    # - Magnetic: standard
    # - Warning:  Throughput Optimized HDD (st1 ) and Cold HDD (sc1 ) volumes can't be used as boot volumes.
    voltype: "maxiops" | "hdd" | "custom" = "maxiops"
    labels: str = ""
    encrypt: bool = False
    backup?: Storage_backup_upcloud

schema ServerDefaults_upcloud(defaults.ServerDefaults):
    """
    Upcloud Server Defaults settings
    """
    provider: "upcloud" = "upcloud"
    # UpCloud provision data settings
    prov_settings: str = "defs/upcloud_settings.k"
    # UpCloud provision data settings clean
    prov_settings_clean: bool = False
    not_use: bool = False
    time_zone: str = "UTC"
    zone: "de-fra1" | "es-mad1" = "es-mad1"
    # UpCloud Plan name, for plans list = "upctl server plans" or use 'custom --cores 2 --memory 4096
    plan: "DEV-1xCPU-1GB-10GB" | "DEV-1xCPU-1GB" | "DEV-1xCPU-2GB" | "DEV-1xCPU-4GB" | "DEV-2xCPU-4GB" | "DEV-2xCPU-8GB" | "DEV-2xCPU-16GB" | "CLOUDNATIVE-1xCPU-4GB" | "CLOUDNATIVE-1xCPU-8GB" | "CLOUDNATIVE-2xCPU-4GB" | "CLOUDNATIVE-2xCPU-8GB" | "1xCPU-1GB" | "1xCPU-2GB" | "2xCPU-2GB" | "2xCPU-4GB" | "4xCPU-8GB" = "1xCPU-2GB"

    # If 'storage_os: find'  storage_os_find will be used to find one in zone (region)
    # expected something like: "name=debian-12 | arch=x86_64" or "name: debian-12 | arch: x86_64"  will be parsed to find latest available
    storage_os_find: str = "name: debian-13 | arch: x86_64"

    #storage_os: find
    # Ubuntu Server 24.04 LTS (Noble Numbat) 01000000-0000-4000-8000-000030240200
    # Debian GNU/Linux 13 (Trixie) 01000000-0000-4000-8000-000020080100
    storage_os: "01000000-0000-4000-8000-000020070100" | "01000000-0000-4000-8000-000030240200" | "01000000-0000-4000-8000-000020080100" = "01000000-0000-4000-8000-000020080100"

    #storage_os: ami-0eb11ab33f229b26c
    # If not Storage size, Plan Storage size will be used
    #storage_size: int
    storages?: [Storage_upcloud]
    #UUID of a server group for the server
    group_id?: str
    # Simple backup rule. Format (HHMM,{dailies,weeklies,monthlies}). Example: 2300,dailies
    backup?: str
    # Add one or more SSH keys to the admin account. Accepted values are SSH public keys or filenames from
    # where to read the keys.
    # ssh public key to be included in /root/.ssh/authorized_keys
    ssh_key_path?: str
    # Public certificate must be created or imported as a key_name
    # use: providers/aws/bin/on-ssh.sh (add -h to get info)
    ssh_key_name?: str
    # To use private network, IPs will be set in servers items
    priv_cidr_block?: str
    # ssh_key_mode: rewrite
    # AWS do not use utility network, if no value it will not be set and utility IP will not be set
    # public network, if no value it will not be set and public IP will not be set
    #network_utility_ipv4: bool = True
    #network_utility_ipv6: bool = False
    #network_public_ipv4?: bool = True
    #network_public_ipv6?: bool = False
    #TODO settings for Elastic IPs or instace without pubic IP
    # To use private network a VPC + Subnet + NetworkInfterface has to be created, IPs will be set in servers items
    # In AWS this is only a name
    network_private_name?: str
    liveness_ip?: str
    liveness_port: int = 22

    # Labels to describe the server in `key: value` format, multiple can be declared.
    # Usage: env: dev
    labels: str = "{Key=cluster,Value=k8s}"
    user: str = "root"

    check:
        len(user) > 0, "Check user value"
        priv_cidr_block == Undefined or regex.match(priv_cidr_block, "^(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}\/(?:3[0-2]|[0-2]?[0-9])$"), "'priv_cidr_block = ${priv_cidr_block}' check value definition"
        liveness_ip == Undefined or regex.match(liveness_ip, "^{{.*}}$") or regex.match(liveness_ip, "^((25[0-5]|2[0-4][0-9]|[0-1]?[0-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|[0-1]?[0-9]?[0-9])$"), "'liveness_ip = ${liveness_ip}' check value definition (use {{variable}} or xx.xx.xx.xx)"

