# generated by datamodel-codegen:
#   filename:  service_component.json
#   timestamp: 2022-08-10T08:48:28+00:00

from __future__ import annotations

from enum import Enum
from typing import Any, Dict, List, Optional, Union

from pydantic import BaseModel, Field, conint, constr


class DockerFileBuild(BaseModel):
    """
        +label=Docker File
    +usage=Deploy a project with Dockerfile
    +icon=fa-brands fa-docker:#0db7ed
    """

    type: constr(regex=r"dockerfile")
    dockerfile_path: str = Field(
        "./Dockerfile",
        description="+label=Path to Dockerfile\n+usage=The file path of the Dockerfile relative to project root path.",
    )
    build_context_path: str = Field(
        "./",
        description="+label=Path to build context\n+usage=Build context path for the Dockerfile relative to project root path.",
    )


class Env(BaseModel):
    name: str = Field(..., description="+usage=Env variable name.")
    value: str = Field(..., description="+usage=The value of the environment variable.")


class GithubSource(BaseModel):
    """
        +label=Github
    +icon=fa-brands fa-github:black
    """

    type: constr(regex=r"github")
    repo_url: str = Field(
        ..., description="+label=Repo URL\n+usage=The repository URL."
    )
    ref: str = Field(
        ...,
        description="+label=Commit SHA\n+usage=The commit sha, branch name or the tag.",
    )


class HttpProbe(BaseModel):
    """
    +usage=Instructions for assessing container health by executing an HTTP GET request.
    """

    type: constr(regex=r"http")
    path: str = Field(
        ...,
        description="+usage=The endpoint, relative to the port, to which the HTTP GET request should be directed.",
    )
    port: conint(ge=0, le=65535) = Field(
        ...,
        description="+usage=The TCP socket within the container to which the HTTP GET request should be directed.",
    )
    host: Optional[str] = None
    scheme: str = "http"


class Image(BaseModel):
    """
        +label=Docker Image
    +usage=Deploy from an image
    +icon=fa-brands fa-docker:#0db7ed
    """

    docker_registry: Optional[str] = Field(
        None,
        description="+usage=FQN of the container registry. If you can't find your registry here,\nadd it through the `Settings` page",
    )
    image_uri: str = Field(
        ...,
        description="+label=Image URI\n+usage=The image URI. Specify the name of the image and the tag. By default,\nthe image is pulled from DockerHub. If you're using a different registry, specify\nthat using `docker_registry` field.",
    )


class LocalSource(BaseModel):
    """
        +label=Local
    +icon=fa-folder:black
    """

    type: constr(regex=r"local")
    project_root_path: str = Field("./", description="+usage=Local project root path.")


class Protocol(Enum):
    """
    +usage=Protocol for the port.
    """

    TCP = "TCP"
    UDP = "UDP"


class Port(BaseModel):
    protocol: Protocol = Field("TCP", description="+usage=Protocol for the port.")
    port: conint(ge=0, le=65535) = Field(
        80, description="+usage=Port number to expose."
    )
    expose: bool = Field(False, description="+usage=Expose the port")


class RemoteSource(BaseModel):
    """
        +label=S3
    +icon=fa-brands fa-aws:black
    """

    type: constr(regex=r"remote")
    remote_uri: str = Field(..., description="+label=Remote URI")


class GpuLimitEnum(Enum):
    int_0 = 0


class GpuVendor(Enum):
    """
        +label=GPU Vendor
    +usage=GPU vendor. Defaults to "nvidia"
    """

    nvidia = "nvidia"
    amd = "amd"


class Resources(BaseModel):
    """
        +icon=fa-microchip
    +label=Resources to allocate to your service
    """

    cpu_request: str = Field(
        "200m",
        description="+label=CPU Request\n+usage=CPU units request for the component. The value can be float like `1.0`, `0.5`\nor you can express it in milli units like `50m` which is equal to 0.05 units.",
    )
    cpu_limit: str = Field(
        "200m",
        description="+label=CPU Limit\n+usage=CPU unit limit for the component. The value can be float like `1.0`, `0.5`\nor you can express it in milli units like `50m` which is equal to 0.05 units.",
    )
    memory_request: str = Field(
        "256Mi",
        description="+label=Memory Request\n+usage=Memory units request for the component. It can be a plain integer or as a fixed-point number followed\nby a quantity as suffix like `E`, `P`, `T`, `G`, `M`, `k` or their power-of-two equivalents: `Ei`, `Pi`, `Ti`, `Gi`, `Mi`, `Ki`",
    )
    memory_limit: str = Field(
        "256Mi",
        description="+label=Memory Limit\n+usage=Memory units limit for the component. It can be a plain integer or as a fixed-point number followed\nby a quantity as suffix like `E`, `P`, `T`, `G`, `M`, `k` or their power-of-two equivalents: `Ei`, `Pi`, `Ti`, `Gi`, `Mi`, `Ki`",
    )
    gpu_limit: Union[GpuLimitEnum, Any] = Field(
        0,
        description="+label=GPU Limit\n+usage=GPU limit for the component. It can be a plain integer.",
    )
    gpu_vendor: GpuVendor = Field(
        "nvidia",
        description='+label=GPU Vendor\n+usage=GPU vendor. Defaults to "nvidia"',
    )


class TfyPythonBuild(BaseModel):
    """
        +label=Python Buildpack
    +usage=Build using Buildpack
    +icon=fa-brands fa-python:#306998
    """

    type: constr(regex=r"tfy-python-buildpack")
    python_version: constr(regex=r"^\d+(\.\d+){1,2}$") = Field(
        "3.9",
        description="+label=Python version\n+usage=Python version to run your application.",
    )
    build_context_path: str = Field(
        "./",
        description="+label=Path to build context\n+usage=Build path relative to project root path.",
    )
    requirements_path: Optional[str] = Field(
        None,
        description="+label=Path to requirements\n+usage=Path to `requirements.txt` relative to\n`Path to build context`",
    )
    pip_packages: Optional[List[str]] = Field(
        None,
        description="+label=Define pip package requirements\n+usage=Define pip package requirements.",
    )
    command: Union[str, List[str]] = Field(
        ...,
        description="+label=Entrypoint override\n+usage=Override the command to run when the container starts.\nCommand will be set as the Entrypoint of the generated\nimage.",
    )


class Build(BaseModel):
    """
        +label=Source Code
    +usage=Deploy from source code
    +icon=fa-code
    """

    build_source: Union[RemoteSource, GithubSource, LocalSource] = Field(
        ...,
        description="+label=Get source code from...\n+usage=Choose where to fetch source code to build and deploy\n+icon=fa-code",
    )
    build_spec: Union[DockerFileBuild, TfyPythonBuild] = Field(
        ...,
        description="+label=Build using...\n+usage=If you have a Dockerfile, use `Docker File` build option.\n+icon=fa-wrench",
    )


class HealthProbe(BaseModel):
    """
    +icon=fa-heart
    """

    config: HttpProbe
    initial_delay_seconds: conint(ge=0) = Field(
        0,
        description="+usage=Number of seconds after the container is started before the first probe is initiated.",
    )
    period_seconds: conint(ge=0) = Field(
        10, description="+usage=How often, in seconds, to execute the probe."
    )
    timeout_seconds: conint(ge=0) = Field(
        1, description="+usage=Number of seconds after which the probe times out."
    )
    success_threshold: conint(ge=0) = Field(
        1,
        description="+usage=Minimum consecutive successes for the probe to be considered successful after having failed.",
    )
    failure_threshold: conint(ge=0) = Field(
        3,
        description="+usage=Number of consecutive failures required to determine the container is not alive (liveness probe) or not ready (readiness probe).",
    )


class Service(BaseModel):
    type: constr(regex=r"service")
    image: Union[Image, Build] = Field(
        ...,
        description="+label=Deploy from...\n+usage=You can either deploy a Docker image or build and deploy from source code\n+icon=fa-solid fa-cloud-arrow-up:#21B6A8",
    )
    resources: Resources
    replicas: conint(ge=1, lt=5) = Field(
        1,
        description="+label=Replicas\n+usage=Number of service instances/replicas you want to run.\n+icon=fa-clone",
    )
    command: Optional[List[str]] = Field(
        None,
        description="+label=Command\n+usage=Override the `Entrypoint` command.\n+icon=fa-terminal",
    )
    env: Optional[List[Env]] = Field(
        None,
        description="+label=Environment Variables\n+usage=Configure environment variables to be injected in the service.\n+icon=fa-globe",
    )
    ports: List[Port] = Field(
        ..., description="+usage=Ports to route customer traffic to\n+icon=fa-plug"
    )
    liveness_probe: Optional[HealthProbe] = None
    readiness_probe: Optional[HealthProbe] = None
    labels: Optional[Dict[str, str]] = Field(
        None, description="+usage=Specify the labels in the workload"
    )
