)]}'
{"glance/api/v1/images.py":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"44d07998167c3081aba528e6fdf678342541ded0","unresolved":false,"context_lines":[{"line_number":552,"context_line":"                logger.error(line)"},{"line_number":553,"context_line":"            self.notifier.error(\u0027image.update\u0027, msg)"},{"line_number":554,"context_line":"            raise HTTPBadRequest(msg, request\u003dreq, content_type\u003d\"text/plain\")"},{"line_number":555,"context_line":"        except exception.NotFound, e:"},{"line_number":556,"context_line":"            msg \u003d (\"Failed to find image to update: %(e)s\" % locals())"},{"line_number":557,"context_line":"            for line in msg.split(\u0027\\n\u0027):"},{"line_number":558,"context_line":"                logger.info(line)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAACH%2F%2F%2FKE%3D","line":555,"updated":"2011-08-24 18:33:29.000000000","message":"I don\u0027t believe this is necessary. There is a get_image_meta_or_404() method call above here that handles this...","commit_id":"94afb1a340127df248ab511784705b2f48755e0d"},{"author":{"_account_id":679,"name":"Kevin L. Mitchell","email":"klmitch@mit.edu","username":"klmitch"},"change_message_id":"5a95531f5bc3757e9ba9d900e83314116d0bac9d","unresolved":false,"context_lines":[{"line_number":552,"context_line":"                logger.error(line)"},{"line_number":553,"context_line":"            self.notifier.error(\u0027image.update\u0027, msg)"},{"line_number":554,"context_line":"            raise HTTPBadRequest(msg, request\u003dreq, content_type\u003d\"text/plain\")"},{"line_number":555,"context_line":"        except exception.NotFound, e:"},{"line_number":556,"context_line":"            msg \u003d (\"Failed to find image to update: %(e)s\" % locals())"},{"line_number":557,"context_line":"            for line in msg.split(\u0027\\n\u0027):"},{"line_number":558,"context_line":"                logger.info(line)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAACH%2F%2F%2FJU%3D","line":555,"in_reply_to":"AAAACH%2F%2F%2FKE%3D","updated":"2011-08-24 18:57:22.000000000","message":"As a matter of fact, it is required; registry.update_image_metadata() may now return 404 if the user doesn\u0027t have authorization to modify the image, even if they\u0027re able to see the image.  (Yes, something other than 404 would be better, but I was limited in what I could get back through the abstraction.)","commit_id":"94afb1a340127df248ab511784705b2f48755e0d"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"44d07998167c3081aba528e6fdf678342541ded0","unresolved":false,"context_lines":[{"line_number":592,"context_line":"                schedule_delete_from_backend(image[\u0027location\u0027], self.options,"},{"line_number":593,"context_line":"                                             req.context, id)"},{"line_number":594,"context_line":"            registry.delete_image_metadata(self.options, req.context, id)"},{"line_number":595,"context_line":"        except exception.NotFound, e:"},{"line_number":596,"context_line":"            msg \u003d (\"Failed to find image to delete: %(e)s\" % locals())"},{"line_number":597,"context_line":"            for line in msg.split(\u0027\\n\u0027):"},{"line_number":598,"context_line":"                logger.info(line)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAACH%2F%2F%2FKA%3D","line":595,"updated":"2011-08-24 18:33:29.000000000","message":"Same here. This shouldn\u0027t be necessary. get_image_meta_or_404 should take care of this.","commit_id":"94afb1a340127df248ab511784705b2f48755e0d"},{"author":{"_account_id":679,"name":"Kevin L. Mitchell","email":"klmitch@mit.edu","username":"klmitch"},"change_message_id":"5a95531f5bc3757e9ba9d900e83314116d0bac9d","unresolved":false,"context_lines":[{"line_number":592,"context_line":"                schedule_delete_from_backend(image[\u0027location\u0027], self.options,"},{"line_number":593,"context_line":"                                             req.context, id)"},{"line_number":594,"context_line":"            registry.delete_image_metadata(self.options, req.context, id)"},{"line_number":595,"context_line":"        except exception.NotFound, e:"},{"line_number":596,"context_line":"            msg \u003d (\"Failed to find image to delete: %(e)s\" % locals())"},{"line_number":597,"context_line":"            for line in msg.split(\u0027\\n\u0027):"},{"line_number":598,"context_line":"                logger.info(line)"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAACH%2F%2F%2FJM%3D","line":595,"in_reply_to":"AAAACH%2F%2F%2FKA%3D","updated":"2011-08-24 18:57:22.000000000","message":"Ibid—registry.delete_image_metadata() may now return 404 in case of lack of authorization.","commit_id":"94afb1a340127df248ab511784705b2f48755e0d"}],"glance/registry/db/api.py":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"44d07998167c3081aba528e6fdf678342541ded0","unresolved":false,"context_lines":[{"line_number":329,"context_line":""},{"line_number":330,"context_line":"            # Perform authorization check"},{"line_number":331,"context_line":"            if not context.is_image_mutable(image_ref):"},{"line_number":332,"context_line":"                raise exception.NotAuthorized(\"You do not own that image\")"},{"line_number":333,"context_line":"        else:"},{"line_number":334,"context_line":"            if \u0027size\u0027 in values:"},{"line_number":335,"context_line":"                values[\u0027size\u0027] \u003d int(values[\u0027size\u0027])"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAACH%2F%2F%2FJ8%3D","line":332,"updated":"2011-08-24 18:33:29.000000000","message":"Need to i18n these strings...\n\nAlso, you might want to DRY this and the same code block above into a method something like:\n\ndef check_image_is_mutable_or_403(self. image_ref, context):\n    if not context.is_image_mutable(image_ref):\n        logger.info(_(\"Attempted to modify image user did not own.\"))\n        msg \u003d _(\"You do not own this image\")\n        raise exception.NotAuthorized(msg)","commit_id":"94afb1a340127df248ab511784705b2f48755e0d"},{"author":{"_account_id":679,"name":"Kevin L. Mitchell","email":"klmitch@mit.edu","username":"klmitch"},"change_message_id":"5a95531f5bc3757e9ba9d900e83314116d0bac9d","unresolved":false,"context_lines":[{"line_number":329,"context_line":""},{"line_number":330,"context_line":"            # Perform authorization check"},{"line_number":331,"context_line":"            if not context.is_image_mutable(image_ref):"},{"line_number":332,"context_line":"                raise exception.NotAuthorized(\"You do not own that image\")"},{"line_number":333,"context_line":"        else:"},{"line_number":334,"context_line":"            if \u0027size\u0027 in values:"},{"line_number":335,"context_line":"                values[\u0027size\u0027] \u003d int(values[\u0027size\u0027])"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAACH%2F%2F%2FJI%3D","line":332,"in_reply_to":"AAAACH%2F%2F%2FJ8%3D","updated":"2011-08-24 18:57:22.000000000","message":"The original is such a short snippet of code that it made sense to just repeat it.  But once you include all the logging, suddenly this approach makes sense :)  There are a *ton* of places in glance where the logging idiom comes up; we really should try to figure out a way to factor that out and make it easier to do.","commit_id":"94afb1a340127df248ab511784705b2f48755e0d"}],"glance/registry/server.py":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"44d07998167c3081aba528e6fdf678342541ded0","unresolved":false,"context_lines":[{"line_number":673,"context_line":"    \"\"\""},{"line_number":674,"context_line":""},{"line_number":675,"context_line":"    def _fetch_memb(memb, attr_map):"},{"line_number":676,"context_line":"        return dict([(k, memb[v]) for k, v in attr_map.iteritems()"},{"line_number":677,"context_line":"                                  if v in memb.keys()])"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":"    # Return the list of members with the given attribute mapping"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAACH%2F%2F%2FJ4%3D","line":676,"updated":"2011-08-24 18:33:29.000000000","message":"Just FYI, you can use items() now instead of iteritems()...","commit_id":"94afb1a340127df248ab511784705b2f48755e0d"},{"author":{"_account_id":679,"name":"Kevin L. Mitchell","email":"klmitch@mit.edu","username":"klmitch"},"change_message_id":"5a95531f5bc3757e9ba9d900e83314116d0bac9d","unresolved":false,"context_lines":[{"line_number":673,"context_line":"    \"\"\""},{"line_number":674,"context_line":""},{"line_number":675,"context_line":"    def _fetch_memb(memb, attr_map):"},{"line_number":676,"context_line":"        return dict([(k, memb[v]) for k, v in attr_map.iteritems()"},{"line_number":677,"context_line":"                                  if v in memb.keys()])"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":"    # Return the list of members with the given attribute mapping"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAACH%2F%2F%2FJE%3D","line":676,"in_reply_to":"AAAACH%2F%2F%2FJ4%3D","updated":"2011-08-24 18:57:22.000000000","message":"Heh, not my code; must be Matt\u0027s.  Can\u0027t complain, though—it clearly fixes a bug I introduced :)","commit_id":"94afb1a340127df248ab511784705b2f48755e0d"}],"glance/tests/functional/__init__.py":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"44d07998167c3081aba528e6fdf678342541ded0","unresolved":false,"context_lines":[{"line_number":73,"context_line":"        :param test_dir: The directory where all test stuff is kept. This is"},{"line_number":74,"context_line":"                         passed from the FunctionalTestCase."},{"line_number":75,"context_line":"        :param port: The port to start a server up on."},{"line_number":76,"context_line":"        \"\"\""},{"line_number":77,"context_line":"        self.verbose \u003d True"},{"line_number":78,"context_line":"        self.debug \u003d True"},{"line_number":79,"context_line":"        self.no_venv \u003d False"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAACH%2F%2F%2FJ0%3D","line":76,"updated":"2011-08-24 18:33:29.000000000","message":"Excellent work in this file. :)","commit_id":"94afb1a340127df248ab511784705b2f48755e0d"},{"author":{"_account_id":679,"name":"Kevin L. Mitchell","email":"klmitch@mit.edu","username":"klmitch"},"change_message_id":"5a95531f5bc3757e9ba9d900e83314116d0bac9d","unresolved":false,"context_lines":[{"line_number":73,"context_line":"        :param test_dir: The directory where all test stuff is kept. This is"},{"line_number":74,"context_line":"                         passed from the FunctionalTestCase."},{"line_number":75,"context_line":"        :param port: The port to start a server up on."},{"line_number":76,"context_line":"        \"\"\""},{"line_number":77,"context_line":"        self.verbose \u003d True"},{"line_number":78,"context_line":"        self.debug \u003d True"},{"line_number":79,"context_line":"        self.no_venv \u003d False"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAACH%2F%2F%2FJA%3D","line":76,"in_reply_to":"AAAACH%2F%2F%2FJ0%3D","updated":"2011-08-24 18:57:22.000000000","message":"*bow*\n\nI\u0027ve actually had an idea for a different approach to establishing fixtures like this, using decorators.  I\u0027m in the process of bouncing it off a QE guy to see what he thinks about the general idea.  Something for the future...","commit_id":"94afb1a340127df248ab511784705b2f48755e0d"}],"glance/tests/functional/keystone_utils.py":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"44d07998167c3081aba528e6fdf678342541ded0","unresolved":false,"context_lines":[{"line_number":75,"context_line":"sql_connection \u003d %(sql_connection)s"},{"line_number":76,"context_line":"backend_entities \u003d [\u0027UserRoleAssociation\u0027, \u0027Endpoints\u0027, \u0027Role\u0027, \u0027Tenant\u0027,"},{"line_number":77,"context_line":"                    \u0027User\u0027, \u0027Credentials\u0027, \u0027EndpointTemplates\u0027, \u0027Token\u0027,"},{"line_number":78,"context_line":"                    \u0027Service\u0027]"},{"line_number":79,"context_line":"sql_idle_timeout \u003d 30"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"[pipeline:admin]"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAACH%2F%2F%2FJw%3D","line":78,"updated":"2011-08-24 18:33:29.000000000","message":"I\u0027m not even going to ask about the above config option...","commit_id":"94afb1a340127df248ab511784705b2f48755e0d"},{"author":{"_account_id":679,"name":"Kevin L. Mitchell","email":"klmitch@mit.edu","username":"klmitch"},"change_message_id":"5a95531f5bc3757e9ba9d900e83314116d0bac9d","unresolved":false,"context_lines":[{"line_number":75,"context_line":"sql_connection \u003d %(sql_connection)s"},{"line_number":76,"context_line":"backend_entities \u003d [\u0027UserRoleAssociation\u0027, \u0027Endpoints\u0027, \u0027Role\u0027, \u0027Tenant\u0027,"},{"line_number":77,"context_line":"                    \u0027User\u0027, \u0027Credentials\u0027, \u0027EndpointTemplates\u0027, \u0027Token\u0027,"},{"line_number":78,"context_line":"                    \u0027Service\u0027]"},{"line_number":79,"context_line":"sql_idle_timeout \u003d 30"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"[pipeline:admin]"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAACH%2F%2F%2FIo%3D","line":78,"in_reply_to":"AAAACH%2F%2F%2FJw%3D","updated":"2011-08-24 18:57:22.000000000","message":"Yeah, I don\u0027t know either; a lot of this is just straight-up c\u0026p from the example keystone.conf in the keystone repo…and it\u0027s been a while since I really climbed through the keystone code, which of course as you know has moved *very* rapidly...","commit_id":"94afb1a340127df248ab511784705b2f48755e0d"}],"glance/tests/functional/test_private_images.py":[{"author":{"_account_id":1032,"name":"Justin Shepherd","email":"jshepher@rackspace.com","username":"jshepher"},"change_message_id":"eb077a6ed3f6f94c0d501261f7e143b89b5a333a","unresolved":false,"context_lines":[{"line_number":180,"context_line":"        path \u003d \"http://%s:%d/v1/images/1\" % (\"0.0.0.0\", self.api_port)"},{"line_number":181,"context_line":"        http \u003d httplib2.Http()"},{"line_number":182,"context_line":"        response, content \u003d http.request(path, \u0027PUT\u0027, headers\u003dheaders)"},{"line_number":183,"context_line":"        self.assertEqual(response.status, 200)"},{"line_number":184,"context_line":"        data \u003d json.loads(content)"},{"line_number":185,"context_line":"        self.assertEqual(data[\u0027image\u0027][\u0027name\u0027], \"Image1\")"},{"line_number":186,"context_line":"        self.assertEqual(data[\u0027image\u0027][\u0027is_public\u0027], True)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAACH%2F%2F%2B6M%3D","line":183,"updated":"2011-08-27 18:13:19.000000000","message":"Is a 200 the correct response for this operation. The user is posting a new metadata value, and a 200 indicates that it was successful (except it was not). Considering the same operation by the admin (line:372) gives the same response code but actually changes the metadata value.","commit_id":"a43658be760454b437941a3603a2f91986b4aa40"},{"author":{"_account_id":1032,"name":"Justin Shepherd","email":"jshepher@rackspace.com","username":"jshepher"},"change_message_id":"900705ff53b9ecd4e515eab99b3a675921c34487","unresolved":false,"context_lines":[{"line_number":180,"context_line":"        path \u003d \"http://%s:%d/v1/images/1\" % (\"0.0.0.0\", self.api_port)"},{"line_number":181,"context_line":"        http \u003d httplib2.Http()"},{"line_number":182,"context_line":"        response, content \u003d http.request(path, \u0027PUT\u0027, headers\u003dheaders)"},{"line_number":183,"context_line":"        self.assertEqual(response.status, 200)"},{"line_number":184,"context_line":"        data \u003d json.loads(content)"},{"line_number":185,"context_line":"        self.assertEqual(data[\u0027image\u0027][\u0027name\u0027], \"Image1\")"},{"line_number":186,"context_line":"        self.assertEqual(data[\u0027image\u0027][\u0027is_public\u0027], True)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAACH%2F%2F%2B5w%3D","line":183,"in_reply_to":"AAAACH%2F%2F%2B6A%3D","updated":"2011-08-29 15:23:08.000000000","message":"Ok.. works for me","commit_id":"a43658be760454b437941a3603a2f91986b4aa40"},{"author":{"_account_id":679,"name":"Kevin L. Mitchell","email":"klmitch@mit.edu","username":"klmitch"},"change_message_id":"d1c38aff5c10f9a07e24b9f8035ba9e2495cc184","unresolved":false,"context_lines":[{"line_number":180,"context_line":"        path \u003d \"http://%s:%d/v1/images/1\" % (\"0.0.0.0\", self.api_port)"},{"line_number":181,"context_line":"        http \u003d httplib2.Http()"},{"line_number":182,"context_line":"        response, content \u003d http.request(path, \u0027PUT\u0027, headers\u003dheaders)"},{"line_number":183,"context_line":"        self.assertEqual(response.status, 200)"},{"line_number":184,"context_line":"        data \u003d json.loads(content)"},{"line_number":185,"context_line":"        self.assertEqual(data[\u0027image\u0027][\u0027name\u0027], \"Image1\")"},{"line_number":186,"context_line":"        self.assertEqual(data[\u0027image\u0027][\u0027is_public\u0027], True)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAACH%2F%2F%2B6A%3D","line":183,"in_reply_to":"AAAACH%2F%2F%2B6M%3D","updated":"2011-08-29 14:57:53.000000000","message":"Yes, 200 is what the code returns.  Basically, owner is ignored unless the user is an admin.  I figured they could see the failure by comparing the return entity\u0027s owner field with the one they specified.  I chose this route because this policy is implemented in the controller, rather than the database API, and at the controller, I don\u0027t have the image itself, only its ID: thus, I can\u0027t tell if \u0027owner\u0027 is different from the value given for the image.  If I raised an error if \u0027owner\u0027 was in the submitted entity, then I disable the ability to take an image metadata on the client side, change one value in it, and PUT the full thing back.  There are things I could do, like rearchitecting db_api.image_update() to take an image_ref instead of an image_id, or implementing the policy in the db_api—neither of which I really like.  (For other policy I needed in db_api, I delegate to methods in the context, but this felt more difficult to implement that way.)","commit_id":"a43658be760454b437941a3603a2f91986b4aa40"}]}
