)]}'
{"shade/operatorcloud.py":[{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"e8530fa47832e0074755e406f80c8a23f68b6df2","unresolved":false,"context_lines":[{"line_number":1325,"context_line":""},{"line_number":1326,"context_line":"    def list_roles_for_user(self, user_name_or_id, project\u003dNone):"},{"line_number":1327,"context_line":"        \"\"\"List Keystone v2 roles assigned to a user"},{"line_number":1328,"context_line":""},{"line_number":1329,"context_line":"        :param string user_name_or_id: name or id of user."},{"line_number":1330,"context_line":"        :param string project: name or id of project."},{"line_number":1331,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"9a68dd71_c172a6ad","line":1328,"updated":"2016-01-20 13:47:04.000000000","message":"We really don\u0027t want to have separate APIs for different versions of things. The idea behind shade is to hide version differences so users don\u0027t have to think so much about it.\n\nWe already have a list_roles_assignments() that can accept a filter for users. I\u0027d suggest a discussion around how we might make that one work for v2. And that should probably be done in a separate review.","commit_id":"4e41ca94e1d0895bcdf96b4308b012d7a6e0f168"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"e8530fa47832e0074755e406f80c8a23f68b6df2","unresolved":false,"context_lines":[{"line_number":1532,"context_line":""},{"line_number":1533,"context_line":"        return True"},{"line_number":1534,"context_line":""},{"line_number":1535,"context_line":"    @_utils.valid_kwargs(\u0027user\u0027, \u0027group\u0027, \u0027project\u0027, \u0027domain\u0027)"},{"line_number":1536,"context_line":"    def _get_grant_revoke_params(self, role, **kwargs):"},{"line_number":1537,"context_line":"        role \u003d self.get_role(role)"},{"line_number":1538,"context_line":"        if role is None:"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a68dd71_e1d24a34","line":1535,"updated":"2016-01-20 13:47:04.000000000","message":"I *really* do not like this use of valid_kwargs(). That utility function is meant to be used on update APIs where None values can have an actual meaning to the client API.","commit_id":"4e41ca94e1d0895bcdf96b4308b012d7a6e0f168"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"e8530fa47832e0074755e406f80c8a23f68b6df2","unresolved":false,"context_lines":[{"line_number":1551,"context_line":""},{"line_number":1552,"context_line":"        for arg_key, arg_val in kwargs.items():"},{"line_number":1553,"context_line":"            value \u003d getattr(self, \u0027get_{0}\u0027.format(arg_key))(arg_val,"},{"line_number":1554,"context_line":"                                                             filters\u003dfilters)"},{"line_number":1555,"context_line":"            if value is not None:"},{"line_number":1556,"context_line":"                data[arg_key] \u003d value.id"},{"line_number":1557,"context_line":"        return data"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a68dd71_81790e32","line":1554,"updated":"2016-01-20 13:47:04.000000000","message":"Although this is clever, it\u0027s not very readable.","commit_id":"4e41ca94e1d0895bcdf96b4308b012d7a6e0f168"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"e8530fa47832e0074755e406f80c8a23f68b6df2","unresolved":false,"context_lines":[{"line_number":1556,"context_line":"                data[arg_key] \u003d value.id"},{"line_number":1557,"context_line":"        return data"},{"line_number":1558,"context_line":""},{"line_number":1559,"context_line":"    @_utils.valid_kwargs(\u0027user\u0027, \u0027group\u0027, \u0027project\u0027, \u0027domain\u0027)"},{"line_number":1560,"context_line":"    def grant_role(self, name_or_id, **kwargs):"},{"line_number":1561,"context_line":"        \"\"\"Grant a role to a user."},{"line_number":1562,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"9a68dd71_61cada51","line":1559,"updated":"2016-01-20 13:47:04.000000000","message":"Again, save valid_kwargs() for update APIs.","commit_id":"4e41ca94e1d0895bcdf96b4308b012d7a6e0f168"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"e8530fa47832e0074755e406f80c8a23f68b6df2","unresolved":false,"context_lines":[{"line_number":1608,"context_line":"                self.manager.submitTask(_tasks.RoleGrantUser(**data))"},{"line_number":1609,"context_line":"        return True"},{"line_number":1610,"context_line":""},{"line_number":1611,"context_line":"    @_utils.valid_kwargs(\u0027user\u0027, \u0027group\u0027, \u0027project\u0027, \u0027domain\u0027)"},{"line_number":1612,"context_line":"    def revoke_role(self, name_or_id, **kwargs):"},{"line_number":1613,"context_line":"        \"\"\"Revoke a role from a user."},{"line_number":1614,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"9a68dd71_c1eb86af","line":1611,"updated":"2016-01-20 13:47:04.000000000","message":"Ditto.","commit_id":"4e41ca94e1d0895bcdf96b4308b012d7a6e0f168"},{"author":{"_account_id":6488,"name":"Clint Byrum","email":"clint@fewbar.com","username":"clint-fewbar"},"change_message_id":"e4f50a323ebcdfcc2fbc67936da84cc6a701b270","unresolved":false,"context_lines":[{"line_number":1558,"context_line":""},{"line_number":1559,"context_line":"        filters \u003d {}"},{"line_number":1560,"context_line":"        if not is_keystone_v2 and domain:"},{"line_number":1561,"context_line":"            filters[\u0027domain_id\u0027] \u003d data[\u0027domain\u0027] \u003d self.get_domain(domain).id"},{"line_number":1562,"context_line":""},{"line_number":1563,"context_line":"        if user:"},{"line_number":1564,"context_line":"            data[\u0027user\u0027] \u003d self.get_user(user, filters\u003dfilters)"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a68dd71_526defca","line":1561,"updated":"2016-01-27 05:09:55.000000000","message":"oops, we do still return munch objects for backward compatibility, but using the object notation is deprecated. Please use dictionary notation. Note the get_domain call, which claims to return a \"dict\", but confusingly says \"attributes\". I\u0027ll submit a patch to fix the wording there, but you definitely will want to use the dict, not object, notation here.","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"e0508e806ac8c5324d29c54efc5ed12c790e01a2","unresolved":false,"context_lines":[{"line_number":1558,"context_line":""},{"line_number":1559,"context_line":"        filters \u003d {}"},{"line_number":1560,"context_line":"        if not is_keystone_v2 and domain:"},{"line_number":1561,"context_line":"            filters[\u0027domain_id\u0027] \u003d data[\u0027domain\u0027] \u003d self.get_domain(domain).id"},{"line_number":1562,"context_line":""},{"line_number":1563,"context_line":"        if user:"},{"line_number":1564,"context_line":"            data[\u0027user\u0027] \u003d self.get_user(user, filters\u003dfilters)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_59469324","line":1561,"in_reply_to":"7a5de9d1_2aab3b8b","updated":"2016-01-27 20:55:56.000000000","message":"At this point, I think we\u0027re stuck with the API as-is, so just assume it will error when not found.","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"bc83be1d4d79bd943eb674df8a1a2d603c0572aa","unresolved":false,"context_lines":[{"line_number":1558,"context_line":""},{"line_number":1559,"context_line":"        filters \u003d {}"},{"line_number":1560,"context_line":"        if not is_keystone_v2 and domain:"},{"line_number":1561,"context_line":"            filters[\u0027domain_id\u0027] \u003d data[\u0027domain\u0027] \u003d self.get_domain(domain).id"},{"line_number":1562,"context_line":""},{"line_number":1563,"context_line":"        if user:"},{"line_number":1564,"context_line":"            data[\u0027user\u0027] \u003d self.get_user(user, filters\u003dfilters)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_c0e4c90e","line":1561,"in_reply_to":"7a5de9d1_774b6f2c","updated":"2016-01-27 18:46:11.000000000","message":"If the domain is not valid, it raise an error.","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"fcf8cc79d1d07b200782de4df5512d9632ec6d99","unresolved":false,"context_lines":[{"line_number":1558,"context_line":""},{"line_number":1559,"context_line":"        filters \u003d {}"},{"line_number":1560,"context_line":"        if not is_keystone_v2 and domain:"},{"line_number":1561,"context_line":"            filters[\u0027domain_id\u0027] \u003d data[\u0027domain\u0027] \u003d self.get_domain(domain).id"},{"line_number":1562,"context_line":""},{"line_number":1563,"context_line":"        if user:"},{"line_number":1564,"context_line":"            data[\u0027user\u0027] \u003d self.get_user(user, filters\u003dfilters)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_ca52a7dd","line":1561,"in_reply_to":"7a5de9d1_c0e4c90e","updated":"2016-01-27 19:00:59.000000000","message":"Actually, this looks like it only raises an error for get_domain...\n\nOpinions on making this not check at all, and let get_{thing} raise an error if it doesn\u0027t exist?\n\nThen I wouldn\u0027t have to do any of the if checking for role, project, or group, and they would be more like domain.","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"9fc54c80f17b987c38d0f25df11fa495063d10c2","unresolved":false,"context_lines":[{"line_number":1558,"context_line":""},{"line_number":1559,"context_line":"        filters \u003d {}"},{"line_number":1560,"context_line":"        if not is_keystone_v2 and domain:"},{"line_number":1561,"context_line":"            filters[\u0027domain_id\u0027] \u003d data[\u0027domain\u0027] \u003d self.get_domain(domain).id"},{"line_number":1562,"context_line":""},{"line_number":1563,"context_line":"        if user:"},{"line_number":1564,"context_line":"            data[\u0027user\u0027] \u003d self.get_user(user, filters\u003dfilters)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_2aab3b8b","line":1561,"in_reply_to":"7a5de9d1_ca52a7dd","updated":"2016-01-27 19:03:13.000000000","message":"or, i could just continue what I am doing here, right now it requires that I also check that the values are not None, since get_project/user/role/group return None if no object is found.","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"98c5e8ebf0275e47652a8ef309c0c3f7d858024a","unresolved":false,"context_lines":[{"line_number":1558,"context_line":""},{"line_number":1559,"context_line":"        filters \u003d {}"},{"line_number":1560,"context_line":"        if not is_keystone_v2 and domain:"},{"line_number":1561,"context_line":"            filters[\u0027domain_id\u0027] \u003d data[\u0027domain\u0027] \u003d self.get_domain(domain).id"},{"line_number":1562,"context_line":""},{"line_number":1563,"context_line":"        if user:"},{"line_number":1564,"context_line":"            data[\u0027user\u0027] \u003d self.get_user(user, filters\u003dfilters)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_774b6f2c","line":1561,"in_reply_to":"9a68dd71_526defca","updated":"2016-01-27 13:52:30.000000000","message":"I\u0027m not sure what is returned when domain is not valid, but if it\u0027s None, trying to access it will result in an exception. Something for you to check.","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"98c5e8ebf0275e47652a8ef309c0c3f7d858024a","unresolved":false,"context_lines":[{"line_number":1604,"context_line":"                \u0027project\u0027 not in data:"},{"line_number":1605,"context_line":"            self.log.debug(\u0027Must specify project for keystone v2\u0027)"},{"line_number":1606,"context_line":"            return False"},{"line_number":1607,"context_line":""},{"line_number":1608,"context_line":"        if self.list_role_assignments(filters\u003ddata):"},{"line_number":1609,"context_line":"            self.log.debug(\u0027Assignment already exists\u0027)"},{"line_number":1610,"context_line":"            return None"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_9c097234","line":1607,"updated":"2016-01-27 13:52:30.000000000","message":"I\u0027m not a fan of these potentially silent failures above here (not seen unless turning on debug and looking at the log). Usually we don\u0027t do that in shade (unless it\u0027s something like a delete request where there is nothing to delete). I think it would be better to raise exceptions here.","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"bc83be1d4d79bd943eb674df8a1a2d603c0572aa","unresolved":false,"context_lines":[{"line_number":1604,"context_line":"                \u0027project\u0027 not in data:"},{"line_number":1605,"context_line":"            self.log.debug(\u0027Must specify project for keystone v2\u0027)"},{"line_number":1606,"context_line":"            return False"},{"line_number":1607,"context_line":""},{"line_number":1608,"context_line":"        if self.list_role_assignments(filters\u003ddata):"},{"line_number":1609,"context_line":"            self.log.debug(\u0027Assignment already exists\u0027)"},{"line_number":1610,"context_line":"            return None"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_20ba7de2","line":1607,"in_reply_to":"7a5de9d1_9c097234","updated":"2016-01-27 18:46:11.000000000","message":"Yup, no problem I can fix all these","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"98c5e8ebf0275e47652a8ef309c0c3f7d858024a","unresolved":false,"context_lines":[{"line_number":1614,"context_line":"                data)):"},{"line_number":1615,"context_line":"            if self.cloud_config.get_api_version(\u0027identity\u0027).startswith(\u00272\u0027):"},{"line_number":1616,"context_line":"                data[\u0027tenant\u0027] \u003d data.pop(\u0027project\u0027, None)"},{"line_number":1617,"context_line":"                self.manager.submitTask(_tasks.RoleAddUser(**data))"},{"line_number":1618,"context_line":"            else:"},{"line_number":1619,"context_line":"                if \u0027project\u0027 in data and \u0027domain\u0027 in data:"},{"line_number":1620,"context_line":"                    self.log.debug(\u0027Removing domain. Project is from domain.\u0027)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_d724a3b0","line":1617,"updated":"2016-01-27 13:52:30.000000000","message":"Does this return anything that might be useful to present to the user?","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"e0508e806ac8c5324d29c54efc5ed12c790e01a2","unresolved":false,"context_lines":[{"line_number":1614,"context_line":"                data)):"},{"line_number":1615,"context_line":"            if self.cloud_config.get_api_version(\u0027identity\u0027).startswith(\u00272\u0027):"},{"line_number":1616,"context_line":"                data[\u0027tenant\u0027] \u003d data.pop(\u0027project\u0027, None)"},{"line_number":1617,"context_line":"                self.manager.submitTask(_tasks.RoleAddUser(**data))"},{"line_number":1618,"context_line":"            else:"},{"line_number":1619,"context_line":"                if \u0027project\u0027 in data and \u0027domain\u0027 in data:"},{"line_number":1620,"context_line":"                    self.log.debug(\u0027Removing domain. Project is from domain.\u0027)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_79e90f1a","line":1617,"in_reply_to":"7a5de9d1_3083acce","updated":"2016-01-27 20:55:56.000000000","message":"Then I\u0027m fine with it not returning an object. I would like to see us just return True (change made) or False (no change/already exists) or raise exception on error.","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"7c90f89046a2ab159c820f9e93c0b2d8bb10c4ba","unresolved":false,"context_lines":[{"line_number":1614,"context_line":"                data)):"},{"line_number":1615,"context_line":"            if self.cloud_config.get_api_version(\u0027identity\u0027).startswith(\u00272\u0027):"},{"line_number":1616,"context_line":"                data[\u0027tenant\u0027] \u003d data.pop(\u0027project\u0027, None)"},{"line_number":1617,"context_line":"                self.manager.submitTask(_tasks.RoleAddUser(**data))"},{"line_number":1618,"context_line":"            else:"},{"line_number":1619,"context_line":"                if \u0027project\u0027 in data and \u0027domain\u0027 in data:"},{"line_number":1620,"context_line":"                    self.log.debug(\u0027Removing domain. Project is from domain.\u0027)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_3083acce","line":1617,"in_reply_to":"7a5de9d1_c0928957","updated":"2016-01-27 19:53:37.000000000","message":"Keystoneclient v2 just returns the role you just assigned, and keystoneclient v3 returns nothing.\n\nI can retrun the role object for both, but since you are passing in the role name or id anyway, i would just as well return True if it succeeds","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"bc83be1d4d79bd943eb674df8a1a2d603c0572aa","unresolved":false,"context_lines":[{"line_number":1614,"context_line":"                data)):"},{"line_number":1615,"context_line":"            if self.cloud_config.get_api_version(\u0027identity\u0027).startswith(\u00272\u0027):"},{"line_number":1616,"context_line":"                data[\u0027tenant\u0027] \u003d data.pop(\u0027project\u0027, None)"},{"line_number":1617,"context_line":"                self.manager.submitTask(_tasks.RoleAddUser(**data))"},{"line_number":1618,"context_line":"            else:"},{"line_number":1619,"context_line":"                if \u0027project\u0027 in data and \u0027domain\u0027 in data:"},{"line_number":1620,"context_line":"                    self.log.debug(\u0027Removing domain. Project is from domain.\u0027)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_c0928957","line":1617,"in_reply_to":"7a5de9d1_d724a3b0","updated":"2016-01-27 18:46:11.000000000","message":"I will check it, but probably will just return a normalized role assignments list for the roleid that is returned? Just basically the output of a list_role_assignments filtering on what was passed and returning only the one assignment object?","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"98c5e8ebf0275e47652a8ef309c0c3f7d858024a","unresolved":false,"context_lines":[{"line_number":1622,"context_line":"                elif \u0027project\u0027 not in data and \u0027domain\u0027 not in data:"},{"line_number":1623,"context_line":"                    self.log.debug(\u0027Must specify either a domain or project\u0027)"},{"line_number":1624,"context_line":"                    return False"},{"line_number":1625,"context_line":"                self.manager.submitTask(_tasks.RoleGrantUser(**data))"},{"line_number":1626,"context_line":"        return True"},{"line_number":1627,"context_line":""},{"line_number":1628,"context_line":"    def revoke_role(self, name_or_id, user\u003dNone, group\u003dNone,"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_f74c3f78","line":1625,"updated":"2016-01-27 13:52:30.000000000","message":"Does this return anything that might be useful to present to the user?","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"98c5e8ebf0275e47652a8ef309c0c3f7d858024a","unresolved":false,"context_lines":[{"line_number":1653,"context_line":"        elif \u0027user\u0027 not in data and \u0027group\u0027 not in data:"},{"line_number":1654,"context_line":"            self.log.debug(\u0027Must specify either a group or user\u0027)"},{"line_number":1655,"context_line":"            return False"},{"line_number":1656,"context_line":""},{"line_number":1657,"context_line":"        if not self.list_role_assignments(filters\u003ddata):"},{"line_number":1658,"context_line":"            self.log.debug(\u0027Assignment does not exist\u0027)"},{"line_number":1659,"context_line":"            return None"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_f773dfb2","line":1656,"updated":"2016-01-27 13:52:30.000000000","message":"More silent failures.  :(","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"9f81613c976c1b6690d933cfe492bc5a481c151c","unresolved":false,"context_lines":[{"line_number":1559,"context_line":"        filters \u003d {}"},{"line_number":1560,"context_line":"        if not is_keystone_v2 and domain:"},{"line_number":1561,"context_line":"            filters[\u0027domain_id\u0027] \u003d data[\u0027domain\u0027] \u003d \\"},{"line_number":1562,"context_line":"                self.get_domain(domain)[\u0027id\u0027]"},{"line_number":1563,"context_line":""},{"line_number":1564,"context_line":"        if user:"},{"line_number":1565,"context_line":"            data[\u0027user\u0027] \u003d self.get_user(user, filters\u003dfilters)"}],"source_content_type":"text/x-python","patch_set":15,"id":"7a5de9d1_020e9b8b","line":1562,"updated":"2016-02-01 22:05:35.000000000","message":"Did you validate what happens with an  invalid domain here?","commit_id":"4ae6c655662e622cb80d1512d1608aab05265ee9"},{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"36d38b0e7bf38290343b4b9a82a981efc0308373","unresolved":false,"context_lines":[{"line_number":1559,"context_line":"        filters \u003d {}"},{"line_number":1560,"context_line":"        if not is_keystone_v2 and domain:"},{"line_number":1561,"context_line":"            filters[\u0027domain_id\u0027] \u003d data[\u0027domain\u0027] \u003d \\"},{"line_number":1562,"context_line":"                self.get_domain(domain)[\u0027id\u0027]"},{"line_number":1563,"context_line":""},{"line_number":1564,"context_line":"        if user:"},{"line_number":1565,"context_line":"            data[\u0027user\u0027] \u003d self.get_user(user, filters\u003dfilters)"}],"source_content_type":"text/x-python","patch_set":15,"id":"7a5de9d1_383aea99","line":1562,"in_reply_to":"7a5de9d1_020e9b8b","updated":"2016-02-01 22:41:41.000000000","message":"Yup, an error is raised if the domain does not exist","commit_id":"4ae6c655662e622cb80d1512d1608aab05265ee9"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"edf3270010b65c749f4c0601c0020b2d99faeaf2","unresolved":false,"context_lines":[{"line_number":1606,"context_line":"                \u0027Must specify project for keystone v2\u0027)"},{"line_number":1607,"context_line":""},{"line_number":1608,"context_line":"        if self.list_role_assignments(filters\u003ddata):"},{"line_number":1609,"context_line":"            self.log.debug(\u0027Assignment already exists\u0027)"},{"line_number":1610,"context_line":"            return False"},{"line_number":1611,"context_line":""},{"line_number":1612,"context_line":"        with _utils.shade_exceptions("}],"source_content_type":"text/x-python","patch_set":15,"id":"7a5de9d1_ceb40584","line":1609,"updated":"2016-02-02 15:21:29.000000000","message":"I hit this \"already exists\" block when I do not specify either a project or domain when trying to grant a role to the admin user. Example:\n\n   cloud.grant_role(\u0027Member\u0027, user\u003d\u0027admin\u0027)\n\nThat doesn\u0027t seem right since that user doesn\u0027t have that role yet.","commit_id":"4ae6c655662e622cb80d1512d1608aab05265ee9"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"dd2c2c1a087cc305108aece28fe46ce32929aa46","unresolved":false,"context_lines":[{"line_number":1606,"context_line":"                \u0027Must specify project for keystone v2\u0027)"},{"line_number":1607,"context_line":""},{"line_number":1608,"context_line":"        if self.list_role_assignments(filters\u003ddata):"},{"line_number":1609,"context_line":"            self.log.debug(\u0027Assignment already exists\u0027)"},{"line_number":1610,"context_line":"            return False"},{"line_number":1611,"context_line":""},{"line_number":1612,"context_line":"        with _utils.shade_exceptions("}],"source_content_type":"text/x-python","patch_set":15,"id":"5a5ae5dd_38e711e6","line":1609,"in_reply_to":"7a5de9d1_532af22d","updated":"2016-02-03 15:05:21.000000000","message":"Hrm, I can\u0027t reproduce this now on either keystone v2 or v3. I\u0027m going to chalk this up to either a keystone anomaly or something stupid in my part. My $$$ is on the latter.","commit_id":"4ae6c655662e622cb80d1512d1608aab05265ee9"},{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"e892d8873d6f364a05ce8b79ce32986e581c112b","unresolved":false,"context_lines":[{"line_number":1606,"context_line":"                \u0027Must specify project for keystone v2\u0027)"},{"line_number":1607,"context_line":""},{"line_number":1608,"context_line":"        if self.list_role_assignments(filters\u003ddata):"},{"line_number":1609,"context_line":"            self.log.debug(\u0027Assignment already exists\u0027)"},{"line_number":1610,"context_line":"            return False"},{"line_number":1611,"context_line":""},{"line_number":1612,"context_line":"        with _utils.shade_exceptions("}],"source_content_type":"text/x-python","patch_set":15,"id":"7a5de9d1_532af22d","line":1609,"in_reply_to":"7a5de9d1_ceb40584","updated":"2016-02-02 18:56:12.000000000","message":"How are you getting this?\n\nIn [11]: that.create_role(\u0027Member\u0027)\nManager adminv3:RegionOne running task RoleCreate\nManager adminv3:RegionOne ran task RoleCreate in 0.0853281021118s\nOut[11]: Munch({\u0027NAME_ATTR\u0027: \u0027name\u0027, \u0027name\u0027: u\u0027Member\u0027, \u0027links\u0027: {u\u0027self\u0027: u\u0027http://172.16.0.11:35357/v3/roles/af24e6b230344c7aaa8eb99dc9d1fb2d\u0027}, \u0027HUMAN_ID\u0027: False, \u0027id\u0027: u\u0027af24e6b230344c7aaa8eb99dc9d1fb2d\u0027, \u0027human_id\u0027: None})\n\nIn [12]: that.grant_role(\u0027Member\u0027, user\u003d\u0027admin\u0027)\nManager adminv3:RegionOne running task RoleList\nManager adminv3:RegionOne ran task RoleList in 0.0241410732269s\nManager adminv3:RegionOne running task UserList\nManager adminv3:RegionOne ran task UserList in 0.0160219669342s\nManager adminv3:RegionOne running task RoleAssignmentList\nManager adminv3:RegionOne ran task RoleAssignmentList in 0.0180151462555s\n{\u0027role\u0027: u\u0027af24e6b230344c7aaa8eb99dc9d1fb2d\u0027, \u0027user\u0027: Munch({\u0027username\u0027: None, \u0027name\u0027: u\u0027admin\u0027, \u0027domain_id\u0027: u\u0027default\u0027, \u0027default_project_id\u0027: None, \u0027enabled\u0027: True, \u0027email\u0027: u\u0027nobody@manfred.io\u0027, \u0027id\u0027: u\u0027c733779a38c747c7847d6bb6997ea442\u0027})}\n---------------------------------------------------------------------------\nOpenStackCloudException                   Traceback (most recent call last)\n\u003cipython-input-12-3dfa47751853\u003e in \u003cmodule\u003e()\n----\u003e 1 that.grant_role(\u0027Member\u0027, user\u003d\u0027admin\u0027)\n\n/root/shade/shade/operatorcloud.pyc in grant_role(self, name_or_id, user, group, project, domain)\n   1624                 if data.get(\u0027project\u0027) is None and data.get(\u0027domain\u0027) is None:\n   1625                     raise OpenStackCloudException(\n-\u003e 1626                         \u0027Must specify either a domain or project\u0027)\n   1627                 self.manager.submitTask(_tasks.RoleGrantUser(**data))\n   1628         return True\n\nOpenStackCloudException: Must specify either a domain or project","commit_id":"4ae6c655662e622cb80d1512d1608aab05265ee9"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"edf3270010b65c749f4c0601c0020b2d99faeaf2","unresolved":false,"context_lines":[{"line_number":1616,"context_line":"                data[\u0027tenant\u0027] \u003d data.pop(\u0027project\u0027)"},{"line_number":1617,"context_line":"                self.manager.submitTask(_tasks.RoleAddUser(**data))"},{"line_number":1618,"context_line":"            else:"},{"line_number":1619,"context_line":"                self.log.debug(data)"},{"line_number":1620,"context_line":"                if data.get(\u0027project\u0027) is not None \\"},{"line_number":1621,"context_line":"                        and data.get(\u0027domain\u0027) is not None:"},{"line_number":1622,"context_line":"                    self.log.debug(\u0027Removing domain. Project is from domain.\u0027)"}],"source_content_type":"text/x-python","patch_set":15,"id":"7a5de9d1_ee7f8164","line":1619,"updated":"2016-02-02 15:21:29.000000000","message":"I don\u0027t think logging this data helps. Let\u0027s remove it.","commit_id":"4ae6c655662e622cb80d1512d1608aab05265ee9"},{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"e892d8873d6f364a05ce8b79ce32986e581c112b","unresolved":false,"context_lines":[{"line_number":1616,"context_line":"                data[\u0027tenant\u0027] \u003d data.pop(\u0027project\u0027)"},{"line_number":1617,"context_line":"                self.manager.submitTask(_tasks.RoleAddUser(**data))"},{"line_number":1618,"context_line":"            else:"},{"line_number":1619,"context_line":"                self.log.debug(data)"},{"line_number":1620,"context_line":"                if data.get(\u0027project\u0027) is not None \\"},{"line_number":1621,"context_line":"                        and data.get(\u0027domain\u0027) is not None:"},{"line_number":1622,"context_line":"                    self.log.debug(\u0027Removing domain. Project is from domain.\u0027)"}],"source_content_type":"text/x-python","patch_set":15,"id":"7a5de9d1_330e56e6","line":1619,"in_reply_to":"7a5de9d1_ee7f8164","updated":"2016-02-02 18:56:12.000000000","message":"dammit, i thought i got all of my troubleshooting logs","commit_id":"4ae6c655662e622cb80d1512d1608aab05265ee9"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"edf3270010b65c749f4c0601c0020b2d99faeaf2","unresolved":false,"context_lines":[{"line_number":1620,"context_line":"                if data.get(\u0027project\u0027) is not None \\"},{"line_number":1621,"context_line":"                        and data.get(\u0027domain\u0027) is not None:"},{"line_number":1622,"context_line":"                    self.log.debug(\u0027Removing domain. Project is from domain.\u0027)"},{"line_number":1623,"context_line":"                    data.pop(\u0027domain\u0027)"},{"line_number":1624,"context_line":"                if data.get(\u0027project\u0027) is None and data.get(\u0027domain\u0027) is None:"},{"line_number":1625,"context_line":"                    raise OpenStackCloudException("},{"line_number":1626,"context_line":"                        \u0027Must specify either a domain or project\u0027)"}],"source_content_type":"text/x-python","patch_set":15,"id":"7a5de9d1_8e712d7a","line":1623,"updated":"2016-02-02 15:21:29.000000000","message":"When I specify both project and domain, the list_role_assignments() will throw an exception because it does not like having both. So this check seems like it would never be true.","commit_id":"4ae6c655662e622cb80d1512d1608aab05265ee9"},{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"e892d8873d6f364a05ce8b79ce32986e581c112b","unresolved":false,"context_lines":[{"line_number":1620,"context_line":"                if data.get(\u0027project\u0027) is not None \\"},{"line_number":1621,"context_line":"                        and data.get(\u0027domain\u0027) is not None:"},{"line_number":1622,"context_line":"                    self.log.debug(\u0027Removing domain. Project is from domain.\u0027)"},{"line_number":1623,"context_line":"                    data.pop(\u0027domain\u0027)"},{"line_number":1624,"context_line":"                if data.get(\u0027project\u0027) is None and data.get(\u0027domain\u0027) is None:"},{"line_number":1625,"context_line":"                    raise OpenStackCloudException("},{"line_number":1626,"context_line":"                        \u0027Must specify either a domain or project\u0027)"}],"source_content_type":"text/x-python","patch_set":15,"id":"7a5de9d1_d35ee211","line":1623,"in_reply_to":"7a5de9d1_8e712d7a","updated":"2016-02-02 18:56:12.000000000","message":"Ahh, i missed that, cool","commit_id":"4ae6c655662e622cb80d1512d1608aab05265ee9"},{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"ed846d9fbf53dc75b343a879c18073b369a049f6","unresolved":false,"context_lines":[{"line_number":1692,"context_line":"                    raise OpenStackCloudException("},{"line_number":1693,"context_line":"                        \u0027Must specify either a domain or project\u0027)"},{"line_number":1694,"context_line":"                self.manager.submitTask(_tasks.RoleRevokeUser(**data))"},{"line_number":1695,"context_line":"        if wait:"},{"line_number":1696,"context_line":"            for count in _utils._iterate_timeout("},{"line_number":1697,"context_line":"                    timeout,"},{"line_number":1698,"context_line":"                    \"Timeout waiting for role to be revoked\"):"}],"source_content_type":"text/x-python","patch_set":21,"id":"5a5ae5dd_afe2bed3","line":1695,"updated":"2016-02-03 23:08:19.000000000","message":"Does anyone have an opinion on this?\n\nIn my testing it only seems to affect keystone v2, which just sometimes the role does not appear to be available immediately?\n\nShould i just make the wait the default behavior, or leave this arg to turn it on if someone wants it.\n\nThe longest I saw it take to grant or revoke the role in keystonev2 was 21 seconds","commit_id":"e38eea3d8cf8e440832893548c77f9feec1bf7d2"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"ad15a1891e9a04bed8b06c8985fea787dba393d6","unresolved":false,"context_lines":[{"line_number":1692,"context_line":"                    raise OpenStackCloudException("},{"line_number":1693,"context_line":"                        \u0027Must specify either a domain or project\u0027)"},{"line_number":1694,"context_line":"                self.manager.submitTask(_tasks.RoleRevokeUser(**data))"},{"line_number":1695,"context_line":"        if wait:"},{"line_number":1696,"context_line":"            for count in _utils._iterate_timeout("},{"line_number":1697,"context_line":"                    timeout,"},{"line_number":1698,"context_line":"                    \"Timeout waiting for role to be revoked\"):"}],"source_content_type":"text/x-python","patch_set":21,"id":"5a5ae5dd_573700e3","line":1695,"in_reply_to":"5a5ae5dd_afe2bed3","updated":"2016-02-04 14:08:21.000000000","message":"Leave the default as False to match the behavior of other API methods.","commit_id":"e38eea3d8cf8e440832893548c77f9feec1bf7d2"}],"shade/tests/functional/test_identity.py":[{"author":{"_account_id":6488,"name":"Clint Byrum","email":"clint@fewbar.com","username":"clint-fewbar"},"change_message_id":"e4f50a323ebcdfcc2fbc67936da84cc6a701b270","unresolved":false,"context_lines":[{"line_number":153,"context_line":"        assignments \u003d self.cloud.list_role_assignments({"},{"line_number":154,"context_line":"            \u0027role\u0027: role.id,"},{"line_number":155,"context_line":"            \u0027user\u0027: user.id,"},{"line_number":156,"context_line":"            \u0027project\u0027: self.cloud.get_project(\u0027demo\u0027).id"},{"line_number":157,"context_line":"        })"},{"line_number":158,"context_line":"        self.assertIsInstance(assignments, list)"},{"line_number":159,"context_line":"        self.assertTrue(len(assignments) \u003d\u003d 1)"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a68dd71_b278eb90","line":156,"updated":"2016-01-27 05:09:55.000000000","message":"Note that all of these tests are also abusing the munch objects too.","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"},{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"bc83be1d4d79bd943eb674df8a1a2d603c0572aa","unresolved":false,"context_lines":[{"line_number":153,"context_line":"        assignments \u003d self.cloud.list_role_assignments({"},{"line_number":154,"context_line":"            \u0027role\u0027: role.id,"},{"line_number":155,"context_line":"            \u0027user\u0027: user.id,"},{"line_number":156,"context_line":"            \u0027project\u0027: self.cloud.get_project(\u0027demo\u0027).id"},{"line_number":157,"context_line":"        })"},{"line_number":158,"context_line":"        self.assertIsInstance(assignments, list)"},{"line_number":159,"context_line":"        self.assertTrue(len(assignments) \u003d\u003d 1)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a5de9d1_00874110","line":156,"in_reply_to":"9a68dd71_b278eb90","updated":"2016-01-27 18:46:11.000000000","message":"yup, i can fix this one too.","commit_id":"3484110092a7b1898cd6d711520e3ce18fe7bb50"}],"shade/tests/unit/test_role_assignment.py":[{"author":{"_account_id":8016,"name":"Daniel Wallace","email":"danielwallace@gtmanfred.com","username":"gtmanfred"},"change_message_id":"76f1a602f7c66469514236c8c1dde29fcc8b6ebf","unresolved":false,"context_lines":[{"line_number":715,"context_line":"            project\u003dself.fake_project[\u0027id\u0027],"},{"line_number":716,"context_line":"            domain\u003dself.fake_domain[\u0027name\u0027]))"},{"line_number":717,"context_line":""},{"line_number":718,"context_line":"    @patch.object(occ.cloud_config.CloudConfig, \u0027get_api_version\u0027)"},{"line_number":719,"context_line":"    @patch.object(OperatorCloud, \u0027keystone_client\u0027)"},{"line_number":720,"context_line":"    def test_grant_no_project_or_domain(self, mock_keystone, mock_api_version):"},{"line_number":721,"context_line":"        mock_api_version.return_value \u003d \u00273\u0027"}],"source_content_type":"text/x-python","patch_set":15,"id":"7a5de9d1_592453ae","line":718,"updated":"2016-02-02 19:39:37.000000000","message":"I actually already have two tests for no project or domain, down here.","commit_id":"4ae6c655662e622cb80d1512d1608aab05265ee9"}]}
