[lxc-devel] [pylxd/master] Add image aliases support.

pcdummy on Github lxc-bot at linuxcontainers.org
Mon Jul 25 16:56:49 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 432 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160725/cc5cb38f/attachment.bin>
-------------- next part --------------
From d7e482f1f402f8e7eca67c5f4458bf8915ccdd2f Mon Sep 17 00:00:00 2001
From: Rene Jochum <rene at jochums.at>
Date: Mon, 25 Jul 2016 18:55:09 +0200
Subject: [PATCH] Add image aliases support.

Signed-off-by: Rene Jochum <rene at jochums.at>
---
 doc/source/images.rst     |   3 ++
 pylxd/image.py            |  24 +++++++++-
 pylxd/tests/mock_lxd.py   |  50 +++++++++++++------
 pylxd/tests/test_image.py | 120 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 181 insertions(+), 16 deletions(-)

diff --git a/doc/source/images.rst b/doc/source/images.rst
index 6c22152..574a7c8 100644
--- a/doc/source/images.rst
+++ b/doc/source/images.rst
@@ -49,6 +49,9 @@ Image methods
   - `export` - Export the image. Returns binary data that is the
     image itself.
 
+  - `add_alias` - Add an alias to the image.
+
+  - `delete_alias` - Remove an alias.
 
 Examples
 --------
diff --git a/pylxd/image.py b/pylxd/image.py
index 4cca19e..560a378 100644
--- a/pylxd/image.py
+++ b/pylxd/image.py
@@ -19,7 +19,7 @@
 
 class Image(model.Model):
     """A LXD Image."""
-    aliases = model.Attribute()
+    aliases = model.Attribute(readonly=True)
     auto_update = model.Attribute()
     architecture = model.Attribute()
     cached = model.Attribute()
@@ -84,3 +84,25 @@ def export(self):
         """Export the image."""
         response = self.api.export.get()
         return response.content
+
+    def add_alias(self, name, description):
+        """Add an alias to the image."""
+        self.client.api.images.aliases.post(json={
+            'description': description,
+            'target': self.fingerprint,
+            'name': name
+        })
+
+        # Update current aliases list
+        self.sync()
+
+        return self
+
+    def delete_alias(self, name, wait=False):
+        """Delete an alias from the image."""
+        self.client.api.images.aliases[name].delete()
+
+        # Update current aliases list
+        self.sync()
+
+        return self
diff --git a/pylxd/tests/mock_lxd.py b/pylxd/tests/mock_lxd.py
index 5dbea19..2947116 100644
--- a/pylxd/tests/mock_lxd.py
+++ b/pylxd/tests/mock_lxd.py
@@ -366,26 +366,12 @@ def profile_GET(request, context):
         'url': r'^http://pylxd.test/1.0/images$',
     },
     {
-        'json': {
-            'type': 'sync',
-            'status': 'Success',
-            'status_code': 200,
-            'metadata': {
-                'name': 'an-alias',
-                'description': 'an-alias',
-                'target': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',  # NOQA
-            }
-        },
-        'method': 'GET',
-        'url': r'^http://pylxd.test/1.0/images/aliases/an-alias$',
-    },
-    {
         'text': json.dumps({
             'type': 'sync',
             'metadata': {
                 'aliases': [
                     {
-                        'name': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',  # NOQA
+                        'name': 'an-alias',  # NOQA
                         'fingerprint': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',  # NOQA
                     }
                 ],
@@ -424,6 +410,40 @@ def profile_GET(request, context):
         'url': r'^http://pylxd.test/1.0/images/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855$',  # NOQA
     },
 
+    # Image Aliases
+    {
+        'json': {
+            'type': 'sync',
+            'status': 'Success',
+            'status_code': 200,
+            'metadata': {
+                'name': 'an-alias',
+                'description': 'an-alias',
+                'target': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',  # NOQA
+            }
+        },
+        'method': 'GET',
+        'url': r'^http://pylxd.test/1.0/images/aliases/an-alias$',
+    },
+    {
+        'json': {
+            'type': 'sync',
+            'status': 'Success',
+            'metadata': None
+        },
+        'method': 'POST',
+        'url': r'^http://pylxd.test/1.0/images/aliases$'
+    },
+    {
+        'json': {
+            'type': 'sync',
+            'status': 'Success',
+            'status_code': 200,
+            'metadata': None
+        },
+        'method': 'DELETE',
+        'url': r'^http://pylxd.test/1.0/images/aliases/an-alias$'
+    },
 
     # Networks
     {
diff --git a/pylxd/tests/test_image.py b/pylxd/tests/test_image.py
index 756e56f..6822865 100644
--- a/pylxd/tests/test_image.py
+++ b/pylxd/tests/test_image.py
@@ -180,3 +180,123 @@ def error(request, context):
         a_image = self.client.images.all()[0]
 
         self.assertRaises(exceptions.LXDAPIException, a_image.export)
+
+    def test_add_alias(self):
+        """Try to add an alias."""
+        def updated_image(request, context):
+            context.status_code = 200
+            return json.dumps({
+                'type': 'sync',
+                'metadata': {
+                    'aliases': [
+                        {
+                            'name': 'an-alias',  # NOQA
+                            'fingerprint': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'  # NOQA
+                        },
+                        {
+                            'name': 'lol',
+                            'fingerprint': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'  # NOQA
+                        }
+                    ],
+                    'architecture': 'x86_64',
+                    'cached': False,
+                    'filename': 'a_image.tar.bz2',
+                    'fingerprint': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',  # NOQA
+                    'public': False,
+                    'properties': {},
+                    'size': 1,
+                    'auto_update': False,
+                    'created_at': '1983-06-16T02:42:00Z',
+                    'expires_at': '1983-06-16T02:42:00Z',
+                    'last_used_at': '1983-06-16T02:42:00Z',
+                    'uploaded_at': '1983-06-16T02:42:00Z',
+                }
+            })
+
+        a_image = self.client.images.all()[0]
+        self.add_rule({
+            'text': updated_image,
+            'method': 'GET',
+            'url': r'^http://pylxd.test/1.0/images/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855$',  # NOQA
+        })
+
+        a_image.add_alias('lol', 'Just LOL')
+
+        aliases = [a['name'] for a in a_image.aliases]
+        self.assertTrue('lol' in aliases, "Image didn't get updated.")
+
+    def test_add_alias_duplicate(self):
+        """Adding a alias twice should raise an LXDAPIException."""
+        def error(request, context):
+            context.status_code = 409
+            return json.dumps({
+                'type': 'error',
+                'error': 'already exists',
+                'error_code': 409})
+        self.add_rule({
+            'text': error,
+            'method': 'POST',
+            'url': r'^http://pylxd.test/1.0/images/aliases$',  # NOQA
+        })
+
+        a_image = self.client.images.all()[0]
+
+        self.assertRaises(
+            exceptions.LXDAPIException,
+            a_image.add_alias,
+            'lol', 'Just LOL'
+        )
+
+    def test_remove_alias(self):
+        """Try to remove an-alias."""
+        def updated_image(request, context):
+            context.status_code = 200
+            return json.dumps({
+                'type': 'sync',
+                'metadata': {
+                    'aliases': [],
+                    'architecture': 'x86_64',
+                    'cached': False,
+                    'filename': 'a_image.tar.bz2',
+                    'fingerprint': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',  # NOQA
+                    'public': False,
+                    'properties': {},
+                    'size': 1,
+                    'auto_update': False,
+                    'created_at': '1983-06-16T02:42:00Z',
+                    'expires_at': '1983-06-16T02:42:00Z',
+                    'last_used_at': '1983-06-16T02:42:00Z',
+                    'uploaded_at': '1983-06-16T02:42:00Z',
+                }
+            })
+
+        a_image = self.client.images.all()[0]
+        self.add_rule({
+            'text': updated_image,
+            'method': 'GET',
+            'url': r'^http://pylxd.test/1.0/images/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855$',  # NOQA
+        })
+
+        a_image.delete_alias('an-alias')
+        self.assertEqual(0, len(a_image.aliases), "Alias didn't get deleted.")
+
+    def test_remove_alias_error(self):
+        """Try to remove an non existant alias."""
+        def error(request, context):
+            context.status_code = 404
+            return json.dumps({
+                'type': 'error',
+                'error': 'not found',
+                'error_code': 404})
+        self.add_rule({
+            'text': error,
+            'method': 'DELETE',
+            'url': r'^http://pylxd.test/1.0/images/aliases/lol$',  # NOQA
+        })
+
+        a_image = self.client.images.all()[0]
+        self.assertRaises(
+            exceptions.LXDAPIException,
+            a_image.delete_alias,
+            'lol'
+        )


More information about the lxc-devel mailing list