From 78312ca9afea22f6511f2421dccb0736f394e9c8 Mon Sep 17 00:00:00 2001
From: Rajasi Kulkarni <rajasikulkarni18@gmail.com>
Date: Mon, 22 Aug 2016 00:26:46 +0530
Subject: [PATCH] Add option "--name" to command "openstack object create"

Option "--name" can be used to set as the object name of
the file to be uploaded in the container. Similar to option
"--object-name" in command "swift upload". Added unit test case
to ensure an exception is raised when using option "--name" for
uploading multiple objects.

Change-Id: Ied7827841f6ca1cf9d4b48e304cbe5d62eda38ab
Closes-Bug: #1607972
---
 doc/source/command-objects/object.rst         |  5 +++++
 openstackclient/api/object_store_v1.py        | 11 ++++++++--
 openstackclient/object/v1/object.py           | 14 +++++++++++-
 openstackclient/tests/unit/object/v1/fakes.py |  2 ++
 .../tests/unit/object/v1/test_object_all.py   | 22 +++++++++++++++++++
 .../notes/bug-1607972-a910a9fbdb81da57.yaml   |  5 +++++
 6 files changed, 56 insertions(+), 3 deletions(-)
 create mode 100644 releasenotes/notes/bug-1607972-a910a9fbdb81da57.yaml

diff --git a/doc/source/command-objects/object.rst b/doc/source/command-objects/object.rst
index 5aaad8a526..11dfd30e98 100644
--- a/doc/source/command-objects/object.rst
+++ b/doc/source/command-objects/object.rst
@@ -13,9 +13,14 @@ Upload object to container
 .. code:: bash
 
     os object create
+        [--name <name>]
         <container>
         <filename> [<filename> ...]
 
+.. option:: --name <name>
+
+    Upload a file and rename it. Can only be used when uploading a single object
+
 .. describe:: <container>
 
     Container for new object
diff --git a/openstackclient/api/object_store_v1.py b/openstackclient/api/object_store_v1.py
index faa55118e9..184814c610 100644
--- a/openstackclient/api/object_store_v1.py
+++ b/openstackclient/api/object_store_v1.py
@@ -214,6 +214,7 @@ class APIv1(api.BaseAPI):
         self,
         container=None,
         object=None,
+        name=None,
     ):
         """Create an object inside a container
 
@@ -221,6 +222,8 @@ class APIv1(api.BaseAPI):
             name of container to store object
         :param string object:
             local path to object
+        :param string name:
+            name of object to create
         :returns:
             dict of returned headers
         """
@@ -229,8 +232,12 @@ class APIv1(api.BaseAPI):
             # TODO(dtroyer): What exception to raise here?
             return {}
 
+        # For uploading a file, if name is provided then set it as the
+        # object's name in the container.
+        object_name_str = name if name else object
+
         full_url = "%s/%s" % (urllib.parse.quote(container),
-                              urllib.parse.quote(object))
+                              urllib.parse.quote(object_name_str))
         with io.open(object, 'rb') as f:
             response = self.create(
                 full_url,
@@ -240,7 +247,7 @@ class APIv1(api.BaseAPI):
         data = {
             'account': self._find_account_id(),
             'container': container,
-            'object': object,
+            'object': object_name_str,
             'x-trans-id': response.headers.get('X-Trans-Id'),
             'etag': response.headers.get('Etag'),
         }
diff --git a/openstackclient/object/v1/object.py b/openstackclient/object/v1/object.py
index db61d638e4..88f6815e80 100644
--- a/openstackclient/object/v1/object.py
+++ b/openstackclient/object/v1/object.py
@@ -19,6 +19,7 @@ import logging
 
 from osc_lib.cli import parseractions
 from osc_lib.command import command
+from osc_lib import exceptions
 from osc_lib import utils
 import six
 
@@ -44,10 +45,20 @@ class CreateObject(command.Lister):
             nargs="+",
             help='Local filename(s) to upload',
         )
+        parser.add_argument(
+            '--name',
+            metavar='<name>',
+            help='Upload a file and rename it. '
+                 'Can only be used when uploading a single object'
+        )
         return parser
 
     def take_action(self, parsed_args):
-
+        if parsed_args.name:
+            if len(parsed_args.objects) > 1:
+                msg = _('Attempting to upload multiple objects and '
+                        'using --name is not permitted')
+                raise exceptions.CommandError(msg)
         results = []
         for obj in parsed_args.objects:
             if len(obj) > 1024:
@@ -57,6 +68,7 @@ class CreateObject(command.Lister):
             data = self.app.client_manager.object_store.object_create(
                 container=parsed_args.container,
                 object=obj,
+                name=parsed_args.name,
             )
             results.append(data)
 
diff --git a/openstackclient/tests/unit/object/v1/fakes.py b/openstackclient/tests/unit/object/v1/fakes.py
index 0ff594bce0..72646d25bb 100644
--- a/openstackclient/tests/unit/object/v1/fakes.py
+++ b/openstackclient/tests/unit/object/v1/fakes.py
@@ -75,6 +75,8 @@ OBJECT_2 = {
     'last_modified': object_modified_2,
 }
 
+object_upload_name = 'test-object-name'
+
 
 class TestObjectv1(utils.TestCommand):
 
diff --git a/openstackclient/tests/unit/object/v1/test_object_all.py b/openstackclient/tests/unit/object/v1/test_object_all.py
index a0948b1bcf..f215836ed0 100644
--- a/openstackclient/tests/unit/object/v1/test_object_all.py
+++ b/openstackclient/tests/unit/object/v1/test_object_all.py
@@ -13,6 +13,7 @@
 
 import copy
 
+from osc_lib import exceptions
 from requests_mock.contrib import fixture
 
 from openstackclient.object.v1 import object as object_cmds
@@ -35,6 +36,27 @@ class TestObjectCreate(TestObjectAll):
         # Get the command object to test
         self.cmd = object_cmds.CreateObject(self.app, None)
 
+    def test_multiple_object_create_with_object_name(self):
+        arglist = [
+            object_fakes.container_name,
+            object_fakes.object_name_1,
+            object_fakes.object_name_2,
+            '--name', object_fakes.object_upload_name,
+        ]
+
+        verifylist = [
+            ('container', object_fakes.container_name),
+            ('objects', [object_fakes.object_name_1,
+                         object_fakes.object_name_2]),
+            ('name', object_fakes.object_upload_name),
+        ]
+
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+        self.assertRaises(exceptions.CommandError,
+                          self.cmd.take_action,
+                          parsed_args)
+
 
 class TestObjectList(TestObjectAll):
 
diff --git a/releasenotes/notes/bug-1607972-a910a9fbdb81da57.yaml b/releasenotes/notes/bug-1607972-a910a9fbdb81da57.yaml
new file mode 100644
index 0000000000..0e3872ea0e
--- /dev/null
+++ b/releasenotes/notes/bug-1607972-a910a9fbdb81da57.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - Add ``--name`` option to command ``object create``
+    for uploading a file and renaming it.
+    [Bug `1607972 <https://bugs.launchpad.net/bugs/1607972>`_]