From dbed97a24df2fb74e4989fb15c912252f8a8bb07 Mon Sep 17 00:00:00 2001
From: Huanxuan Ao <huanxuan.ao@easystack.cn>
Date: Tue, 28 Jun 2016 14:39:00 +0800
Subject: [PATCH] Add "--property" option to "flavor create" command

Add "--property" option to "flavor create" command to support
adding properties to a new falvor.

Change-Id: I4f06b364375d5a81584fe41122d48e9568fa712a
Closes-Bug: #1596798
---
 doc/source/command-objects/flavor.rst         |  5 +++++
 functional/tests/compute/v2/test_flavor.py    | 22 +++++++++++--------
 openstackclient/compute/v2/flavor.py          | 21 +++++++++++++++---
 openstackclient/tests/compute/v2/fakes.py     |  1 +
 .../tests/compute/v2/test_flavor.py           | 20 +++++++++++++----
 .../notes/bug-1596798-b22fd587bdca8b36.yaml   |  4 ++++
 6 files changed, 57 insertions(+), 16 deletions(-)
 create mode 100644 releasenotes/notes/bug-1596798-b22fd587bdca8b36.yaml

diff --git a/doc/source/command-objects/flavor.rst b/doc/source/command-objects/flavor.rst
index a886b9ff1a..9ea504c1be 100644
--- a/doc/source/command-objects/flavor.rst
+++ b/doc/source/command-objects/flavor.rst
@@ -21,6 +21,7 @@ Create new flavor
         [--vcpus <num-cpu>]
         [--rxtx-factor <factor>]
         [--public | --private]
+        [--property <key=value> [...] ]
         [--project <project>]
         [--project-domain <project-domain>]
         <flavor-name>
@@ -61,6 +62,10 @@ Create new flavor
 
     Flavor is not available to other projects
 
+.. option:: --property <key=value>
+
+    Property to add for this flavor (repeat option to set multiple properties)
+
 .. option:: --project <project>
 
     Allow <project> to access private flavor (name or ID)
diff --git a/functional/tests/compute/v2/test_flavor.py b/functional/tests/compute/v2/test_flavor.py
index 2bb075bd59..6edb1fdfec 100644
--- a/functional/tests/compute/v2/test_flavor.py
+++ b/functional/tests/compute/v2/test_flavor.py
@@ -25,7 +25,8 @@ class FlavorTests(test.TestCase):
     @classmethod
     def setUpClass(cls):
         opts = cls.get_show_opts(cls.FIELDS)
-        raw_output = cls.openstack('flavor create ' + cls.NAME + opts)
+        raw_output = cls.openstack(
+            'flavor create --property a=b --property c=d ' + cls.NAME + opts)
         expected = cls.NAME + '\n'
         cls.assertOutput(expected, raw_output)
 
@@ -47,19 +48,22 @@ class FlavorTests(test.TestCase):
 
     def test_flavor_properties(self):
         opts = self.get_show_opts(['properties'])
-
-        raw_output = self.openstack(
-            'flavor set --property a=b --property c=d ' + self.NAME
-        )
-        self.assertEqual('', raw_output)
-
+        # check the properties we added in create command.
         raw_output = self.openstack('flavor show ' + self.NAME + opts)
         self.assertEqual("a='b', c='d'\n", raw_output)
 
         raw_output = self.openstack(
-            'flavor unset --property a ' + self.NAME
+            'flavor set --property e=f --property g=h ' + self.NAME
         )
         self.assertEqual('', raw_output)
 
         raw_output = self.openstack('flavor show ' + self.NAME + opts)
-        self.assertEqual("c='d'\n", raw_output)
+        self.assertEqual("a='b', c='d', e='f', g='h'\n", raw_output)
+
+        raw_output = self.openstack(
+            'flavor unset --property a --property c ' + self.NAME
+        )
+        self.assertEqual('', raw_output)
+
+        raw_output = self.openstack('flavor show ' + self.NAME + opts)
+        self.assertEqual("e='f', g='h'\n", raw_output)
diff --git a/openstackclient/compute/v2/flavor.py b/openstackclient/compute/v2/flavor.py
index 01d7da75ff..000df59899 100644
--- a/openstackclient/compute/v2/flavor.py
+++ b/openstackclient/compute/v2/flavor.py
@@ -121,6 +121,13 @@ class CreateFlavor(command.ShowOne):
             action="store_false",
             help=_("Flavor is not available to other projects")
         )
+        parser.add_argument(
+            "--property",
+            metavar="<key=value>",
+            action=parseractions.KeyValueAction,
+            help=_("Property to add for this flavor "
+                   "(repeat option to set multiple properties)")
+        )
         parser.add_argument(
             '--project',
             metavar='<project>',
@@ -150,8 +157,7 @@ class CreateFlavor(command.ShowOne):
             parsed_args.public
         )
 
-        flavor = compute_client.flavors.create(*args)._info.copy()
-        flavor.pop("links")
+        flavor = compute_client.flavors.create(*args)
 
         if parsed_args.project:
             try:
@@ -166,8 +172,17 @@ class CreateFlavor(command.ShowOne):
                 msg = _("Failed to add project %(project)s access to "
                         "flavor: %(e)s")
                 LOG.error(msg % {'project': parsed_args.project, 'e': e})
+        if parsed_args.property:
+            try:
+                flavor.set_keys(parsed_args.property)
+            except Exception as e:
+                LOG.error(_("Failed to set flavor property: %s"), e)
 
-        return zip(*sorted(six.iteritems(flavor)))
+        flavor_info = flavor._info.copy()
+        flavor_info.pop("links")
+        flavor_info['properties'] = utils.format_dict(flavor.get_keys())
+
+        return zip(*sorted(six.iteritems(flavor_info)))
 
 
 class DeleteFlavor(command.Command):
diff --git a/openstackclient/tests/compute/v2/fakes.py b/openstackclient/tests/compute/v2/fakes.py
index b7f17fbc93..a7a66d5e1f 100644
--- a/openstackclient/tests/compute/v2/fakes.py
+++ b/openstackclient/tests/compute/v2/fakes.py
@@ -716,6 +716,7 @@ class FakeFlavor(object):
             'OS-FLV-DISABLED:disabled': False,
             'os-flavor-access:is_public': True,
             'OS-FLV-EXT-DATA:ephemeral': 0,
+            'properties': {'property': 'value'},
         }
 
         # Overwrite default attributes.
diff --git a/openstackclient/tests/compute/v2/test_flavor.py b/openstackclient/tests/compute/v2/test_flavor.py
index da76b6d706..20ae8706f6 100644
--- a/openstackclient/tests/compute/v2/test_flavor.py
+++ b/openstackclient/tests/compute/v2/test_flavor.py
@@ -56,6 +56,7 @@ class TestFlavorCreate(TestFlavor):
         'id',
         'name',
         'os-flavor-access:is_public',
+        'properties',
         'ram',
         'rxtx_factor',
         'swap',
@@ -68,6 +69,7 @@ class TestFlavorCreate(TestFlavor):
         flavor.id,
         flavor.name,
         flavor.is_public,
+        utils.format_dict(flavor.properties),
         flavor.ram,
         flavor.rxtx_factor,
         flavor.swap,
@@ -116,7 +118,6 @@ class TestFlavorCreate(TestFlavor):
     def test_flavor_create_all_options(self):
 
         arglist = [
-            self.flavor.name,
             '--id', self.flavor.id,
             '--ram', str(self.flavor.ram),
             '--disk', str(self.flavor.disk),
@@ -125,9 +126,10 @@ class TestFlavorCreate(TestFlavor):
             '--vcpus', str(self.flavor.vcpus),
             '--rxtx-factor', str(self.flavor.rxtx_factor),
             '--public',
+            '--property', 'property=value',
+            self.flavor.name,
         ]
         verifylist = [
-            ('name', self.flavor.name),
             ('id', self.flavor.id),
             ('ram', self.flavor.ram),
             ('disk', self.flavor.disk),
@@ -136,6 +138,8 @@ class TestFlavorCreate(TestFlavor):
             ('vcpus', self.flavor.vcpus),
             ('rxtx_factor', self.flavor.rxtx_factor),
             ('public', True),
+            ('property', {'property': 'value'}),
+            ('name', self.flavor.name),
         ]
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
 
@@ -152,6 +156,8 @@ class TestFlavorCreate(TestFlavor):
         )
         columns, data = self.cmd.take_action(parsed_args)
         self.flavors_mock.create.assert_called_once_with(*args)
+        self.flavor.set_keys.assert_called_once_with({'property': 'value'})
+        self.flavor.get_keys.assert_called_once_with()
 
         self.assertEqual(self.columns, columns)
         self.assertEqual(self.data, data)
@@ -160,7 +166,6 @@ class TestFlavorCreate(TestFlavor):
 
         self.flavor.is_public = False
         arglist = [
-            self.flavor.name,
             '--id', self.flavor.id,
             '--ram', str(self.flavor.ram),
             '--disk', str(self.flavor.disk),
@@ -170,9 +175,11 @@ class TestFlavorCreate(TestFlavor):
             '--rxtx-factor', str(self.flavor.rxtx_factor),
             '--private',
             '--project', identity_fakes.project_id,
+            '--property', 'key1=value1',
+            '--property', 'key2=value2',
+            self.flavor.name,
         ]
         verifylist = [
-            ('name', self.flavor.name),
             ('id', self.flavor.id),
             ('ram', self.flavor.ram),
             ('disk', self.flavor.disk),
@@ -182,6 +189,8 @@ class TestFlavorCreate(TestFlavor):
             ('rxtx_factor', self.flavor.rxtx_factor),
             ('public', False),
             ('project', identity_fakes.project_id),
+            ('property', {'key1': 'value1', 'key2': 'value2'}),
+            ('name', self.flavor.name),
         ]
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
 
@@ -202,6 +211,9 @@ class TestFlavorCreate(TestFlavor):
             self.flavor.id,
             identity_fakes.project_id,
         )
+        self.flavor.set_keys.assert_called_with(
+            {'key1': 'value1', 'key2': 'value2'})
+        self.flavor.get_keys.assert_called_with()
         self.assertEqual(self.columns, columns)
         self.assertEqual(self.data, data)
 
diff --git a/releasenotes/notes/bug-1596798-b22fd587bdca8b36.yaml b/releasenotes/notes/bug-1596798-b22fd587bdca8b36.yaml
new file mode 100644
index 0000000000..6ab833da16
--- /dev/null
+++ b/releasenotes/notes/bug-1596798-b22fd587bdca8b36.yaml
@@ -0,0 +1,4 @@
+---
+features:
+  - Add ``--property`` option to ``flavor create`` command.
+    [Bug `1596798 <https://bugs.launchpad.net/bugs/1596798>`_]