[lxc-devel] [pylxd/master] Add mode/uid/gid to the container put method
ajkavanagh on Github
lxc-bot at linuxcontainers.org
Tue Feb 6 13:00:16 UTC 2018
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 522 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180206/a91acdad/attachment.bin>
-------------- next part --------------
From cc434441d918b05c55289ec5de156ffdcee19583 Mon Sep 17 00:00:00 2001
From: Kees Bos <cornelis.bos at gmail.com>
Date: Thu, 22 Dec 2016 15:23:48 +0100
Subject: [PATCH 1/3] Handle mode/uid/gid in FilesManager.put()
---
pylxd/models/container.py | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/pylxd/models/container.py b/pylxd/models/container.py
index f2c8f91..7f7281e 100644
--- a/pylxd/models/container.py
+++ b/pylxd/models/container.py
@@ -78,7 +78,20 @@ def __init__(self, client, container):
self._client = client
self._container = container
- def put(self, filepath, data):
+ def put(self, filepath, data, mode=None, uid=None, gid=None):
+
+ if isinstance(mode, int):
+ mode = oct(mode)
+ elif not mode.startswith('0'):
+ mode = '0{0}'.format(mode)
+ headers = {}
+ if mode is not None:
+ headers['X-LXD-mode'] = mode
+ if uid is not None:
+ headers['X-LXD-uid'] = str(uid)
+ if gid is not None:
+ headers['X-LXD-gid'] = str(gid)
+
response = self._client.api.containers[
self._container.name].files.post(
params={'path': filepath}, data=data)
From 23791a13c5e30226786ce0045f923f43e94ad5b7 Mon Sep 17 00:00:00 2001
From: Kees Bos <cornelis.bos at gmail.com>
Date: Fri, 27 Jan 2017 09:41:19 +0100
Subject: [PATCH 2/3] Fix FilesManager.put mode checking
---
pylxd/models/container.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/pylxd/models/container.py b/pylxd/models/container.py
index 7f7281e..03f031b 100644
--- a/pylxd/models/container.py
+++ b/pylxd/models/container.py
@@ -80,12 +80,12 @@ def __init__(self, client, container):
def put(self, filepath, data, mode=None, uid=None, gid=None):
- if isinstance(mode, int):
- mode = oct(mode)
- elif not mode.startswith('0'):
- mode = '0{0}'.format(mode)
headers = {}
if mode is not None:
+ if isinstance(mode, int):
+ mode = oct(mode)
+ elif not mode.startswith('0'):
+ mode = '0{0}'.format(mode)
headers['X-LXD-mode'] = mode
if uid is not None:
headers['X-LXD-uid'] = str(uid)
From 4a9292c0bcd10048f705e5dbdb5c3f4e07f23e38 Mon Sep 17 00:00:00 2001
From: Alex Kavanagh <alex at ajkavanagh.co.uk>
Date: Tue, 6 Feb 2018 12:56:40 +0000
Subject: [PATCH 3/3] Fix up file mode to work on Py3 and add tests/docs
Fix up the file mode str-ing to work with Python 3.
Add tests to check that headers are being set according to policy.
Add docstring to the `put` method to describe how to use the feature.
---
pylxd/models/container.py | 44 ++++++++++++++++++++++--------
pylxd/tests/models/test_container.py | 53 +++++++++++++++++++++++++++++++++---
2 files changed, 82 insertions(+), 15 deletions(-)
diff --git a/pylxd/models/container.py b/pylxd/models/container.py
index 03f031b..bc7f984 100644
--- a/pylxd/models/container.py
+++ b/pylxd/models/container.py
@@ -79,22 +79,45 @@ def __init__(self, client, container):
self._container = container
def put(self, filepath, data, mode=None, uid=None, gid=None):
-
+ """Push a file to the container.
+
+ This pushes a single file to the containers file system named by
+ the `filepath`.
+
+ :param filepath: The path in the container to to store the data in.
+ :type filepath: str
+ :param data: The data to store in the file.
+ :type data: bytes or str
+ :param mode: The unit mode to store the file with. The default of
+ None stores the file with the current mask of 0700, which is
+ the lxd default.
+ :type mode: oct | int | str
+ :param uid: The uid to use inside the container. Default of None
+ results in 0 (root).
+ :type uid: int
+ :param gid: The gid to use inside the container. Default of None
+ results in 0 (root).
+ :type gid: int
+ :returns: True if the file store succeeded otherwise False.
+ :rtype: Bool
+ """
headers = {}
if mode is not None:
if isinstance(mode, int):
- mode = oct(mode)
- elif not mode.startswith('0'):
- mode = '0{0}'.format(mode)
+ mode = format(mode, 'o')
+ if not isinstance(mode, six.string_types):
+ raise ValueError("'mode' parameter must be int or string")
+ if not mode.startswith('0'):
+ mode = '0{}'.format(mode)
headers['X-LXD-mode'] = mode
if uid is not None:
headers['X-LXD-uid'] = str(uid)
if gid is not None:
headers['X-LXD-gid'] = str(gid)
-
- response = self._client.api.containers[
- self._container.name].files.post(
- params={'path': filepath}, data=data)
+ response = (self._client.api.containers[self._container.name]
+ .files.post(params={'path': filepath},
+ data=data,
+ headers=headers or None))
return response.status_code == 200
def delete_available(self):
@@ -114,9 +137,8 @@ def delete(self, filepath):
'File Deletion is not available for this host')
def get(self, filepath):
- response = self._client.api.containers[
- self._container.name].files.get(
- params={'path': filepath})
+ response = (self._client.api.containers[self._container.name]
+ .files.get(params={'path': filepath}))
return response.content
@classmethod
diff --git a/pylxd/tests/models/test_container.py b/pylxd/tests/models/test_container.py
index f32ceff..72b3bff 100644
--- a/pylxd/tests/models/test_container.py
+++ b/pylxd/tests/models/test_container.py
@@ -436,7 +436,9 @@ def test_put_delete(self):
data = 'The quick brown fox'
res = self.container.files.put('/tmp/putted', data)
- self.assertEqual(True, res, msg='Failed to put file, result: {}'.format(res)) # NOQA
+ self.assertEqual(True, res,
+ msg=('Failed to put file, result: {}'
+ .format(res))) # NOQA
# we are mocked, so delete should initially not be available
self.assertEqual(False, self.container.files.delete_available())
@@ -462,7 +464,48 @@ def test_put_delete(self):
self.assertEqual(True, self.container.files.delete_available())
res = self.container.files.delete('/tmp/putted')
- self.assertEqual(True, res, msg='Failed to delete file, result: {}'.format(res)) # NOQA
+ self.assertEqual(True, res,
+ msg=('Failed to delete file, result: {}'
+ .format(res))) # NOQA
+
+ def test_put_mode_uid_gid(self):
+ """Should be able to set the mode, uid and gid of a file"""
+ # fix up the default POST rule to allow us to see the posted vars
+ _capture = {}
+
+ def capture(request, context):
+ _capture['headers'] = getattr(request._request, 'headers')
+ context.status_code = 200
+
+ rule = {
+ 'text': capture,
+ 'method': 'POST',
+ 'url': (r'^http://pylxd.test/1.0/containers/an-container/files'
+ '\?path=%2Ftmp%2Fputted$'), # NOQA
+ }
+ self.add_rule(rule)
+
+ data = 'The quick brown fox'
+ # start with an octal mode
+ res = self.container.files.put('/tmp/putted', data, mode=0o123,
+ uid=1, gid=2)
+ self.assertEqual(True, res,
+ msg=('Failed to put file, result: {}'
+ .format(res))) # NOQA
+ headers = _capture['headers']
+ self.assertEqual(headers['X-LXD-mode'], '0123')
+ self.assertEqual(headers['X-LXD-uid'], '1')
+ self.assertEqual(headers['X-LXD-gid'], '2')
+ # use a str mode this type
+ res = self.container.files.put('/tmp/putted', data, mode='456')
+ self.assertEqual(True, res,
+ msg=('Failed to put file, result: {}'
+ .format(res))) # NOQA
+ headers = _capture['headers']
+ self.assertEqual(headers['X-LXD-mode'], '0456')
+ # check that assertion is raised
+ with self.assertRaises(ValueError):
+ res = self.container.files.put('/tmp/putted', data, mode=object)
def test_get(self):
"""A file is retrieved from the container."""
@@ -477,7 +520,8 @@ def not_found(request, context):
rule = {
'text': not_found,
'method': 'GET',
- 'url': r'^http://pylxd.test/1.0/containers/an-container/files\?path=%2Ftmp%2Fgetted$', # NOQA
+ 'url': (r'^http://pylxd.test/1.0/containers/an-container/files'
+ '\?path=%2Ftmp%2Fgetted$'), # NOQA
}
self.add_rule(rule)
@@ -492,7 +536,8 @@ def not_found(request, context):
rule = {
'text': not_found,
'method': 'GET',
- 'url': r'^http://pylxd.test/1.0/containers/an-container/files\?path=%2Ftmp%2Fgetted$', # NOQA
+ 'url': (r'^http://pylxd.test/1.0/containers/an-container/files'
+ '\?path=%2Ftmp%2Fgetted$'), # NOQA
}
self.add_rule(rule)
More information about the lxc-devel
mailing list