From 6549a4f7ffd03d555d2ac661ff7c963863fd1d59 Mon Sep 17 00:00:00 2001 From: Gabriel de Marmiesse Date: Wed, 12 Jul 2023 11:52:08 +0200 Subject: [PATCH] Add explicit optional on all models (#454) --- .../components/buildx/imagetools/models.py | 12 +- python_on_whales/components/compose/models.py | 132 ++--- python_on_whales/components/config/models.py | 22 +- .../components/container/models.py | 454 +++++++++--------- python_on_whales/components/context/models.py | 20 +- python_on_whales/components/image/models.py | 62 +-- .../components/manifest/models.py | 10 +- python_on_whales/components/network/models.py | 48 +- python_on_whales/components/node/models.py | 72 +-- python_on_whales/components/plugin/models.py | 34 +- python_on_whales/components/secret/models.py | 11 +- python_on_whales/components/service/models.py | 96 ++-- python_on_whales/components/system/models.py | 281 +++++------ python_on_whales/components/task/models.py | 184 +++---- python_on_whales/components/volume/models.py | 18 +- python_on_whales/utils.py | 15 +- .../buildx/test_buildx_cli_wrapper.py | 4 +- 17 files changed, 745 insertions(+), 730 deletions(-) diff --git a/python_on_whales/components/buildx/imagetools/models.py b/python_on_whales/components/buildx/imagetools/models.py index 52c6a819..14df659e 100644 --- a/python_on_whales/components/buildx/imagetools/models.py +++ b/python_on_whales/components/buildx/imagetools/models.py @@ -12,7 +12,7 @@ class ManifestConfig(pydantic.BaseModel): class ManifestLayer(pydantic.BaseModel): - media_type: str = pydantic.Field(alias="mediaType") + media_type: Optional[str] = pydantic.Field(alias="mediaType") digest: Optional[str] size: Optional[int] @@ -25,15 +25,15 @@ class ManifestPlatform(pydantic.BaseModel): class ImageVariantManifest(pydantic.BaseModel): - media_type: str = pydantic.Field(alias="mediaType") - size: int - digest: str + media_type: Optional[str] = pydantic.Field(alias="mediaType") + size: Optional[int] + digest: Optional[str] platform: Optional[ManifestPlatform] class Manifest(pydantic.BaseModel): - media_type: str = pydantic.Field(alias="mediaType") - schema_version: int = pydantic.Field(alias="schemaVersion") + media_type: Optional[str] = pydantic.Field(alias="mediaType") + schema_version: Optional[int] = pydantic.Field(alias="schemaVersion") layers: Optional[List[ManifestLayer]] manifests: Optional[List[ImageVariantManifest]] config: Optional[ManifestConfig] diff --git a/python_on_whales/components/compose/models.py b/python_on_whales/components/compose/models.py index c2358784..548e0717 100644 --- a/python_on_whales/components/compose/models.py +++ b/python_on_whales/components/compose/models.py @@ -8,124 +8,124 @@ @all_fields_optional class ServicePlacement(BaseModel): - constraints: List[str] + constraints: Optional[List[str]] = None @all_fields_optional class ResourcesLimits(BaseModel): - cpus: float - memory: int + cpus: Optional[float] + memory: Optional[int] @all_fields_optional class ResourcesReservation(BaseModel): - cpus: Union[float, str] - memory: int + cpus: Union[float, str, None] + memory: Optional[int] @all_fields_optional class ServiceResources(BaseModel): - limits: ResourcesLimits - reservations: ResourcesReservation + limits: Optional[ResourcesLimits] + reservations: Optional[ResourcesReservation] @all_fields_optional class ServiceDeployConfig(BaseModel): - labels: Dict[str, str] - resources: ServiceResources - placement: ServicePlacement - replicas: int + labels: Optional[Dict[str, str]] + resources: Optional[ServiceResources] + placement: Optional[ServicePlacement] + replicas: Optional[int] @all_fields_optional class DependencyCondition(BaseModel): - condition: str + condition: Optional[str] @all_fields_optional class ComposeServiceBuild(BaseModel): - context: Path + context: Optional[Path] @all_fields_optional class ComposeServicePort(BaseModel): - mode: str - protocol: str - published: int - target: int + mode: Optional[str] + protocol: Optional[str] + published: Optional[int] + target: Optional[int] @all_fields_optional class ComposeServiceVolume(BaseModel): - bind: dict - source: str - target: str - type: str + bind: Optional[dict] + source: Optional[str] + target: Optional[str] + type: Optional[str] @all_fields_optional class ComposeConfigService(BaseModel): - deploy: ServiceDeployConfig - blkio_config: Any - cpu_count: float - cpu_percent: float - cpu_shares: int - cpuset: str - build: ComposeServiceBuild - cap_add: List[str] = Field(default_factory=list) - cap_drop: List[str] = Field(default_factory=list) - cgroup_parent: str - command: List[str] - configs: Any - container_name: str + deploy: Optional[ServiceDeployConfig] + blkio_config: Optional[Any] + cpu_count: Optional[float] + cpu_percent: Optional[float] + cpu_shares: Optional[int] + cpuset: Optional[str] + build: Optional[ComposeServiceBuild] + cap_add: Optional[List[str]] = Field(default_factory=list) + cap_drop: Optional[List[str]] = Field(default_factory=list) + cgroup_parent: Optional[str] + command: Optional[List[str]] + configs: Any = None + container_name: Optional[str] depends_on: Dict[str, DependencyCondition] = Field(default_factory=dict) device_cgroup_rules: List[str] = Field(default_factory=list) - devices: Any - environment: Dict[str, Optional[str]] - entrypoint: List[str] - image: str - labels: Dict[str, str] = Field(default_factory=dict) - ports: List[ComposeServicePort] - volumes: List[ComposeServiceVolume] + devices: Any = None + environment: Optional[Dict[str, Optional[str]]] + entrypoint: Optional[List[str]] + image: Optional[str] + labels: Optional[Dict[str, str]] = Field(default_factory=dict) + ports: Optional[List[ComposeServicePort]] + volumes: Optional[List[ComposeServiceVolume]] @all_fields_optional class ComposeConfigNetwork(BaseModel): - driver: str - name: str - external: bool = False - driver_opts: Dict[str, Any] - attachable: bool - enable_ipv6: bool - ipam: Any - internal: bool + driver: Optional[str] + name: Optional[str] + external: Optional[bool] = False + driver_opts: Optional[Dict[str, Any]] + attachable: Optional[bool] + enable_ipv6: Optional[bool] + ipam: Any = None + internal: Optional[bool] labels: Dict[str, str] = Field(default_factory=dict) @all_fields_optional class ComposeConfigVolume(BaseModel): - driver: str - driver_opts: Dict[str, Any] - external: bool - labels: Dict[str, str] = Field(default_factory=dict) - name: str + driver: Optional[str] + driver_opts: Optional[Dict[str, Any]] + external: Optional[bool] + labels: Optional[Dict[str, str]] = Field(default_factory=dict) + name: Optional[str] @all_fields_optional class ComposeConfig(BaseModel): - services: Dict[str, ComposeConfigService] - networks: Dict[str, ComposeConfigNetwork] = Field(default_factory=dict) - volumes: Dict[str, ComposeConfigVolume] = Field(default_factory=dict) - configs: Any - secrets: Any + services: Optional[Dict[str, ComposeConfigService]] + networks: Optional[Dict[str, ComposeConfigNetwork]] = Field(default_factory=dict) + volumes: Optional[Dict[str, ComposeConfigVolume]] = Field(default_factory=dict) + configs: Any = None + secrets: Any = None class ComposeProject(BaseModel): - name: str - created: int = 0 - running: int = 0 - restarting: int = 0 - exited: int = 0 - paused: int = 0 - dead: int = 0 + name: Optional[str] + created: Optional[int] = 0 + running: Optional[int] = 0 + restarting: Optional[int] = 0 + exited: Optional[int] = 0 + paused: Optional[int] = 0 + dead: Optional[int] = 0 config_files: Optional[List[Path]] diff --git a/python_on_whales/components/config/models.py b/python_on_whales/components/config/models.py index 0de6cc4b..f910c093 100644 --- a/python_on_whales/components/config/models.py +++ b/python_on_whales/components/config/models.py @@ -7,24 +7,24 @@ class DockerObjectVersion(DockerCamelModel): - index: int + index: Optional[int] = None class ConfigSpecDriver(DockerCamelModel): - name: str - options: Dict[str, Any] + name: Optional[str] = None + options: Optional[Dict[str, Any]] = None class ConfigSpec(DockerCamelModel): - name: str - labels: Dict[str, str] - data: str + name: Optional[str] + labels: Optional[Dict[str, str]] + data: Optional[str] templating: Optional[ConfigSpecDriver] class ConfigInspectResult(DockerCamelModel): - id: str = pydantic.Field(alias="ID") - version: DockerObjectVersion - created_at: datetime - updated_at: datetime - spec: ConfigSpec + id: Optional[str] = pydantic.Field(None, alias="ID") + version: Optional[DockerObjectVersion] + created_at: Optional[datetime] + updated_at: Optional[datetime] + spec: Optional[ConfigSpec] diff --git a/python_on_whales/components/container/models.py b/python_on_whales/components/container/models.py index 8dd1fdef..ebc51268 100644 --- a/python_on_whales/components/container/models.py +++ b/python_on_whales/components/container/models.py @@ -9,330 +9,330 @@ @all_fields_optional class ContainerHealthcheckResult(DockerCamelModel): - start: datetime - end: datetime - exit_code: int - output: str + start: Optional[datetime] + end: Optional[datetime] + exit_code: Optional[int] + output: Optional[str] @all_fields_optional class ContainerHealth(DockerCamelModel): - status: str - failing_streak: int - log: List[ContainerHealthcheckResult] + status: Optional[str] + failing_streak: Optional[int] + log: Optional[List[ContainerHealthcheckResult]] @all_fields_optional class ContainerState(DockerCamelModel): - status: str - running: bool - paused: bool - restarting: bool - oom_killed: bool - dead: bool - pid: int - exit_code: int - error: str - started_at: datetime - finished_at: datetime - health: ContainerHealth + status: Optional[str] + running: Optional[bool] + paused: Optional[bool] + restarting: Optional[bool] + oom_killed: Optional[bool] + dead: Optional[bool] + pid: Optional[int] + exit_code: Optional[int] + error: Optional[str] + started_at: Optional[datetime] + finished_at: Optional[datetime] + health: Optional[ContainerHealth] @all_fields_optional class ContainerWeightDevice(DockerCamelModel): - path: Path - weight: int + path: Optional[Path] + weight: Optional[int] @all_fields_optional class ContainerThrottleDevice(DockerCamelModel): - path: Path - rate: int + path: Optional[Path] + rate: Optional[int] @all_fields_optional class ContainerDevice(DockerCamelModel): - path_on_host: Path - path_in_container: Path - cgroup_permissions: str + path_on_host: Optional[Path] + path_in_container: Optional[Path] + cgroup_permissions: Optional[str] @all_fields_optional class ContainerDeviceRequest(DockerCamelModel): - driver: str - count: int - device_ids: List[str] = pydantic.Field(alias="DeviceIDs") - capabilities: List[Any] - options: Dict[str, str] + driver: Optional[str] + count: Optional[int] + device_ids: Optional[List[str]] = pydantic.Field(None, alias="DeviceIDs") + capabilities: Optional[List[Any]] + options: Optional[Dict[str, str]] @all_fields_optional class ContainerUlimit(DockerCamelModel): - name: str - soft: int - hard: int + name: Optional[str] + soft: Optional[int] + hard: Optional[int] @all_fields_optional class ContainerLogConfig(DockerCamelModel): - type: str - config: Any + type: Optional[str] + config: Optional[Any] @all_fields_optional class ContainerRestartPolicy(DockerCamelModel): - name: str - maximum_retry_count: int + name: Optional[str] + maximum_retry_count: Optional[int] @all_fields_optional class PortBinding(DockerCamelModel): - host_ip: str - host_port: str + host_ip: Optional[str] + host_port: Optional[str] @all_fields_optional class ContainerMountBindOption(DockerCamelModel): - propagation: str - non_recursive: bool + propagation: Optional[str] + non_recursive: Optional[bool] @all_fields_optional class ContainerVolumeDriverConfig(DockerCamelModel): - name: str - options: Dict[str, Any] + name: Optional[str] + options: Optional[Dict[str, Any]] @all_fields_optional class ContainerVolumeOptions(DockerCamelModel): - no_copy: bool - labels: Dict[str, str] + no_copy: Optional[bool] + labels: Optional[Dict[str, str]] @all_fields_optional class ContainerTmpfsOptions(DockerCamelModel): - size_bytes: int - mode: int + size_bytes: Optional[int] + mode: Optional[int] @all_fields_optional class ContainerMount(DockerCamelModel): - target: Path - source: str - type: str - read_only: bool - consistency: str - bind_options: ContainerMountBindOption - volume_options: ContainerVolumeOptions - tmpfs_options: ContainerTmpfsOptions + target: Optional[Path] + source: Optional[str] + type: Optional[str] + read_only: Optional[bool] + consistency: Optional[str] + bind_options: Optional[ContainerMountBindOption] + volume_options: Optional[ContainerVolumeOptions] + tmpfs_options: Optional[ContainerTmpfsOptions] @all_fields_optional class ContainerHostConfig(DockerCamelModel): - cpu_shares: int - memory: int - cgroup_parent: Path - blkio_weight: int - blkio_weight_device: List[ContainerWeightDevice] - blkio_device_read_bps: List[ContainerThrottleDevice] - blkio_device_write_bps: List[ContainerThrottleDevice] - blkio_device_read_iops: List[ContainerThrottleDevice] - blkio_device_write_iops: List[ContainerThrottleDevice] - cpu_period: int - cpu_quota: int - cpu_realtime_period: int - cpu_realtime_runtime: int - cpuset_cpus: str - cpuset_mems: str - devices: List[ContainerDevice] - device_cgroup_rules: List[str] - device_requests: List[ContainerDeviceRequest] - kernel_memory: int - kernel_memory_tcp: int - memory_reservation: int - memory_swap: int - memory_swappiness: int - nano_cpus: int - oom_kill_disable: bool - init: bool - pids_limit: int - ulimits: List[ContainerUlimit] - cpu_count: int - cpu_percent: int - binds: List[str] - container_id_file: Path - log_config: ContainerLogConfig - network_mode: str - port_bindings: Dict[str, Optional[List[PortBinding]]] - restart_policy: ContainerRestartPolicy - auto_remove: bool - volume_driver: str - volumes_from: List[str] - mounts: List[ContainerMount] - capabilities: List[str] - cap_add: List[str] - cap_drop: List[str] - cgroupns_mode: str - dns: List[str] - dns_options: List[str] - dns_search: List[str] - extra_hosts: List[str] - group_add: List[str] - ipc_mode: str - cgroup: str - links: List[str] - oom_score_adj: int - pid_mode: str - privileged: bool - publish_all_ports: bool - readonly_rootfs: bool - security_opt: List[str] - storage_opt: Any - tmpfs: Dict[Path, str] - uts_mode: str - userns_mode: str - shm_size: int - sysctls: Dict[str, Any] - runtime: str - console_size: Tuple[int, int] - isolation: str - masked_paths: List[Path] - readonly_paths: List[Path] + cpu_shares: Optional[int] + memory: Optional[int] + cgroup_parent: Optional[Path] + blkio_weight: Optional[int] + blkio_weight_device: Optional[List[ContainerWeightDevice]] + blkio_device_read_bps: Optional[List[ContainerThrottleDevice]] + blkio_device_write_bps: Optional[List[ContainerThrottleDevice]] + blkio_device_read_iops: Optional[List[ContainerThrottleDevice]] + blkio_device_write_iops: Optional[List[ContainerThrottleDevice]] + cpu_period: Optional[int] + cpu_quota: Optional[int] + cpu_realtime_period: Optional[int] + cpu_realtime_runtime: Optional[int] + cpuset_cpus: Optional[str] + cpuset_mems: Optional[str] + devices: Optional[List[ContainerDevice]] + device_cgroup_rules: Optional[List[str]] + device_requests: Optional[List[ContainerDeviceRequest]] + kernel_memory: Optional[int] + kernel_memory_tcp: Optional[int] + memory_reservation: Optional[int] + memory_swap: Optional[int] + memory_swappiness: Optional[int] + nano_cpus: Optional[int] + oom_kill_disable: Optional[bool] + init: Optional[bool] + pids_limit: Optional[int] + ulimits: Optional[List[ContainerUlimit]] + cpu_count: Optional[int] + cpu_percent: Optional[int] + binds: Optional[List[str]] + container_id_file: Optional[Path] + log_config: Optional[ContainerLogConfig] + network_mode: Optional[str] + port_bindings: Optional[Dict[str, Optional[List[PortBinding]]]] + restart_policy: Optional[ContainerRestartPolicy] + auto_remove: Optional[bool] + volume_driver: Optional[str] + volumes_from: Optional[List[str]] + mounts: Optional[List[ContainerMount]] + capabilities: Optional[List[str]] + cap_add: Optional[List[str]] + cap_drop: Optional[List[str]] + cgroupns_mode: Optional[str] + dns: Optional[List[str]] + dns_options: Optional[List[str]] + dns_search: Optional[List[str]] + extra_hosts: Optional[List[str]] + group_add: Optional[List[str]] + ipc_mode: Optional[str] + cgroup: Optional[str] + links: Optional[List[str]] + oom_score_adj: Optional[int] + pid_mode: Optional[str] + privileged: Optional[bool] + publish_all_ports: Optional[bool] + readonly_rootfs: Optional[bool] + security_opt: Optional[List[str]] + storage_opt: Any = None + tmpfs: Optional[Dict[Path, str]] + uts_mode: Optional[str] + userns_mode: Optional[str] + shm_size: Optional[int] + sysctls: Optional[Dict[str, Any]] + runtime: Optional[str] + console_size: Optional[Tuple[int, int]] + isolation: Optional[str] + masked_paths: Optional[List[Path]] + readonly_paths: Optional[List[Path]] @all_fields_optional class ContainerHealthCheck(DockerCamelModel): - test: List[str] - interval: int - timeout: int - retries: int - start_period: int + test: Optional[List[str]] + interval: Optional[int] + timeout: Optional[int] + retries: Optional[int] + start_period: Optional[int] @all_fields_optional class ContainerConfig(DockerCamelModel): - hostname: str - domainname: str - user: str - attach_stdin: bool - attach_stdout: bool - attach_stderr: bool - exposed_ports: dict - tty: bool - open_stdin: bool - stdin_once: bool - env: List[str] - cmd: List[str] - healthcheck: ContainerHealthCheck - args_escaped: bool - image: str - volumes: dict - working_dir: Path - entrypoint: Union[List[str], str] - network_disabled: bool - mac_address: str - on_build: List[str] - labels: Dict[str, str] - stop_signal: str - stop_timeout: int - shell: List[str] + hostname: Optional[str] + domainname: Optional[str] + user: Optional[str] + attach_stdin: Optional[bool] + attach_stdout: Optional[bool] + attach_stderr: Optional[bool] + exposed_ports: Optional[dict] + tty: Optional[bool] + open_stdin: Optional[bool] + stdin_once: Optional[bool] + env: Optional[List[str]] + cmd: Optional[List[str]] + healthcheck: Optional[ContainerHealthCheck] + args_escaped: Optional[bool] + image: Optional[str] + volumes: Optional[dict] + working_dir: Optional[Path] + entrypoint: Union[List[str], str, None] = None + network_disabled: Optional[bool] + mac_address: Optional[str] + on_build: Optional[List[str]] + labels: Optional[Dict[str, str]] + stop_signal: Optional[str] + stop_timeout: Optional[int] + shell: Optional[List[str]] @all_fields_optional class Mount(DockerCamelModel): - type: str - name: str - source: str - destination: str - driver: str - mode: str - rw: bool - propagation: str + type: Optional[str] + name: Optional[str] + source: Optional[str] + destination: Optional[str] + driver: Optional[str] + mode: Optional[str] + rw: Optional[bool] + propagation: Optional[str] @all_fields_optional class ContainerEndpointIPAMConfig(DockerCamelModel): - ipv4_address: str - ipv6_address: str - link_local_ips: List[str] + ipv4_address: Optional[str] + ipv6_address: Optional[str] + link_local_ips: Optional[List[str]] @all_fields_optional class NetworkInspectResult(DockerCamelModel): - ipam_config: ContainerEndpointIPAMConfig - links: List[str] - aliases: List[str] - network_id: str - endpoint_id: str - gateway: str - ip_address: str - ip_prefix_length: int - ipv6_gateway: str - global_ipv6_address: str - global_ipv6_prefix_length: int - mac_address: str - driver_options: dict + ipam_config: Optional[ContainerEndpointIPAMConfig] + links: Optional[List[str]] + aliases: Optional[List[str]] + network_id: Optional[str] + endpoint_id: Optional[str] + gateway: Optional[str] + ip_address: Optional[str] + ip_prefix_length: Optional[int] + ipv6_gateway: Optional[str] + global_ipv6_address: Optional[str] + global_ipv6_prefix_length: Optional[int] + mac_address: Optional[str] + driver_options: Optional[dict] @all_fields_optional class ContainerNetworkAddress(DockerCamelModel): - addr: str - prefix_len: int + addr: Optional[str] + prefix_len: Optional[int] @all_fields_optional class NetworkSettings(DockerCamelModel): - bridge: str - sandbox_id: str - hairpin_mode: bool - link_local_ipv6_address: str - link_local_ipv6_prefix_length: int - ports: dict # to rework - sandbox_key: Path - secondary_ip_addresses: List[ContainerNetworkAddress] - secondary_ipv6_addresses: List[ContainerNetworkAddress] - endpoint_id: str - gateway: str - global_ipv6_address: str - global_ipv6_prefix_length: int - ip_address: str - ip_prefix_length: int - ipv6_gateway: str - mac_address: str - networks: Dict[str, NetworkInspectResult] + bridge: Optional[str] + sandbox_id: Optional[str] + hairpin_mode: Optional[bool] + link_local_ipv6_address: Optional[str] + link_local_ipv6_prefix_length: Optional[int] + ports: Optional[dict] # to rework + sandbox_key: Optional[Path] + secondary_ip_addresses: Optional[List[ContainerNetworkAddress]] + secondary_ipv6_addresses: Optional[List[ContainerNetworkAddress]] + endpoint_id: Optional[str] + gateway: Optional[str] + global_ipv6_address: Optional[str] + global_ipv6_prefix_length: Optional[int] + ip_address: Optional[str] + ip_prefix_length: Optional[int] + ipv6_gateway: Optional[str] + mac_address: Optional[str] + networks: Optional[Dict[str, NetworkInspectResult]] @all_fields_optional class ContainerGraphDriver(DockerCamelModel): - name: str - data: Dict[str, Any] + name: Optional[str] + data: Optional[Dict[str, Any]] @all_fields_optional class ContainerInspectResult(DockerCamelModel): - id: str - created: datetime - path: str - args: List[str] - state: ContainerState - image: str - resolv_conf_path: str - hostname_path: Path - hosts_path: Path - log_path: Path - node: Any - name: str - restart_count: int - driver: str - platform: str - mount_label: str - process_label: str - app_armor_profile: str - exec_ids: List[str] - host_config: ContainerHostConfig - graph_driver: ContainerGraphDriver - size_rw: int - size_root_fs: int - mounts: List[Mount] - config: ContainerConfig - network_settings: NetworkSettings + id: Optional[str] + created: Optional[datetime] + path: Optional[str] + args: Optional[List[str]] + state: Optional[ContainerState] + image: Optional[str] + resolv_conf_path: Optional[str] + hostname_path: Optional[Path] + hosts_path: Optional[Path] + log_path: Optional[Path] + node: Any = None + name: Optional[str] + restart_count: Optional[int] + driver: Optional[str] + platform: Optional[str] + mount_label: Optional[str] + process_label: Optional[str] + app_armor_profile: Optional[str] + exec_ids: Optional[List[str]] + host_config: Optional[ContainerHostConfig] + graph_driver: Optional[ContainerGraphDriver] + size_rw: Optional[int] + size_root_fs: Optional[int] + mounts: Optional[List[Mount]] + config: Optional[ContainerConfig] + network_settings: Optional[NetworkSettings] diff --git a/python_on_whales/components/context/models.py b/python_on_whales/components/context/models.py index 4a5e4b8c..14883b71 100644 --- a/python_on_whales/components/context/models.py +++ b/python_on_whales/components/context/models.py @@ -1,4 +1,4 @@ -from typing import Dict +from typing import Dict, Optional import pydantic @@ -6,18 +6,18 @@ class ContextEndpoint(DockerCamelModel): - host: str - skip_tls_verify: bool = pydantic.Field(alias="SkipTLSVerify") + host: Optional[str] + skip_tls_verify: Optional[bool] = pydantic.Field(alias="SkipTLSVerify") class ContextStorage(DockerCamelModel): - metadata_path: str - tls_path: str = pydantic.Field(alias="TLSPath") + metadata_path: Optional[str] + tls_path: Optional[str] = pydantic.Field(None, alias="TLSPath") class ContextInspectResult(DockerCamelModel): - name: str - metadata: Dict[str, str] - endpoints: Dict[str, ContextEndpoint] - tls_material: dict = pydantic.Field(alias="TLSMaterial") - storage: ContextStorage + name: Optional[str] + metadata: Optional[Dict[str, str]] + endpoints: Optional[Dict[str, ContextEndpoint]] + tls_material: Optional[dict] = pydantic.Field(None, alias="TLSMaterial") + storage: Optional[ContextStorage] diff --git a/python_on_whales/components/image/models.py b/python_on_whales/components/image/models.py index eec8821b..12eb6304 100644 --- a/python_on_whales/components/image/models.py +++ b/python_on_whales/components/image/models.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional import python_on_whales.components.container.models from python_on_whales.utils import DockerCamelModel, all_fields_optional @@ -7,44 +7,46 @@ @all_fields_optional class ImageHealthcheck(DockerCamelModel): - test: List[str] - interval: int - timeout: int - retries: int - start_period: int + test: Optional[List[str]] + interval: Optional[int] + timeout: Optional[int] + retries: Optional[int] + start_period: Optional[int] @all_fields_optional class ImageGraphDriver(DockerCamelModel): - name: str - data: Any + name: Optional[str] + data: Any = None @all_fields_optional class ImageRootFS(DockerCamelModel): - type: str - layers: List[str] - base_layer: str + type: Optional[str] + layers: Optional[List[str]] + base_layer: Optional[str] @all_fields_optional class ImageInspectResult(DockerCamelModel): - id: str - repo_tags: List[str] - repo_digests: List[str] - parent: str - comment: str - created: datetime - container: str - container_config: python_on_whales.components.container.models.ContainerConfig - docker_version: str - author: str - config: python_on_whales.components.container.models.ContainerConfig - architecture: str - os: str - os_version: str - size: int - virtual_size: int - graph_driver: ImageGraphDriver - root_fs: ImageRootFS - metadata: Dict[str, str] + id: Optional[str] + repo_tags: Optional[List[str]] + repo_digests: Optional[List[str]] + parent: Optional[str] + comment: Optional[str] + created: Optional[datetime] + container: Optional[str] + container_config: Optional[ + python_on_whales.components.container.models.ContainerConfig + ] + docker_version: Optional[str] + author: Optional[str] + config: Optional[python_on_whales.components.container.models.ContainerConfig] + architecture: Optional[str] + os: Optional[str] + os_version: Optional[str] + size: Optional[int] + virtual_size: Optional[int] + graph_driver: Optional[ImageGraphDriver] + root_fs: Optional[ImageRootFS] + metadata: Optional[Dict[str, str]] diff --git a/python_on_whales/components/manifest/models.py b/python_on_whales/components/manifest/models.py index 177218ac..2fafcaf2 100644 --- a/python_on_whales/components/manifest/models.py +++ b/python_on_whales/components/manifest/models.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Optional from python_on_whales.components.buildx.imagetools.models import ImageVariantManifest from python_on_whales.utils import DockerCamelModel, all_fields_optional @@ -6,7 +6,7 @@ @all_fields_optional class ManifestListInspectResult(DockerCamelModel): - name: str - schema_version: int - media_type: str - manifests: List[ImageVariantManifest] + name: Optional[str] + schema_version: Optional[int] + media_type: Optional[str] + manifests: Optional[List[ImageVariantManifest]] diff --git a/python_on_whales/components/network/models.py b/python_on_whales/components/network/models.py index 3bd0ff67..501115f0 100644 --- a/python_on_whales/components/network/models.py +++ b/python_on_whales/components/network/models.py @@ -1,39 +1,39 @@ from datetime import datetime -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional from python_on_whales.utils import DockerCamelModel, all_fields_optional @all_fields_optional class NetworkIPAM(DockerCamelModel): - driver: str - config: List[Dict[str, Any]] - options: Dict[str, Any] + driver: Optional[str] + config: Optional[List[Dict[str, Any]]] + options: Optional[Dict[str, Any]] @all_fields_optional class NetworkContainer(DockerCamelModel): - name: str - endpoint_id: str - mac_address: str - ipv4_address: str - ipv6_address: str + name: Optional[str] + endpoint_id: Optional[str] + mac_address: Optional[str] + ipv4_address: Optional[str] + ipv6_address: Optional[str] @all_fields_optional class NetworkInspectResult(DockerCamelModel): - name: str - id: str - created: datetime - scope: str - driver: str - enable_ipv6: bool - ipam: NetworkIPAM - internal: bool - attachable: bool - ingress: bool - containers: Dict[str, NetworkContainer] - options: Dict[str, Any] - labels: Dict[str, str] - config_from: dict - config_only: bool + name: Optional[str] + id: Optional[str] + created: Optional[datetime] + scope: Optional[str] + driver: Optional[str] + enable_ipv6: Optional[bool] + ipam: Optional[NetworkIPAM] + internal: Optional[bool] + attachable: Optional[bool] + ingress: Optional[bool] + containers: Optional[Dict[str, NetworkContainer]] + options: Optional[Dict[str, Any]] + labels: Optional[Dict[str, str]] + config_from: Optional[dict] + config_only: Optional[bool] diff --git a/python_on_whales/components/node/models.py b/python_on_whales/components/node/models.py index 598ffcc5..9e57ee8f 100644 --- a/python_on_whales/components/node/models.py +++ b/python_on_whales/components/node/models.py @@ -8,33 +8,33 @@ @all_fields_optional class NodeVersion(DockerCamelModel): - index: int + index: Optional[int] @all_fields_optional class NodeSpec(DockerCamelModel): name: Optional[str] - labels: Dict[str, str] - role: str - availability: str + labels: Optional[Dict[str, str]] + role: Optional[str] + availability: Optional[str] @all_fields_optional class NodePlatform(DockerCamelModel): - architecture: str - os: str = Field(alias="OS") + architecture: Optional[str] + os: Optional[str] = Field(None, alias="OS") @all_fields_optional class NodeNamedResourceSpec(DockerCamelModel): - kind: str - value: str + kind: Optional[str] + value: Optional[str] @all_fields_optional class NodeDiscreteResourceSpec(DockerCamelModel): - kind: str - value: int + kind: Optional[str] + value: Optional[int] @all_fields_optional @@ -45,61 +45,61 @@ class NodeGenericResource(DockerCamelModel): @all_fields_optional class NodeResource(DockerCamelModel): - nano_cpus: int = Field(alias="NanoCPUs") - memory_bytes: int + nano_cpus: Optional[int] = Field(None, alias="NanoCPUs") + memory_bytes: Optional[int] generic_resources: Optional[List[NodeGenericResource]] @all_fields_optional class EnginePlugin(DockerCamelModel): - type: str - name: str + type: Optional[str] + name: Optional[str] @all_fields_optional class NodeEngine(DockerCamelModel): - engine_version: str + engine_version: Optional[str] labels: Optional[Dict[str, str]] - plugins: List[EnginePlugin] + plugins: Optional[List[EnginePlugin]] @all_fields_optional class NodeTLSInfo(DockerCamelModel): - trust_root: str - cert_issuer_subject: str - cert_issuer_public_key: str + trust_root: Optional[str] + cert_issuer_subject: Optional[str] + cert_issuer_public_key: Optional[str] @all_fields_optional class NodeDescription(DockerCamelModel): - hostname: str - platform: NodePlatform - resources: NodeResource - engine: NodeEngine - tls_info: NodeTLSInfo + hostname: Optional[str] + platform: Optional[NodePlatform] + resources: Optional[NodeResource] + engine: Optional[NodeEngine] + tls_info: Optional[NodeTLSInfo] @all_fields_optional class NodeStatus(DockerCamelModel): - state: str + state: Optional[str] message: Optional[str] - addr: str + addr: Optional[str] @all_fields_optional class NodeManagerStatus(DockerCamelModel): - leader: bool - reachability: str - addr: str + leader: Optional[bool] + reachability: Optional[str] + addr: Optional[str] @all_fields_optional class NodeInspectResult(DockerCamelModel): - id: str = Field(alias="ID") - version: NodeVersion - created_at: datetime - updated_at: datetime - spec: NodeSpec - description: NodeDescription - status: NodeStatus + id: Optional[str] = Field(None, alias="ID") + version: Optional[NodeVersion] + created_at: Optional[datetime] + updated_at: Optional[datetime] + spec: Optional[NodeSpec] + description: Optional[NodeDescription] + status: Optional[NodeStatus] manager_status: Optional[NodeManagerStatus] diff --git a/python_on_whales/components/plugin/models.py b/python_on_whales/components/plugin/models.py index 1ba2c5d5..e8af95e0 100644 --- a/python_on_whales/components/plugin/models.py +++ b/python_on_whales/components/plugin/models.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Optional from python_on_whales.utils import DockerCamelModel, all_fields_optional @@ -15,10 +15,10 @@ class PluginDevice(DockerCamelModel): @all_fields_optional class PluginSettings(DockerCamelModel): - mounts: List[PluginMount] - env: List[str] - args: List[str] - devices: List[PluginDevice] + mounts: Optional[List[PluginMount]] + env: Optional[List[str]] + args: Optional[List[str]] + devices: Optional[List[PluginDevice]] @all_fields_optional @@ -28,20 +28,20 @@ class Interface(DockerCamelModel): @all_fields_optional class PluginConfig(DockerCamelModel): - docker_version: str - description: str - documentation: str - interface: Interface - entrypoint: List[str] - work_dir: str + docker_version: Optional[str] + description: Optional[str] + documentation: Optional[str] + interface: Optional[Interface] + entrypoint: Optional[List[str]] + work_dir: Optional[str] # TODO: add missing attributes @all_fields_optional class PluginInspectResult(DockerCamelModel): - id: str - name: str - enabled: bool - settings: PluginSettings - plugin_reference: str - config: PluginConfig + id: Optional[str] + name: Optional[str] + enabled: Optional[bool] + settings: Optional[PluginSettings] + plugin_reference: Optional[str] + config: Optional[PluginConfig] diff --git a/python_on_whales/components/secret/models.py b/python_on_whales/components/secret/models.py index 5c43471b..b50ce324 100644 --- a/python_on_whales/components/secret/models.py +++ b/python_on_whales/components/secret/models.py @@ -1,12 +1,13 @@ from datetime import datetime +from typing import Optional from python_on_whales.utils import DockerCamelModel, all_fields_optional @all_fields_optional class SecretInspectResult(DockerCamelModel): - id: str - version: dict - created_at: datetime - updated_at: datetime - spec: dict + id: Optional[str] + version: Optional[dict] + created_at: Optional[datetime] + updated_at: Optional[datetime] + spec: Optional[dict] diff --git a/python_on_whales/components/service/models.py b/python_on_whales/components/service/models.py index 53bae72b..2618750f 100644 --- a/python_on_whales/components/service/models.py +++ b/python_on_whales/components/service/models.py @@ -8,99 +8,99 @@ @all_fields_optional class CPUMemoryQuotas(DockerCamelModel): - nano_cpus: int = Field(alias="NanoCPUs") - memory_bytes: int + nano_cpus: Optional[int] = Field(None, alias="NanoCPUs") + memory_bytes: Optional[int] @all_fields_optional class Resources(DockerCamelModel): - limits: CPUMemoryQuotas - reservations: CPUMemoryQuotas + limits: Optional[CPUMemoryQuotas] + reservations: Optional[CPUMemoryQuotas] @all_fields_optional class ContainerSpec(DockerCamelModel): - image: str - labels: Dict[str, str] - privileges: Dict[str, Optional[str]] - stop_grace_period: int - isolation: str - env: List[str] + image: Optional[str] + labels: Optional[Dict[str, str]] + privileges: Optional[Dict[str, Optional[str]]] + stop_grace_period: Optional[int] + isolation: Optional[str] + env: Optional[List[str]] @all_fields_optional class TaskTemplate(DockerCamelModel): - container_spec: ContainerSpec - resources: Resources + container_spec: Optional[ContainerSpec] + resources: Optional[Resources] @all_fields_optional class ChangeConfig(DockerCamelModel): - parallelism: int - failure_action: str - monitor: int - max_failure_ratio: int - order: str + parallelism: Optional[int] + failure_action: Optional[str] + monitor: Optional[int] + max_failure_ratio: Optional[int] + order: Optional[str] @all_fields_optional class ServiceSpec(DockerCamelModel): - name: str - labels: Dict[str, str] - mode: Dict[str, Any] - update_config: ChangeConfig - rollback_config: ChangeConfig - task_template: TaskTemplate + name: Optional[str] + labels: Optional[Dict[str, str]] + mode: Optional[Dict[str, Any]] + update_config: Optional[ChangeConfig] + rollback_config: Optional[ChangeConfig] + task_template: Optional[TaskTemplate] @all_fields_optional class ServiceVersion(DockerCamelModel): - index: int + index: Optional[int] @all_fields_optional class EndpointPortConfig(DockerCamelModel): - name: str - protocol: str - target_port: int - published_port: int - publish_mode: str + name: Optional[str] + protocol: Optional[str] + target_port: Optional[int] + published_port: Optional[int] + publish_mode: Optional[str] @all_fields_optional class ServiceEndpointSpec(DockerCamelModel): - mode: str - ports: List[EndpointPortConfig] + mode: Optional[str] + ports: Optional[List[EndpointPortConfig]] @all_fields_optional class VirtualIP(DockerCamelModel): - network_id: str - addr: str + network_id: Optional[str] + addr: Optional[str] @all_fields_optional class ServiceEndpoint(DockerCamelModel): - spec: ServiceEndpointSpec - ports: List[EndpointPortConfig] - virtual_ips: List[VirtualIP] + spec: Optional[ServiceEndpointSpec] + ports: Optional[List[EndpointPortConfig]] + virtual_ips: Optional[List[VirtualIP]] @all_fields_optional class ServiceUpdateStatus(DockerCamelModel): - state: str - started_at: str - completed_at: str - message: str + state: Optional[str] + started_at: Optional[str] + completed_at: Optional[str] + message: Optional[str] @all_fields_optional class ServiceInspectResult(DockerCamelModel): - id: str = Field(alias="ID") - version: ServiceVersion - created_at: datetime - updated_at: datetime - spec: ServiceSpec - previous_spec: ServiceSpec - endpoint: ServiceEndpoint - update_status: ServiceUpdateStatus + id: Optional[str] = Field(None, alias="ID") + version: Optional[ServiceVersion] + created_at: Optional[datetime] + updated_at: Optional[datetime] + spec: Optional[ServiceSpec] + previous_spec: Optional[ServiceSpec] + endpoint: Optional[ServiceEndpoint] + update_status: Optional[ServiceUpdateStatus] diff --git a/python_on_whales/components/system/models.py b/python_on_whales/components/system/models.py index 53de1de6..f67cad1f 100644 --- a/python_on_whales/components/system/models.py +++ b/python_on_whales/components/system/models.py @@ -1,6 +1,6 @@ from datetime import datetime from pathlib import Path -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional import pydantic @@ -10,215 +10,220 @@ @all_fields_optional class DockerEventActor(DockerCamelModel): - id: str = pydantic.Field(alias="ID") - attributes: Dict[str, Any] = pydantic.Field(alias="Attributes") + id: Optional[str] = pydantic.Field(None, alias="ID") + attributes: Optional[Dict[str, Any]] = pydantic.Field(None, alias="Attributes") -@all_fields_optional class DockerEvent(DockerCamelModel): - type: str = pydantic.Field(alias="Type") - action: str = pydantic.Field(alias="Action") - actor: DockerEventActor = pydantic.Field(alias="Actor") - time: datetime - time_nano: int = pydantic.Field(alias="timeNano") + type: Optional[str] = pydantic.Field(None, alias="Type") + action: Optional[str] = pydantic.Field(None, alias="Action") + actor: Optional[DockerEventActor] = pydantic.Field(None, alias="Actor") + time: Optional[datetime] = pydantic.Field(None, alias="time") + time_nano: Optional[int] = pydantic.Field(None, alias="timeNano") @all_fields_optional class DockerItemsSummary(DockerCamelModel): - active: int - reclaimable: pydantic.ByteSize - reclaimable_percent: float - size: pydantic.ByteSize - total_count: int + active: Optional[int] + reclaimable: Optional[pydantic.ByteSize] + reclaimable_percent: Optional[float] + size: Optional[pydantic.ByteSize] + total_count: Optional[int] @all_fields_optional class Plugins(DockerCamelModel): - volume: List[str] - network: List[str] - authorization: Any - log: List[str] + volume: Optional[List[str]] + network: Optional[List[str]] + authorization: Any = None + log: Optional[List[str]] @all_fields_optional class Runtime(DockerCamelModel): - path: str - runtime_args: List[str] + path: Optional[str] + runtime_args: Optional[List[str]] @all_fields_optional class Commit(DockerCamelModel): - id: str = pydantic.Field(alias="ID") - expected: str + id: Optional[str] = pydantic.Field(None, alias="ID") + expected: Optional[str] @all_fields_optional class RemoteManager(DockerCamelModel): - node_id: str = pydantic.Field(alias="NodeID") - addr: str + node_id: Optional[str] = pydantic.Field(None, alias="NodeID") + addr: Optional[str] @all_fields_optional class Orchestration(DockerCamelModel): - task_history_retention_limit: int + task_history_retention_limit: Optional[int] @all_fields_optional class Raft(DockerCamelModel): - snapshot_interval: int - keep_old_snapshots: int - log_entries_for_slow_followers: int - election_tick: int - heartbeat_tick: int + snapshot_interval: Optional[int] + keep_old_snapshots: Optional[int] + log_entries_for_slow_followers: Optional[int] + election_tick: Optional[int] + heartbeat_tick: Optional[int] @all_fields_optional class SwarmDispatcher(DockerCamelModel): - heartbeat_period: int + heartbeat_period: Optional[int] @all_fields_optional class SwarmCAConfig(DockerCamelModel): - node_cert_expiry: int - external_ca: List[Any] = pydantic.Field(alias="ExternalCA") # TODO: set type - signing_ca_cert: str = pydantic.Field(alias="SigningCACert") - signing_ca_key: str = pydantic.Field(alias="SigningCAKey") - force_rotate: int + node_cert_expiry: Optional[int] + external_ca: Optional[List[Any]] = pydantic.Field( + None, alias="ExternalCA" + ) # TODO: set type + signing_ca_cert: Optional[str] = pydantic.Field(None, alias="SigningCACert") + signing_ca_key: Optional[str] = pydantic.Field(None, alias="SigningCAKey") + force_rotate: Optional[int] @all_fields_optional class SwarmEncryptionConfig(DockerCamelModel): - auto_lock_managers: bool + auto_lock_managers: Optional[bool] @all_fields_optional class Driver(DockerCamelModel): - name: str - options: Dict[str, Any] + name: Optional[str] + options: Optional[Dict[str, Any]] @all_fields_optional class SwarmTasksDefault(DockerCamelModel): - log_driver: Driver + log_driver: Optional[Driver] @all_fields_optional class SwarmSpec(DockerCamelModel): - name: str - labels: Dict[str, str] - orchestration: Orchestration - raft: Raft - dispatcher: SwarmDispatcher - ca_config: SwarmCAConfig = pydantic.Field(alias="CAConfig") - encryption_config: SwarmEncryptionConfig - task_defaults: SwarmTasksDefault + name: Optional[str] + labels: Optional[Dict[str, str]] + orchestration: Optional[Orchestration] + raft: Optional[Raft] + dispatcher: Optional[SwarmDispatcher] + ca_config: Optional[SwarmCAConfig] = pydantic.Field(None, alias="CAConfig") + encryption_config: Optional[SwarmEncryptionConfig] + task_defaults: Optional[SwarmTasksDefault] @all_fields_optional class ClusterInfo(DockerCamelModel): - id: str = pydantic.Field(alias="ID") - version: python_on_whales.components.node.models.NodeVersion - created_at: datetime - updated_at: datetime - spec: SwarmSpec - tls_info: python_on_whales.components.node.models.NodeTLSInfo - root_rotation_in_progress: bool - data_path_port: int - default_addr_pool: List[str] - subnet_size: int + id: Optional[str] = pydantic.Field(None, alias="ID") + version: Optional[python_on_whales.components.node.models.NodeVersion] + created_at: Optional[datetime] + updated_at: Optional[datetime] + spec: Optional[SwarmSpec] + tls_info: Optional[python_on_whales.components.node.models.NodeTLSInfo] + root_rotation_in_progress: Optional[bool] + data_path_port: Optional[int] + default_addr_pool: Optional[List[str]] + subnet_size: Optional[int] @all_fields_optional class SwarmInfo(DockerCamelModel): - node_id: str = pydantic.Field(alias="NodeID") - node_addr: str - local_node_state: str - control_available: bool - error: str - remote_managers: List[RemoteManager] - nodes: int - managers: int - cluster: ClusterInfo + node_id: Optional[str] = pydantic.Field(None, alias="NodeID") + node_addr: Optional[str] + local_node_state: Optional[str] + control_available: Optional[bool] + error: Optional[str] + remote_managers: Optional[List[RemoteManager]] + nodes: Optional[int] + managers: Optional[int] + cluster: Optional[ClusterInfo] @all_fields_optional class ClientPlugin(DockerCamelModel): - schema_version: str - vendor: str - version: str - short_description: str - name: str - path: Path - shadowed_paths: List[Path] + schema_version: Optional[str] + vendor: Optional[str] + version: Optional[str] + short_description: Optional[str] + name: Optional[str] + path: Optional[Path] + shadowed_paths: Optional[List[Path]] @all_fields_optional class ClientInfo(DockerCamelModel): - debug: bool - plugins: List[ClientPlugin] - warnings: List[str] + debug: Optional[bool] + plugins: Optional[List[ClientPlugin]] + warnings: Optional[List[str]] @all_fields_optional class SystemInfo(DockerCamelModel): - id: str = pydantic.Field(alias="ID") - containers: int - containers_running: int - containers_paused: int - containers_stopped: int - images: int - driver: str - driver_status: List[List[str]] - docker_root_dir: Path - system_status: List[str] - plugins: Plugins - memory_limit: bool - swap_limit: bool - kernel_memory: bool - cpu_cfs_period: bool - cpu_cfs_quota: bool - cpu_shares: bool = pydantic.Field(alias="CPUShares") - cpu_set: bool = pydantic.Field(alias="CPUSet") - pids_limit: bool - oom_kill_disable: bool - ipv4_forwarding: bool = pydantic.Field(alias="IPv4Forwarding") - bridge_nf_iptables: bool - bridge_nf_ip6tables: bool = pydantic.Field(alias="BridgeNfIp6tables") - debug: bool - nfd: int = pydantic.Field(alias="NFd") - n_goroutines: int - system_time: str - logging_driver: str - cgroup_driver: str - n_events_listener: int - kernel_version: str - operating_system: str - os_type: str = pydantic.Field(alias="OSType") - architecture: str - n_cpu: int = pydantic.Field(alias="NCPU") - mem_total: int - index_server_address: str - registry_config: Dict[str, Any] - generic_resources: List[python_on_whales.components.node.models.NodeGenericResource] - - http_proxy: str - https_proxy: str - no_proxy: str - name: str - labels: Dict[str, str] - experimental_build: bool - server_version: str - cluster_store: str - runtimes: Dict[str, Runtime] - default_runtime: str - swarm: SwarmInfo - live_restore_enabled: bool - isolation: str - init_binary: str - containerd_commit: Commit - runc_commit: Commit - init_commit: Commit - security_options: List[str] - product_license: str - warnings: List[str] - client_info: ClientInfo + id: Optional[str] = pydantic.Field(None, alias="ID") + containers: Optional[int] + containers_running: Optional[int] + containers_paused: Optional[int] + containers_stopped: Optional[int] + images: Optional[int] + driver: Optional[str] + driver_status: Optional[List[List[str]]] + docker_root_dir: Optional[Path] + system_status: Optional[List[str]] + plugins: Optional[Plugins] + memory_limit: Optional[bool] + swap_limit: Optional[bool] + kernel_memory: Optional[bool] + cpu_cfs_period: Optional[bool] + cpu_cfs_quota: Optional[bool] + cpu_shares: Optional[bool] = pydantic.Field(None, alias="CPUShares") + cpu_set: Optional[bool] = pydantic.Field(None, alias="CPUSet") + pids_limit: Optional[bool] + oom_kill_disable: Optional[bool] + ipv4_forwarding: Optional[bool] = pydantic.Field(None, alias="IPv4Forwarding") + bridge_nf_iptables: Optional[bool] + bridge_nf_ip6tables: Optional[bool] = pydantic.Field( + None, alias="BridgeNfIp6tables" + ) + debug: Optional[bool] + nfd: Optional[int] = pydantic.Field(None, alias="NFd") + n_goroutines: Optional[int] + system_time: Optional[str] + logging_driver: Optional[str] + cgroup_driver: Optional[str] + n_events_listener: Optional[int] + kernel_version: Optional[str] + operating_system: Optional[str] + os_type: Optional[str] = pydantic.Field(None, alias="OSType") + architecture: Optional[str] + n_cpu: Optional[int] = pydantic.Field(None, alias="NCPU") + mem_total: Optional[int] + index_server_address: Optional[str] + registry_config: Optional[Dict[str, Any]] + generic_resources: Optional[ + List[python_on_whales.components.node.models.NodeGenericResource] + ] + + http_proxy: Optional[str] + https_proxy: Optional[str] + no_proxy: Optional[str] + name: Optional[str] + labels: Optional[Dict[str, str]] + experimental_build: Optional[bool] + server_version: Optional[str] + cluster_store: Optional[str] + runtimes: Optional[Dict[str, Runtime]] + default_runtime: Optional[str] + swarm: Optional[SwarmInfo] + live_restore_enabled: Optional[bool] + isolation: Optional[str] + init_binary: Optional[str] + containerd_commit: Optional[Commit] + runc_commit: Optional[Commit] + init_commit: Optional[Commit] + security_options: Optional[List[str]] + product_license: Optional[str] + warnings: Optional[List[str]] + client_info: Optional[ClientInfo] diff --git a/python_on_whales/components/task/models.py b/python_on_whales/components/task/models.py index e2e1179a..1a9e6f90 100644 --- a/python_on_whales/components/task/models.py +++ b/python_on_whales/components/task/models.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional import pydantic @@ -8,171 +8,171 @@ @all_fields_optional class ObjectVersion(DockerCamelModel): - index: int + index: Optional[int] @all_fields_optional class NamedResourceSpec(DockerCamelModel): - kind: str - value: str + kind: Optional[str] + value: Optional[str] @all_fields_optional class DiscreteResourceSpec(DockerCamelModel): - kind: str - value: int + kind: Optional[str] + value: Optional[int] @all_fields_optional class AssignedGenericResources(DockerCamelModel): - named_resource_spec: NamedResourceSpec - discrete_resource_spec: DiscreteResourceSpec + named_resource_spec: Optional[NamedResourceSpec] + discrete_resource_spec: Optional[DiscreteResourceSpec] @all_fields_optional class ContainerStatus(DockerCamelModel): - container_id: str = pydantic.Field(alias="ContainerID") - pid: int = pydantic.Field(alias="PID") - exit_code: int + container_id: Optional[str] = pydantic.Field(None, alias="ContainerID") + pid: Optional[int] = pydantic.Field(None, alias="PID") + exit_code: Optional[int] @all_fields_optional class TaskStatus(DockerCamelModel): - timestamp: datetime - state: str - message: str - err: str - container_status: ContainerStatus + timestamp: Optional[datetime] + state: Optional[str] + message: Optional[str] + err: Optional[str] + container_status: Optional[ContainerStatus] @all_fields_optional class LogDriver(DockerCamelModel): - name: str - options: Dict[str, str] + name: Optional[str] + options: Optional[Dict[str, str]] @all_fields_optional class NetworkAttachmentConfig(DockerCamelModel): - target: str - aliases: List[str] - driver_opts: Dict[str, str] + target: Optional[str] + aliases: Optional[List[str]] + driver_opts: Optional[Dict[str, str]] @all_fields_optional class Platform(DockerCamelModel): - architecture: str - os: str = pydantic.Field(alias="OS") + architecture: Optional[str] + os: Optional[str] = pydantic.Field(None, alias="OS") @all_fields_optional class Spread(DockerCamelModel): - spread_descriptor: str + spread_descriptor: Optional[str] @all_fields_optional class Placement(DockerCamelModel): - constraints: List[str] - preferences: List[Spread] - max_replicas: int - platforms: List[Platform] + constraints: Optional[List[str]] + preferences: Optional[List[Spread]] + max_replicas: Optional[int] + platforms: Optional[List[Platform]] @all_fields_optional class RestartPolicy(DockerCamelModel): - condition: str - delay: int - max_attempts: int - window: int + condition: Optional[str] + delay: Optional[int] + max_attempts: Optional[int] + window: Optional[int] @all_fields_optional class PluginPrivilege(DockerCamelModel): - name: str - description: str - value: List[str] + name: Optional[str] + description: Optional[str] + value: Optional[List[str]] @all_fields_optional class PluginSpec(DockerCamelModel): - name: str - remote: str - disabled: bool - plugin_privilege: List[PluginPrivilege] + name: Optional[str] + remote: Optional[str] + disabled: Optional[bool] + plugin_privilege: Optional[List[PluginPrivilege]] @all_fields_optional class ContainerSpec(DockerCamelModel): - image: str - labels: Dict[str, str] - command: List[str] - args: List[str] - hostname: str - env: List[str] - dir: str - user: str - groups: List[str] - privileges: Any - tty: bool = pydantic.Field(alias="TTY") - open_stdin: bool - read_only: bool - mounts: List[Any] - stop_signal: str - stop_grace_period: int - health_check: Any - hosts: List[str] - dns_config: Any - secrets: List[Any] - configs: List[Any] - isolation: str - init: bool - sysctls: Any + image: Optional[str] + labels: Optional[Dict[str, str]] + command: Optional[List[str]] + args: Optional[List[str]] + hostname: Optional[str] + env: Optional[List[str]] + dir: Optional[str] + user: Optional[str] + groups: Optional[List[str]] + privileges: Optional[Any] + tty: Optional[bool] = pydantic.Field(None, alias="TTY") + open_stdin: Optional[bool] + read_only: Optional[bool] + mounts: Optional[List[Any]] + stop_signal: Optional[str] + stop_grace_period: Optional[int] + health_check: Any = None + hosts: Optional[List[str]] + dns_config: Any = None + secrets: Optional[List[Any]] + configs: Optional[List[Any]] + isolation: Optional[str] + init: Optional[bool] + sysctls: Optional[Any] @all_fields_optional class NetworkAttachmentSpec(DockerCamelModel): - container_id: str = pydantic.Field(alias="ContainerID") + container_id: Optional[str] = pydantic.Field(None, alias="ContainerID") @all_fields_optional class ResourceObject(DockerCamelModel): - nano_cpus: int = pydantic.Field(alias="NanoCPUs") - memory_bytes: int - generic_resources: List[AssignedGenericResources] + nano_cpus: Optional[int] = pydantic.Field(None, alias="NanoCPUs") + memory_bytes: Optional[int] + generic_resources: Optional[List[AssignedGenericResources]] @all_fields_optional class Resources(DockerCamelModel): - limits: ResourceObject - reservation: ResourceObject + limits: Optional[ResourceObject] + reservation: Optional[ResourceObject] @all_fields_optional class TaskSpec(DockerCamelModel): # TODO: set types for Any - plugin_spec: PluginSpec - container_spec: ContainerSpec - network_attachment_spec: NetworkAttachmentSpec - resources: Resources - restart_policy: Any - placement: Placement - force_update: int - runtime: str - networks: List[NetworkAttachmentConfig] - log_driver: LogDriver + plugin_spec: Optional[PluginSpec] + container_spec: Optional[ContainerSpec] + network_attachment_spec: Optional[NetworkAttachmentSpec] + resources: Optional[Resources] + restart_policy: Any = None + placement: Optional[Placement] + force_update: Optional[int] + runtime: Optional[str] + networks: Optional[List[NetworkAttachmentConfig]] + log_driver: Optional[LogDriver] @all_fields_optional class TaskInspectResult(DockerCamelModel): - id: str = pydantic.Field(alias="ID") - version: ObjectVersion - created_at: datetime - updated_at: datetime - name: str - labels: Dict[str, str] - spec: TaskSpec - service_id: str = pydantic.Field(alias="ServiceID") - slot: int - node_id: str = pydantic.Field(alias="NodeID") - assigned_generic_resources: List[AssignedGenericResources] - status: TaskStatus - desired_state: str + id: Optional[str] = pydantic.Field(None, alias="ID") + version: Optional[ObjectVersion] + created_at: Optional[datetime] + updated_at: Optional[datetime] + name: Optional[str] + labels: Optional[Dict[str, str]] + spec: Optional[TaskSpec] + service_id: Optional[str] = pydantic.Field(None, alias="ServiceID") + slot: Optional[int] + node_id: Optional[str] = pydantic.Field(None, alias="NodeID") + assigned_generic_resources: Optional[List[AssignedGenericResources]] + status: Optional[TaskStatus] + desired_state: Optional[str] diff --git a/python_on_whales/components/volume/models.py b/python_on_whales/components/volume/models.py index 6923a52a..aba45d4f 100644 --- a/python_on_whales/components/volume/models.py +++ b/python_on_whales/components/volume/models.py @@ -1,17 +1,17 @@ from datetime import datetime from pathlib import Path -from typing import Any, Dict +from typing import Any, Dict, Optional from python_on_whales.utils import DockerCamelModel, all_fields_optional @all_fields_optional class VolumeInspectResult(DockerCamelModel): - name: str - driver: str - mountpoint: Path - created_at: datetime - status: Dict[str, Any] - labels: Dict[str, str] - scope: str - options: Dict[str, str] + name: Optional[str] + driver: Optional[str] + mountpoint: Optional[Path] + created_at: Optional[datetime] + status: Optional[Dict[str, Any]] + labels: Optional[Dict[str, str]] + scope: Optional[str] + options: Optional[Dict[str, str]] diff --git a/python_on_whales/utils.py b/python_on_whales/utils.py index 59f8ff89..a662c21c 100644 --- a/python_on_whales/utils.py +++ b/python_on_whales/utils.py @@ -3,6 +3,7 @@ import subprocess import sys from datetime import datetime, timedelta +from importlib.metadata import version from pathlib import Path from queue import Queue from subprocess import PIPE, Popen @@ -22,6 +23,7 @@ ) PROJECT_ROOT = Path(__file__).parents[1] +PYDANTIC_V2 = version("pydantic").startswith("2.") def title_if_necessary(string: str): @@ -70,7 +72,11 @@ def to_docker_camel(string): class DockerCamelModel(pydantic.BaseModel): class Config: alias_generator = to_docker_camel - allow_population_by_field_name = True + + if PYDANTIC_V2: + allow_population_by_field_name = True + else: + populate_by_name = True @overload @@ -296,9 +302,10 @@ def read_env_files(env_files: List[Path]) -> Dict[str, str]: def all_fields_optional(cls): """Decorator function used to modify a pydantic model's fields to all be optional.""" - for field in cls.__fields__.values(): - field.required = False - field.allow_none = True + if not PYDANTIC_V2: + for field in cls.__fields__.values(): + field.required = False + field.allow_none = True return cls diff --git a/tests/python_on_whales/components/buildx/test_buildx_cli_wrapper.py b/tests/python_on_whales/components/buildx/test_buildx_cli_wrapper.py index c13909c1..baec806f 100644 --- a/tests/python_on_whales/components/buildx/test_buildx_cli_wrapper.py +++ b/tests/python_on_whales/components/buildx/test_buildx_cli_wrapper.py @@ -41,7 +41,7 @@ def test_buildx_build(tmp_path): def test_buildx_build_streaming_logs(tmp_path): (tmp_path / "Dockerfile").write_text(dockerfile_content1) output = list(docker.buildx.build(tmp_path, stream_logs=True)) - assert output[0] == "#1 [internal] load build definition from Dockerfile\n" + assert "#1 [internal] load build definition from Dockerfile\n" in output assert "#6 DONE" in output[-1] @@ -56,7 +56,7 @@ def test_buildx_build_streaming_logs_with_decode_error_handling(tmp_path): ) (tmp_path / "Dockerfile").write_text(bad_encoding_dockerfile) output = list(docker.buildx.build(tmp_path, cache=False, stream_logs=True)) - assert output[0] == "#1 [internal] load build definition from Dockerfile\n" + assert "#1 [internal] load build definition from Dockerfile\n" in output assert len([x for x in output if "�" in x]) == 1 assert "#7 DONE" in output[-1]