Skip to content

Commit 9ed9248

Browse files
committed
Add http service tests
Signed-off-by: Sagi Shnaidman <[email protected]>
1 parent d1b5338 commit 9ed9248

File tree

8 files changed

+561
-512
lines changed

8 files changed

+561
-512
lines changed

.github/workflows/podman_container_api.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,17 @@ jobs:
4141
matrix:
4242
ansible-version:
4343
- ansible<2.10
44-
- git+https://github.com/ansible/ansible.git@stable-2.15
44+
# - git+https://github.com/ansible/ansible.git@stable-2.17
4545
- git+https://github.com/ansible/ansible.git@devel
4646
os:
4747
- ubuntu-22.04
4848
python-version:
49-
- "3.10"
49+
- "3.11"
5050
podman-version:
5151
- unstable
5252
include:
5353
- os: ubuntu-22.04
54-
ansible-version: git+https://github.com/ansible/ansible.git@stable-2.15
54+
ansible-version: git+https://github.com/ansible/ansible.git@stable-2.17
5555
python-version: "3.10"
5656
podman-version: stable
5757

@@ -108,6 +108,7 @@ jobs:
108108
python3 -m pip install --user -r requirements.txt
109109
podman system service --time=0 unix:///tmp/podman.sock &
110110
sudo podman system service --time=0 unix:///tmp/root-podman.sock &
111+
podman system service --time=0 tcp:localhost:25771 &
111112
112113
echo $ANSIBLE_CONFIG
113114
command -v ansible-playbook

plugins/module_utils/podman/common.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,18 @@
1717
try:
1818
from distutils.version import LooseVersion # noqa: F401
1919
except ImportError as exc:
20-
raise_from(ImportError('To use this plugin or module with ansible-core'
21-
' < 2.11, you need to use Python < 3.12 with '
22-
'distutils.version present'), exc)
20+
raise_from(
21+
ImportError(
22+
"To use this plugin or module with ansible-core"
23+
" < 2.11, you need to use Python < 3.12 with "
24+
"distutils.version present"
25+
),
26+
exc,
27+
)
2328
try:
2429
import requests # pylint: disable=unused-import
2530
from .podman_api import PodmanAPIClient
31+
2632
HAS_REQUESTS = True
2733
except ImportError:
2834
PodmanAPIClient = object
@@ -380,8 +386,8 @@ def createcommand(argument, info_config, boolean_type=False):
380386
all_values = []
381387
# Remove command args from the list
382388
container_cmd = info_config.get("cmd")
383-
if container_cmd and container_cmd == cr_com[-len(container_cmd):]:
384-
cr_com = cr_com[:-len(container_cmd)]
389+
if container_cmd and container_cmd == cr_com[-len(container_cmd) :]:
390+
cr_com = cr_com[: -len(container_cmd)]
385391
for arg in argument_values:
386392
for ind, cr_opt in enumerate(cr_com):
387393
if arg == cr_opt:
@@ -456,10 +462,9 @@ def diff_generic(params, info_config, module_arg, cmd_arg, boolean_type=False):
456462

457463
class PodmanAPI:
458464
def __init__(self, module, module_params):
459-
if module_params.get('podman_socket') and not HAS_REQUESTS:
460-
module.fail_json(
461-
msg="Requests module is not installed while socket was provided!")
462-
self.client = PodmanAPIClient(module_params.get('podman_socket'))
465+
if module_params.get("podman_socket") and not HAS_REQUESTS:
466+
module.fail_json(msg="Requests module is not installed while socket was provided!")
467+
self.client = PodmanAPIClient(module_params.get("podman_socket"))
463468
try:
464469
self.client.version()
465470
except Exception as api_error:

plugins/module_utils/podman/podman_api.py

Lines changed: 41 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
1-
21
# The follwing code is taken from
32
# https://github.com/msabramo/requests-unixsocket/blob/master/
43
# requests_unixsocket/adapters.py
5-
from __future__ import (absolute_import, division, print_function)
4+
from __future__ import absolute_import, division, print_function
65

76
import socket
7+
88
try:
99
import requests
1010
from requests.adapters import HTTPAdapter
1111
from requests.compat import urlparse, unquote, quote
12+
1213
HAS_REQUESTS = True
1314
except ImportError:
1415
HAS_REQUESTS = False
1516

1617
try:
1718
from requests.packages import urllib3
19+
1820
HAS_URLLIB3 = True
1921
except ImportError:
2022
try:
2123
import urllib3
24+
2225
HAS_URLLIB3 = True
2326
except ImportError:
2427
HAS_URLLIB3 = False
@@ -34,7 +37,7 @@
3437
__metaclass__ = type
3538

3639

37-
DEFAULT_SCHEME = 'http+unix://'
40+
DEFAULT_SCHEME = "http+unix://"
3841

3942

4043
class PodmanAPIError(Exception):
@@ -51,7 +54,7 @@ def __init__(self, unix_socket_url, timeout=60):
5154
netloc is a percent-encoded path to a unix domain socket. E.g.:
5255
'http+unix://%2Ftmp%2Fprofilesvc.sock/status/pid'
5356
"""
54-
super(UnixHTTPConnection, self).__init__('localhost', timeout=timeout)
57+
super(UnixHTTPConnection, self).__init__("localhost", timeout=timeout)
5558
self.unix_socket_url = unix_socket_url
5659
self.timeout = timeout
5760
self.sock = None
@@ -69,11 +72,11 @@ def connect(self):
6972

7073

7174
if HAS_URLLIB3:
75+
7276
class UnixHTTPConnectionPool(urllib3.connectionpool.HTTPConnectionPool):
7377

7478
def __init__(self, socket_path, timeout=60):
75-
super(UnixHTTPConnectionPool, self).__init__(
76-
'localhost', timeout=timeout)
79+
super(UnixHTTPConnectionPool, self).__init__("localhost", timeout=timeout)
7780
self.socket_path = socket_path
7881
self.timeout = timeout
7982

@@ -82,22 +85,20 @@ def _new_conn(self):
8285

8386

8487
if HAS_REQUESTS:
88+
8589
class UnixAdapter(HTTPAdapter):
8690

8791
def __init__(self, *args, timeout=60, pool_connections=25, **kwargs):
8892
super(UnixAdapter, self).__init__(*args, **kwargs)
8993
self.timeout = timeout
90-
self.pools = urllib3._collections.RecentlyUsedContainer(
91-
pool_connections, dispose_func=lambda p: p.close()
92-
)
94+
self.pools = urllib3._collections.RecentlyUsedContainer(pool_connections, dispose_func=lambda p: p.close())
9395

9496
def get_connection(self, url, proxies=None):
9597
proxies = proxies or {}
9698
proxy = proxies.get(urlparse(url.lower()).scheme)
9799

98100
if proxy:
99-
raise ValueError('%s does not support specifying proxies'
100-
% self.__class__.__name__)
101+
raise ValueError("%s does not support specifying proxies" % self.__class__.__name__)
101102

102103
with self.pools.lock:
103104
pool = self.pools.get(url)
@@ -117,6 +118,7 @@ def close(self):
117118

118119

119120
if HAS_REQUESTS:
121+
120122
class APISession(requests.Session):
121123
def __init__(self, *args, url_scheme=DEFAULT_SCHEME, **kwargs):
122124
super(APISession, self).__init__(*args, **kwargs)
@@ -125,9 +127,7 @@ def __init__(self, *args, url_scheme=DEFAULT_SCHEME, **kwargs):
125127

126128
class PodmanAPIHTTP:
127129
def __init__(self, base_url, scheme=DEFAULT_SCHEME):
128-
self.api_url = "".join((scheme,
129-
quote(base_url, safe=""),
130-
"/v2.0.0/libpod"))
130+
self.api_url = "".join((scheme, quote(base_url, safe=""), "/v2.0.0/libpod"))
131131
if scheme == "http://":
132132
self.api_url = "".join((scheme, base_url, "/v2.0.0/libpod"))
133133
self.session = APISession()
@@ -136,28 +136,28 @@ def request(self, method, url, **kwargs):
136136
return self.session.request(method=method, url=self.api_url + url, **kwargs)
137137

138138
def get(self, url, **kwargs):
139-
kwargs.setdefault('allow_redirects', True)
140-
return self.request('get', url, **kwargs)
139+
kwargs.setdefault("allow_redirects", True)
140+
return self.request("get", url, **kwargs)
141141

142142
def head(self, url, **kwargs):
143-
kwargs.setdefault('allow_redirects', False)
144-
return self.request('head', url, **kwargs)
143+
kwargs.setdefault("allow_redirects", False)
144+
return self.request("head", url, **kwargs)
145145

146146
def post(self, url, data=None, json=None, **kwargs):
147-
return self.request('post', url, data=data, json=json, **kwargs)
147+
return self.request("post", url, data=data, json=json, **kwargs)
148148

149149
def patch(self, url, data=None, **kwargs):
150-
return self.request('patch', url, data=data, **kwargs)
150+
return self.request("patch", url, data=data, **kwargs)
151151

152152
def put(self, url, data=None, **kwargs):
153-
return self.request('put', url, data=data, **kwargs)
153+
return self.request("put", url, data=data, **kwargs)
154154

155155
def delete(self, url, **kwargs):
156-
return self.request('delete', url, **kwargs)
156+
return self.request("delete", url, **kwargs)
157157

158158
def options(self, url, **kwargs):
159-
kwargs.setdefault('allow_redirects', True)
160-
return self.request('options', url, **kwargs)
159+
kwargs.setdefault("allow_redirects", True)
160+
return self.request("options", url, **kwargs)
161161

162162

163163
class PodmanAPIClient:
@@ -166,10 +166,7 @@ def __init__(self, base_url):
166166
raise PodmanAPIError("requests package is required for podman API")
167167
socket_opt = urlparse(base_url)
168168
if socket_opt.scheme not in ("unix", "http"):
169-
raise PodmanAPIError("Scheme %s is not supported! Use %s" % (
170-
socket_opt.scheme,
171-
DEFAULT_SCHEME
172-
))
169+
raise PodmanAPIError("Scheme %s is not supported! Use %s" % (socket_opt.scheme, DEFAULT_SCHEME))
173170
if socket_opt.scheme == "http":
174171
self.api = PodmanAPIHTTP(socket_opt.netloc, "http://")
175172
else:
@@ -178,8 +175,7 @@ def __init__(self, base_url):
178175
self.images = PodmanAPIImages(api=self.api)
179176

180177
def version(self):
181-
response = self.api.get(
182-
'/version')
178+
response = self.api.get("/version")
183179
return response.json()
184180

185181

@@ -188,8 +184,7 @@ def __init__(self, api):
188184
self.api = api
189185
self.quote = quote
190186

191-
def list(
192-
self, all_=None, filters=None, limit=None, size=None, sync=None):
187+
def list(self, all_=None, filters=None, limit=None, size=None, sync=None):
193188
"""List all images for a Podman service."""
194189
query = {}
195190
if all_ is not None:
@@ -213,14 +208,12 @@ def create(self, **container_data):
213208
)
214209
if response.ok:
215210
return response.json()
216-
raise PodmanAPIError("Container %s failed to create! Error: %s" %
217-
(container_data.get('name'), response.text))
211+
raise PodmanAPIError("Container %s failed to create! Error: %s" % (container_data.get("name"), response.text))
218212

219213
def get(self, name):
220-
response = self.api.get(
221-
'/containers/{0}/json'.format(self.quote(name)))
214+
response = self.api.get("/containers/{0}/json".format(self.quote(name)))
222215
data = response.json()
223-
if data.get('response') == 404:
216+
if data.get("response") == 404:
224217
data = {}
225218
# raise Exception("Container %s not found!" % name)
226219
return data
@@ -253,8 +246,7 @@ def restart(self, name):
253246

254247
def remove(self, name, force=False):
255248
_ = self.api.delete( # pylint: disable=blacklisted-name
256-
"/containers/{0}".format(self.quote(name)),
257-
params={"force": force}
249+
"/containers/{0}".format(self.quote(name)), params={"force": force}
258250
)
259251
return
260252

@@ -266,31 +258,26 @@ def __init__(self, api):
266258
self.inspect = self.get
267259

268260
def exists(self, name):
269-
response = self.api.get(
270-
'/images/{0}/exists'.format(self.quote(name)))
261+
response = self.api.get("/images/{0}/exists".format(self.quote(name)))
271262
return response.status_code == 204
272263

273264
def pull(self, reference):
274-
response = self.api.post(
275-
'/images/pull',
276-
params={'reference': reference}
277-
)
265+
response = self.api.post("/images/pull", params={"reference": reference})
278266
if response.ok:
279-
correct_response = {'stream': '', 'text': response.text}
267+
correct_response = {"stream": "", "text": response.text}
280268
for i in response.text.splitlines():
281269
if '"images"' in i:
282-
correct_response['images'] = json.loads(i)['images']
270+
correct_response["images"] = json.loads(i)["images"]
283271
if '"id"' in i:
284-
correct_response['id'] = json.loads(i)['id']
272+
correct_response["id"] = json.loads(i)["id"]
285273
elif '"stream"' in i:
286-
correct_response['stream'] += json.loads(i)['stream']
274+
correct_response["stream"] += json.loads(i)["stream"]
287275
elif '"error"' in i:
288-
correct_response['error'] = json.loads(i)['error']
289-
correct_response['code'] = response.status_code
276+
correct_response["error"] = json.loads(i)["error"]
277+
correct_response["code"] = response.status_code
290278
return correct_response
291-
return {"error": "HTTP %s Error: %s" % (response.json()['message'])}
279+
return {"error": "HTTP %s Error: %s" % (response.json()["message"])}
292280

293281
def get(self, name):
294-
response = self.api.get(
295-
'/images/{0}/json'.format(self.quote(name)))
282+
response = self.api.get("/images/{0}/json".format(self.quote(name)))
296283
return response.json()

0 commit comments

Comments
 (0)