-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update config.py #439
base: main
Are you sure you want to change the base?
Update config.py #439
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,16 @@ | ||
"""Read containers.conf file.""" | ||
"""Read containers.conf file and create Podman containers with network options.""" | ||
|
||
import sys | ||
import urllib | ||
from pathlib import Path | ||
from typing import Dict, Optional | ||
import json | ||
import logging | ||
|
||
from podman.api import cached_property | ||
from podman.api.path_utils import get_xdg_config_home | ||
from podman import PodmanClient | ||
from podman.errors import PodmanError | ||
|
||
if sys.version_info >= (3, 11): | ||
from tomllib import loads as toml_loads | ||
|
@@ -65,7 +68,6 @@ class PodmanConfig: | |
|
||
def __init__(self, path: Optional[str] = None): | ||
"""Read Podman configuration from users XDG_CONFIG_HOME.""" | ||
|
||
self.is_default = False | ||
if path is None: | ||
home = Path(get_xdg_config_home()) | ||
|
@@ -101,7 +103,7 @@ def __init__(self, path: Optional[str] = None): | |
) from e | ||
|
||
# Read the old toml file configuration | ||
if self.is_default and old_toml_file.exists(): | ||
if self.is_default and old_toml_file and old_toml_file.exists(): | ||
with old_toml_file.open(encoding='utf-8') as file: | ||
buffer = file.read() | ||
loaded_toml = toml_loads(buffer) | ||
|
@@ -124,17 +126,17 @@ def id(self): # pylint: disable=invalid-name | |
def services(self): | ||
"""Dict[str, ServiceConnection]: Returns list of service connections. | ||
|
||
Examples: | ||
podman_config = PodmanConfig() | ||
address = podman_config.services["testing"] | ||
print(f"Testing service address {address}") | ||
""" | ||
Examples: | ||
podman_config = PodmanConfig() | ||
address = podman_config.services["testing"] | ||
print(f"Testing service address {address}") | ||
""" | ||
services: Dict[str, ServiceConnection] = {} | ||
|
||
# read the keys of the toml file first | ||
engine = self.attrs.get("engine") | ||
if engine: | ||
destinations = engine.get("service_destinations") | ||
destinations = engine.get("service_destinations", {}) | ||
for key in destinations: | ||
connection = ServiceConnection(key, attrs=destinations[key]) | ||
services[key] = connection | ||
|
@@ -145,7 +147,7 @@ def services(self): | |
# json one | ||
connection = self.attrs.get("Connection") | ||
if connection: | ||
destinations = connection.get("Connections") | ||
destinations = connection.get("Connections", {}) | ||
for key in destinations: | ||
connection = ServiceConnection(key, attrs=destinations[key]) | ||
services[key] = connection | ||
|
@@ -155,19 +157,128 @@ def services(self): | |
@cached_property | ||
def active_service(self): | ||
"""Optional[ServiceConnection]: Returns active connection.""" | ||
|
||
# read the new json file format | ||
connection = self.attrs.get("Connection") | ||
if connection: | ||
active = connection.get("Default") | ||
destinations = connection.get("Connections") | ||
return ServiceConnection(active, attrs=destinations[active]) | ||
destinations = connection.get("Connections", {}) | ||
if active in destinations: | ||
return ServiceConnection(active, attrs=destinations[active]) | ||
|
||
# if we are here, that means there was no default in the new json file | ||
engine = self.attrs.get("engine") | ||
if engine: | ||
active = engine.get("active_service") | ||
destinations = engine.get("service_destinations") | ||
return ServiceConnection(active, attrs=destinations[active]) | ||
destinations = engine.get("service_destinations", {}) | ||
if active in destinations: | ||
return ServiceConnection(active, attrs=destinations[active]) | ||
|
||
return None | ||
|
||
@cached_property | ||
def network_options(self) -> Dict[str, list]: | ||
""" | ||
Retrieves network options for all configured networks. | ||
|
||
Returns: | ||
Dict[str, list]: A dictionary where keys are network names and values are lists of options. | ||
""" | ||
network_opts = {} | ||
network_config = self.attrs.get("network", {}) | ||
for network_name, config in network_config.items(): | ||
# Assuming network options are stored as 'pasta_options', 'bridge_options', etc. | ||
options_key = f"{network_name}_options" | ||
if options_key in network_config: | ||
network_opts[network_name] = network_config[options_key] | ||
Comment on lines
+187
to
+192
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. besides pasta_options none of the other fields exists in containers.conf so it should not invent anything. |
||
return network_opts | ||
|
||
|
||
def create_container_with_pasta(network_name: str, port_mapping: str, image: str, container_name: str, **kwargs): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is nothing special about pasta API wise, all the networks settings should be able to be set already via the normal API. |
||
""" | ||
Creates and starts a Podman container with specified Pasta network options. | ||
|
||
Args: | ||
network_name (str): The name of the network (e.g., 'pasta'). | ||
port_mapping (str): The port mapping in 'host_port:container_port' format (e.g., '3128:3128'). | ||
image (str): The container image to use. | ||
container_name (str): The name for the container. | ||
**kwargs: Additional keyword arguments for container creation. | ||
|
||
Returns: | ||
podman.containers.Container: The created and started container instance. | ||
""" | ||
try: | ||
# Initialize Podman client | ||
podman_client = PodmanClient(base_url="unix://run/podman/io.podman") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line relates to the fix above |
||
logging.debug("Podman client initialized.") | ||
|
||
# Read Podman configuration | ||
podman_config = PodmanConfig() | ||
logging.debug("Podman configuration loaded.") | ||
|
||
# Extract network options for the specified network | ||
network_opts = podman_config.network_options.get(network_name, []) | ||
logging.debug(f"Original network options for '{network_name}': {network_opts}") | ||
|
||
# Append the port mapping using '-T' flag | ||
network_opts += ["-T", port_mapping] | ||
logging.debug(f"Updated network options for '{network_name}': {network_opts}") | ||
Comment on lines
+223
to
+225
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks wrong, -T maps container ports to the host and you allow only one string. Overall I don't follow this at all. |
||
|
||
# Create the container with network options | ||
logging.info(f"Creating container '{container_name}' with image '{image}' on network '{network_name}' with options {network_opts}") | ||
|
||
container = podman_client.containers.create( | ||
image=image, | ||
name=container_name, | ||
networks={network_name: {}}, | ||
network_options={network_name: network_opts}, | ||
**kwargs # Include other parameters like environment variables, volumes, etc. | ||
) | ||
logging.info(f"Container '{container_name}' created successfully.") | ||
|
||
# Start the container | ||
container.start() | ||
logging.info(f"Container '{container_name}' started successfully.") | ||
|
||
return container | ||
|
||
except PodmanError as pe: | ||
logging.error(f"Podman error occurred: {pe}") | ||
raise | ||
except PermissionError as pe: | ||
logging.error(f"Permission error: {pe}") | ||
raise | ||
except Exception as e: | ||
logging.error(f"An unexpected error occurred: {e}") | ||
raise | ||
|
||
|
||
if __name__ == "__main__": | ||
try: | ||
# Define container parameters | ||
network_name = "pasta" # Replace with your network name if different | ||
port_mapping = "3128:3128" # Host port : Container port | ||
image = "your-image" # Replace with your actual image | ||
container_name = "your-container" # Replace with your desired container name | ||
|
||
# Additional parameters (if any) | ||
additional_kwargs = { | ||
# Example: Environment variables | ||
# "environment": {"ENV_VAR": "value"}, | ||
# Example: Volume mounts | ||
# "volumes": {"/host/path": {"bind": "/container/path", "mode": "rw"}}, | ||
} | ||
|
||
# Create and start the container | ||
container = create_container_with_pasta( | ||
network_name=network_name, | ||
port_mapping=port_mapping, | ||
image=image, | ||
container_name=container_name, | ||
**additional_kwargs | ||
) | ||
|
||
print(f"Container '{container.name}' is running with TCP namespace forwarding from host port {port_mapping.split(':')[0]} to container port {port_mapping.split(':')[1]}.") | ||
|
||
except Exception as e: | ||
print(f"Failed to create and start container: {e}") | ||
Comment on lines
+256
to
+284
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am perplexed about the There are circular imports failures related to it, so I would remove it. The example looks nice though so actually it could be documented. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is giving a circular import. Please, remove it. There are ways to call the client such as
podman_client = self.client