Skip to content

Commit

Permalink
Use new json connections file
Browse files Browse the repository at this point in the history
Podman has updated where it will store its
system connection information to a new json
format file.
Add support to podman-py to read from both the
new json file and old toml file giving preference
to the new json file.

Signed-off-by: Urvashi Mohnani <[email protected]>
  • Loading branch information
umohnani8 committed Feb 19, 2024
1 parent 1585d91 commit 47fb327
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 11 deletions.
43 changes: 35 additions & 8 deletions podman/domain/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import urllib
from pathlib import Path
from typing import Dict, Optional
import json

import xdg.BaseDirectory

Expand Down Expand Up @@ -48,12 +49,16 @@ def id(self): # pylint: disable=invalid-name
@cached_property
def url(self):
"""urllib.parse.ParseResult: Returns URL for service connection."""
return urllib.parse.urlparse(self.attrs.get("uri"))
if self.attrs.get("uri"):
return urllib.parse.urlparse(self.attrs.get("uri"))
return urllib.parse.urlparse(self.attrs.get("URI"))

@cached_property
def identity(self):
"""Path: Returns Path to identity file for service connection."""
return Path(self.attrs.get("identity"))
if self.attrs.get("identity"):
return Path(self.attrs.get("identity"))
return Path(self.attrs.get("Identity"))


class PodmanConfig:
Expand All @@ -64,15 +69,22 @@ def __init__(self, path: Optional[str] = None):

if path is None:
home = Path(xdg.BaseDirectory.xdg_config_home)
self.path = home / "containers" / "containers.conf"
self.path = home / "containers" / "podman-connections.json"
old_toml_file = home / "containers" / "containers.conf"
else:
self.path = Path(path)

self.attrs = {}
if self.path.exists():
with self.path.open(encoding='utf-8') as file:
with open(self.path, encoding='utf-8') as file:
self.attrs = json.load(file)

# Read the old toml file configuration
if old_toml_file.exists():
with old_toml_file.open(encoding='utf-8') as file:
buffer = file.read()
self.attrs = toml_loads(buffer)
loaded_toml = toml_loads(buffer)
self.attrs.update(loaded_toml)

def __hash__(self) -> int:
return hash(tuple(self.path.name))
Expand Down Expand Up @@ -105,17 +117,32 @@ def services(self):
connection = ServiceConnection(key, attrs=destinations[key])
services[key] = connection

# read the new json file format
connection = self.attrs.get("Connection")
if connection:
destinations = connection.get("Connections")
for key in destinations:
connection = ServiceConnection(key, attrs=destinations[key])
services[key] = connection

return services

@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])

# 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")
for key in destinations:
if key == active:
return ServiceConnection(key, attrs=destinations[key])
return ServiceConnection(active, attrs=destinations[active])

return None
45 changes: 42 additions & 3 deletions podman/tests/unit/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from podman.domain.config import PodmanConfig


class PodmanConfigTestCase(unittest.TestCase):
class PodmanConfigTestCaseTOML(unittest.TestCase):
opener = mock.mock_open(
read_data="""
[containers]
Expand Down Expand Up @@ -35,7 +35,7 @@ def setUp(self) -> None:
super().setUp()

def mocked_open(self, *args, **kwargs):
return PodmanConfigTestCase.opener(self, *args, **kwargs)
return PodmanConfigTestCaseTOML.opener(self, *args, **kwargs)

self.mocked_open = mocked_open

Expand All @@ -49,10 +49,49 @@ def test_connections(self):
self.assertEqual(config.active_service.url, expected)
self.assertEqual(config.services["production"].identity, Path("/home/root/.ssh/id_rsa"))

PodmanConfigTestCase.opener.assert_called_with(
PodmanConfigTestCaseTOML.opener.assert_called_with(
Path("/home/developer/containers.conf"), encoding='utf-8'
)

class PodmanConfigTestCaseJSON(unittest.TestCase):
opener = mock.mock_open(
read_data="""
{
"Connection": {
"Default": "testing",
"Connections": {
"testing": {
"URI": "ssh://qe@localhost:2222/run/podman/podman.sock",
"Identity": "/home/qe/.ssh/id_rsa"
}
"production": {
"URI": "ssh://root@localhost:22/run/podman/podman.sock",
"Identity": "/home/root/.ssh/id_rsa"
}
}
},
"Farm": {}
}
"""
)

def setUp(self) -> None:
super().setUp()

def mocked_open(self, *args, **kwargs):
return PodmanConfigTestCaseJSON.opener(self, *args, **kwargs)

self.mocked_open = mocked_open

def test_connections(self):
with mock.patch.multiple(Path, open=self.mocked_open, exists=MagicMock(return_value=True)):
config = PodmanConfig("/home/developer/podman-connections.json")

self.assertEqual(config.active_service.id, "testing")

expected = urllib.parse.urlparse("ssh://qe@localhost:2222/run/podman/podman.sock")
self.assertEqual(config.active_service.url, expected)
self.assertEqual(config.services["production"].identity, Path("/home/root/.ssh/id_rsa"))

if __name__ == '__main__':
unittest.main()

0 comments on commit 47fb327

Please sign in to comment.