-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add docker container status card on summary page
- Loading branch information
Showing
10 changed files
with
151 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
from rich.table import Table | ||
from textual import on | ||
from textual.app import ComposeResult | ||
from textual.containers import Container | ||
from textual.widgets import Static, Button | ||
|
||
from service_locator import ServiceLocator | ||
|
||
|
||
class DockerCard(Container): | ||
DEFAULT_CSS = """ | ||
DockerCard { | ||
width: 60; | ||
} | ||
""" | ||
BORDER_TITLE = "Docker containers" | ||
|
||
def __init__(self, **kwargs): | ||
super().__init__(**kwargs, classes="card") | ||
self._docker_panel = Static(id="system_panel") | ||
|
||
def compose(self) -> ComposeResult: | ||
yield self._docker_panel | ||
yield Button("[underline]Refresh", id="refresh-docker_panel") | ||
|
||
def on_mount(self) -> None: | ||
table = Table( | ||
show_header=False, | ||
box=None, | ||
) | ||
table.add_column() | ||
table.add_column() | ||
docker_client = ServiceLocator.docker_client() | ||
for container, status in docker_client.list_container_names().items(): | ||
table.add_row(f"[label]{container}", f"[{self._color_by_status(status)}]{status.capitalize()}") | ||
self._docker_panel.update(table) | ||
|
||
@staticmethod | ||
def _color_by_status(status: str) -> str: | ||
if status == "running" or status == "running (healthy)": | ||
return "green" | ||
elif status == "paused" or status.startswith("running ("): | ||
return "yellow" | ||
elif status.startswith("exited"): | ||
return "red" | ||
else: | ||
return "grey39" | ||
|
||
@on(Button.Pressed, "#refresh-docker_panel") | ||
def refresh_docker_panel(self) -> None: | ||
self.on_mount() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,59 @@ | ||
import os | ||
from enum import Enum | ||
from typing import Literal | ||
|
||
import docker | ||
import yaml | ||
|
||
from models.app_context import AppContext | ||
from .base_service import BaseService | ||
|
||
|
||
class ContainerStatus(Enum): | ||
NA = "n/a" | ||
RUNNING = "Running" | ||
|
||
class DockerClient(BaseService): | ||
def __init__(self): | ||
self.client = docker.from_env() | ||
def __init__(self, context: AppContext): | ||
self._client = docker.from_env() | ||
self._context = context | ||
|
||
def get_running_containers(self) -> list: | ||
"""Fetches a list of running containers.""" | ||
return self.client.containers.list() | ||
""" | ||
Fetches a list of running containers. | ||
""" | ||
return self._client.containers.list(all=True) | ||
|
||
def get_container_logs(self, container_id): | ||
"""Fetches logs from a specific container.""" | ||
container = self.client.containers.get(container_id) | ||
# return container.logs(follow=True, tail=1000) | ||
""" | ||
Fetches logs from a specific container. | ||
""" | ||
container = self._client.containers.get(container_id) | ||
return container.logs(stream=True, follow=True) | ||
|
||
def list_container_names(self) -> dict[str, str]: | ||
""" | ||
List docker containers names and their statuses. | ||
""" | ||
project = self._context.current_project | ||
basename = os.path.basename(project.path) | ||
container_names = {} | ||
running_containers = self.get_running_containers() | ||
for compose_file in project.docker_compose_files: | ||
file_path = os.path.join(project.path, compose_file) | ||
with open(file_path, 'r') as file: | ||
docker_compose = yaml.safe_load(file) | ||
|
||
services = docker_compose.get("services", {}) | ||
for service_name, service_config in services.items(): | ||
container_name = service_config.get("container_name", f"{basename}-{service_name}") | ||
container_names[container_name] = ContainerStatus.NA.value | ||
|
||
for running_container in running_containers: | ||
if running_container.name.startswith(container_name): | ||
container_names[container_name] = running_container.status | ||
if "Health" in running_container.attrs["State"]: | ||
container_names[container_name] += f" ({running_container.attrs["State"]["Health"]["Status"]})" | ||
break | ||
|
||
return container_names |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters