)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"5d54d02641ce871126277ea65a15816f0c321d8d","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Sergey Vilgelm \u003csergey@vilgelm.info\u003e"},{"line_number":5,"context_line":"CommitDate: 2018-11-10 16:05:04 -0600"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Test list actions"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Add override_role_and_validate_list function to RbacUtils to validate"},{"line_number":10,"context_line":"the list actions."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":20,"id":"3f79a3b5_45908a41","line":7,"range":{"start_line":7,"start_character":0,"end_line":7,"end_character":17},"updated":"2018-11-12 02:29:54.000000000","message":"Also may we put a more descriptive commit message here like:\n\nHelper for validating RBAC list actions\n\nList RBAC actions typically perform soft authorization checks meaning that the response bodies omit resources that the user isn\u0027t authorized to see. For example, if an admin user creates a user, member role might not be able to see that user when listing all the users in a tenant, depending on the RBAC rule. This patch set adds override_role_and_validate_list function to RbacUtils to validate RBAC flows for API list actions.\n\n[...]","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"4447bf60a2cef6c19fe5fc48cfc36b9fafd86983","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Sergey Vilgelm \u003csergey@vilgelm.info\u003e"},{"line_number":5,"context_line":"CommitDate: 2018-11-10 16:05:04 -0600"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Test list actions"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Add override_role_and_validate_list function to RbacUtils to validate"},{"line_number":10,"context_line":"the list actions."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":20,"id":"3f79a3b5_c269e55a","line":7,"range":{"start_line":7,"start_character":0,"end_line":7,"end_character":17},"in_reply_to":"3f79a3b5_45908a41","updated":"2018-11-12 14:17:32.000000000","message":"Thank you","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"}],"patrole_tempest_plugin/rbac_exceptions.py":[{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"700b76429145a0483fce13fc7e657b9945eb35ab","unresolved":false,"context_lines":[{"line_number":92,"context_line":"    message \u003d \"Unsupported error code passed in test\""},{"line_number":93,"context_line":""},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"class RbacOverrideRoleException(BasePatroleException):"},{"line_number":96,"context_line":"    \"\"\"Raised when override_role is used incorrectly or fails somehow."},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    Used for safeguarding against false positives that might occur when the"}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_c57fc466","side":"PARENT","line":95,"range":{"start_line":95,"start_character":6,"end_line":95,"end_character":31},"updated":"2018-11-10 02:37:43.000000000","message":"Why was this removed?","commit_id":"3230e20d4c999a97cb30b696ef93170b6be59c84"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"8c97d216193276781f888bf3e14128478d9f463b","unresolved":false,"context_lines":[{"line_number":92,"context_line":"    message \u003d \"Unsupported error code passed in test\""},{"line_number":93,"context_line":""},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"class RbacOverrideRoleException(BasePatroleException):"},{"line_number":96,"context_line":"    \"\"\"Raised when override_role is used incorrectly or fails somehow."},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    Used for safeguarding against false positives that might occur when the"}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_25b8f8be","side":"PARENT","line":95,"range":{"start_line":95,"start_character":6,"end_line":95,"end_character":31},"in_reply_to":"3f79a3b5_c57fc466","updated":"2018-11-10 03:51:45.000000000","message":"Incorrect rebase","commit_id":"3230e20d4c999a97cb30b696ef93170b6be59c84"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ab58dd1e1da5fc6876d96c408d02964b93fc338f","unresolved":false,"context_lines":[{"line_number":50,"context_line":"    message \u003d (\"The response body is empty due to policy enforcement failure.\")"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"class RbacListValid(BasePatroleResponseBodyException):"},{"line_number":54,"context_line":"    \"\"\"Raised when the result of a list action doesn\u0027t contain expected"},{"line_number":55,"context_line":"    resource or contains less resources."},{"line_number":56,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_65a59000","line":53,"range":{"start_line":53,"start_character":6,"end_line":53,"end_character":19},"updated":"2018-11-10 02:36:18.000000000","message":"How does this differ from RbacPartialResponseBody?","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"8c97d216193276781f888bf3e14128478d9f463b","unresolved":false,"context_lines":[{"line_number":50,"context_line":"    message \u003d (\"The response body is empty due to policy enforcement failure.\")"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"class RbacListValid(BasePatroleResponseBodyException):"},{"line_number":54,"context_line":"    \"\"\"Raised when the result of a list action doesn\u0027t contain expected"},{"line_number":55,"context_line":"    resource or contains less resources."},{"line_number":56,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_45c73447","line":53,"range":{"start_line":53,"start_character":6,"end_line":53,"end_character":19},"in_reply_to":"3f79a3b5_65a59000","updated":"2018-11-10 03:51:45.000000000","message":"At that time I didn\u0027t know exactly how you planned to refactor the Exceptions, so decided to create this one. I will re-use the RbacPartialResponseBody","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"1852e45b9144692dc24a237cd5b6839248ba8f32","unresolved":false,"context_lines":[{"line_number":116,"context_line":"    * The ``ctx.resources`` variable wasn\u0027t set in"},{"line_number":117,"context_line":"        override_role_and_validate_list context."},{"line_number":118,"context_line":"    \"\"\""},{"line_number":119,"context_line":"    message \u003d \"Incorrect usage of override_role_and_validate_list: %s\""}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_653b4699","line":119,"range":{"start_line":119,"start_character":67,"end_line":119,"end_character":69},"updated":"2018-11-12 02:26:10.000000000","message":"This should be a variable or else removed; see L43 for an example","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"4447bf60a2cef6c19fe5fc48cfc36b9fafd86983","unresolved":false,"context_lines":[{"line_number":116,"context_line":"    * The ``ctx.resources`` variable wasn\u0027t set in"},{"line_number":117,"context_line":"        override_role_and_validate_list context."},{"line_number":118,"context_line":"    \"\"\""},{"line_number":119,"context_line":"    message \u003d \"Incorrect usage of override_role_and_validate_list: %s\""}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_bfd642c0","line":119,"range":{"start_line":119,"start_character":67,"end_line":119,"end_character":69},"in_reply_to":"3f79a3b5_653b4699","updated":"2018-11-12 14:17:32.000000000","message":"Done","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"}],"patrole_tempest_plugin/rbac_utils.py":[{"author":{"_account_id":16274,"name":"Mykola Yakovliev","email":"VegasQ@gmail.com","username":"vegasq"},"change_message_id":"618ddf2b7a185b4ba148932163b8caa0b823e6bc","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    resources \u003d None"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"    def __init__(self, resources\u003dNone, resource_id\u003dNone):"},{"line_number":39,"context_line":"        if resources is not None and resource_id is None:"},{"line_number":40,"context_line":"            self._old_len \u003d len(resources)"},{"line_number":41,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":42,"context_line":"            if not self._old_len:"}],"source_content_type":"text/x-python","patch_set":14,"id":"3f79a3b5_436c776a","line":39,"range":{"start_line":39,"start_character":21,"end_line":39,"end_character":32},"updated":"2018-11-05 21:31:06.000000000","message":"Can be dropped","commit_id":"a8a9568ce040b27a9f89775e83cf8890889f7f37"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"26fdc115b46d308acab68a2f143defeeb86e7597","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    resources \u003d None"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"    def __init__(self, resources\u003dNone, resource_id\u003dNone):"},{"line_number":39,"context_line":"        if resources is not None and resource_id is None:"},{"line_number":40,"context_line":"            self._old_len \u003d len(resources)"},{"line_number":41,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":42,"context_line":"            if not self._old_len:"}],"source_content_type":"text/x-python","patch_set":14,"id":"3f79a3b5_1e7a54ba","line":39,"range":{"start_line":39,"start_character":21,"end_line":39,"end_character":32},"in_reply_to":"3f79a3b5_436c776a","updated":"2018-11-06 14:39:21.000000000","message":"Done","commit_id":"a8a9568ce040b27a9f89775e83cf8890889f7f37"},{"author":{"_account_id":16274,"name":"Mykola Yakovliev","email":"VegasQ@gmail.com","username":"vegasq"},"change_message_id":"618ddf2b7a185b4ba148932163b8caa0b823e6bc","unresolved":false,"context_lines":[{"line_number":41,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":42,"context_line":"            if not self._old_len:"},{"line_number":43,"context_line":"                raise testcase.TestSkipped(\"The list of resources is empty\")"},{"line_number":44,"context_line":"        elif resource_id is not None and resources is None:"},{"line_number":45,"context_line":"            self._resource_id \u003d resource_id"},{"line_number":46,"context_line":"            self._validate_func \u003d self._validate_resource"},{"line_number":47,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":14,"id":"3f79a3b5_e388231b","line":44,"range":{"start_line":44,"start_character":25,"end_line":44,"end_character":36},"updated":"2018-11-05 21:31:06.000000000","message":"Can be dropped","commit_id":"a8a9568ce040b27a9f89775e83cf8890889f7f37"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"26fdc115b46d308acab68a2f143defeeb86e7597","unresolved":false,"context_lines":[{"line_number":41,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":42,"context_line":"            if not self._old_len:"},{"line_number":43,"context_line":"                raise testcase.TestSkipped(\"The list of resources is empty\")"},{"line_number":44,"context_line":"        elif resource_id is not None and resources is None:"},{"line_number":45,"context_line":"            self._resource_id \u003d resource_id"},{"line_number":46,"context_line":"            self._validate_func \u003d self._validate_resource"},{"line_number":47,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":14,"id":"3f79a3b5_3e75d0c9","line":44,"range":{"start_line":44,"start_character":25,"end_line":44,"end_character":36},"in_reply_to":"3f79a3b5_e388231b","updated":"2018-11-06 14:39:21.000000000","message":"Done","commit_id":"a8a9568ce040b27a9f89775e83cf8890889f7f37"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ab58dd1e1da5fc6876d96c408d02964b93fc338f","unresolved":false,"context_lines":[{"line_number":39,"context_line":"    the result of a list function must be assigned to the ``ctx.resources``"},{"line_number":40,"context_line":"    variable."},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    Example:"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"        with self.rbac_utils.override_role_and_validate_list(...) as ctx:"},{"line_number":45,"context_line":"            ctx.resources \u003d list_function()"}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_c52344a9","line":42,"range":{"start_line":42,"start_character":11,"end_line":42,"end_character":12},"updated":"2018-11-10 02:36:18.000000000","message":"::","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"8c97d216193276781f888bf3e14128478d9f463b","unresolved":false,"context_lines":[{"line_number":39,"context_line":"    the result of a list function must be assigned to the ``ctx.resources``"},{"line_number":40,"context_line":"    variable."},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    Example:"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"        with self.rbac_utils.override_role_and_validate_list(...) as ctx:"},{"line_number":45,"context_line":"            ctx.resources \u003d list_function()"}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_a5e168d0","line":42,"range":{"start_line":42,"start_character":11,"end_line":42,"end_character":12},"in_reply_to":"3f79a3b5_c52344a9","updated":"2018-11-10 03:51:45.000000000","message":"Done\n\nNeed to read some documentation about this formatting","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ab58dd1e1da5fc6876d96c408d02964b93fc338f","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        if resources is not None and not resource_id:"},{"line_number":66,"context_line":"            self._old_len \u003d len(resources)"},{"line_number":67,"context_line":"            if not self._old_len:"},{"line_number":68,"context_line":"                raise testcase.TestSkipped(\"The list of resources is empty\")"},{"line_number":69,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":70,"context_line":"        elif resource_id and not resources:"},{"line_number":71,"context_line":"            self._resource_id \u003d resource_id"}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_7fde7f0f","line":68,"range":{"start_line":68,"start_character":22,"end_line":68,"end_character":42},"updated":"2018-11-10 02:36:18.000000000","message":"Better to raise `raise testtools.TestCase.skipException`","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"8c97d216193276781f888bf3e14128478d9f463b","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        if resources is not None and not resource_id:"},{"line_number":66,"context_line":"            self._old_len \u003d len(resources)"},{"line_number":67,"context_line":"            if not self._old_len:"},{"line_number":68,"context_line":"                raise testcase.TestSkipped(\"The list of resources is empty\")"},{"line_number":69,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":70,"context_line":"        elif resource_id and not resources:"},{"line_number":71,"context_line":"            self._resource_id \u003d resource_id"}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_25cd585a","line":68,"range":{"start_line":68,"start_character":22,"end_line":68,"end_character":42},"in_reply_to":"3f79a3b5_7fde7f0f","updated":"2018-11-10 03:51:45.000000000","message":"Yeah, you are right","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ab58dd1e1da5fc6876d96c408d02964b93fc338f","unresolved":false,"context_lines":[{"line_number":71,"context_line":"            self._resource_id \u003d resource_id"},{"line_number":72,"context_line":"            self._validate_func \u003d self._validate_resource"},{"line_number":73,"context_line":"        else:"},{"line_number":74,"context_line":"            raise rbac_exceptions.RbacValidateListException()"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    def _validate_len(self):"},{"line_number":77,"context_line":"        \"\"\"Validates that the number of resource is different."}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_05429c3c","line":74,"range":{"start_line":74,"start_character":34,"end_line":74,"end_character":59},"updated":"2018-11-10 02:36:18.000000000","message":"Should add a message here saying resources and resource_id are mutually exclusive.","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"8c97d216193276781f888bf3e14128478d9f463b","unresolved":false,"context_lines":[{"line_number":71,"context_line":"            self._resource_id \u003d resource_id"},{"line_number":72,"context_line":"            self._validate_func \u003d self._validate_resource"},{"line_number":73,"context_line":"        else:"},{"line_number":74,"context_line":"            raise rbac_exceptions.RbacValidateListException()"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    def _validate_len(self):"},{"line_number":77,"context_line":"        \"\"\"Validates that the number of resource is different."}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_a5fac872","line":74,"range":{"start_line":74,"start_character":34,"end_line":74,"end_character":59},"in_reply_to":"3f79a3b5_05429c3c","updated":"2018-11-10 03:51:45.000000000","message":"Done","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ab58dd1e1da5fc6876d96c408d02964b93fc338f","unresolved":false,"context_lines":[{"line_number":78,"context_line":"        \"\"\""},{"line_number":79,"context_line":"        return self._old_len \u003e len(self.resources)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def _validate_resource(self):"},{"line_number":82,"context_line":"        \"\"\"Validates that the resource is not present in the list of resources."},{"line_number":83,"context_line":"        \"\"\""},{"line_number":84,"context_line":"        for resource in self.resources:"}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_45aad4d2","line":81,"updated":"2018-11-10 02:36:18.000000000","message":"What if the rbac_test_role is admin? Then it will fail because the same resources before and during this check are the same.","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"8c97d216193276781f888bf3e14128478d9f463b","unresolved":false,"context_lines":[{"line_number":78,"context_line":"        \"\"\""},{"line_number":79,"context_line":"        return self._old_len \u003e len(self.resources)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def _validate_resource(self):"},{"line_number":82,"context_line":"        \"\"\"Validates that the resource is not present in the list of resources."},{"line_number":83,"context_line":"        \"\"\""},{"line_number":84,"context_line":"        for resource in self.resources:"}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_e51200b3","line":81,"in_reply_to":"3f79a3b5_45aad4d2","updated":"2018-11-10 03:51:45.000000000","message":"In this case the _validate_resource returns False and RbacPartialResponseBody will not be raised, that is a valid case","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ab58dd1e1da5fc6876d96c408d02964b93fc338f","unresolved":false,"context_lines":[{"line_number":92,"context_line":"        :raises RbacValidateListException: if the `ctx.resources`` variable is"},{"line_number":93,"context_line":"        not set."},{"line_number":94,"context_line":"        \"\"\""},{"line_number":95,"context_line":"        if not self.resources:"},{"line_number":96,"context_line":"            raise rbac_exceptions.RbacValidateListException()"},{"line_number":97,"context_line":"        if self._validate_func():"},{"line_number":98,"context_line":"            raise rbac_exceptions.RbacListValid()"}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_e599a0ce","line":95,"range":{"start_line":95,"start_character":11,"end_line":95,"end_character":29},"updated":"2018-11-10 02:36:18.000000000","message":"nit: self.resources is None","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"8c97d216193276781f888bf3e14128478d9f463b","unresolved":false,"context_lines":[{"line_number":92,"context_line":"        :raises RbacValidateListException: if the `ctx.resources`` variable is"},{"line_number":93,"context_line":"        not set."},{"line_number":94,"context_line":"        \"\"\""},{"line_number":95,"context_line":"        if not self.resources:"},{"line_number":96,"context_line":"            raise rbac_exceptions.RbacValidateListException()"},{"line_number":97,"context_line":"        if self._validate_func():"},{"line_number":98,"context_line":"            raise rbac_exceptions.RbacListValid()"}],"source_content_type":"text/x-python","patch_set":15,"id":"3f79a3b5_85054c6a","line":95,"range":{"start_line":95,"start_character":11,"end_line":95,"end_character":29},"in_reply_to":"3f79a3b5_e599a0ce","updated":"2018-11-10 03:51:45.000000000","message":"Done","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"1852e45b9144692dc24a237cd5b6839248ba8f32","unresolved":false,"context_lines":[{"line_number":32,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"class ValidateListContext(object):"},{"line_number":36,"context_line":"    \"\"\"Context class responsible for validation of the list functions."},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"    This class is used in ``override_role_and_validate_list`` function and"}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_45516ad4","line":35,"range":{"start_line":35,"start_character":6,"end_line":35,"end_character":25},"updated":"2018-11-12 02:26:10.000000000","message":"This can be private I think as in: _ValidateListContext","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"4447bf60a2cef6c19fe5fc48cfc36b9fafd86983","unresolved":false,"context_lines":[{"line_number":32,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"class ValidateListContext(object):"},{"line_number":36,"context_line":"    \"\"\"Context class responsible for validation of the list functions."},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"    This class is used in ``override_role_and_validate_list`` function and"}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_828d2d2a","line":35,"range":{"start_line":35,"start_character":6,"end_line":35,"end_character":25},"in_reply_to":"3f79a3b5_45516ad4","updated":"2018-11-12 14:17:32.000000000","message":"Done","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"1852e45b9144692dc24a237cd5b6839248ba8f32","unresolved":false,"context_lines":[{"line_number":45,"context_line":"            ctx.resources \u003d list_function()"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    \"\"\""},{"line_number":48,"context_line":"    def __init__(self, resources\u003dNone, resource_id\u003dNone):"},{"line_number":49,"context_line":"        \"\"\"Constructor for ``ValidateListContext``."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"        Either ``resources`` or ``resource_id`` should be used, not both."}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_2541ce08","line":48,"range":{"start_line":48,"start_character":23,"end_line":48,"end_character":32},"updated":"2018-11-12 02:26:10.000000000","message":"May we call this admin_resources/admin_resource_id to make this clearer?","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"4447bf60a2cef6c19fe5fc48cfc36b9fafd86983","unresolved":false,"context_lines":[{"line_number":45,"context_line":"            ctx.resources \u003d list_function()"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    \"\"\""},{"line_number":48,"context_line":"    def __init__(self, resources\u003dNone, resource_id\u003dNone):"},{"line_number":49,"context_line":"        \"\"\"Constructor for ``ValidateListContext``."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"        Either ``resources`` or ``resource_id`` should be used, not both."}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_7fee6a8a","line":48,"range":{"start_line":48,"start_character":23,"end_line":48,"end_character":32},"in_reply_to":"3f79a3b5_2541ce08","updated":"2018-11-12 14:17:32.000000000","message":"Done","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"1852e45b9144692dc24a237cd5b6839248ba8f32","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"        Either ``resources`` or ``resource_id`` should be used, not both."},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"        :param list resources: The list of resources received before calling"},{"line_number":54,"context_line":"            the ``override_role_and_validate_list`` function. To validate will"},{"line_number":55,"context_line":"            be used the ``_validate_len`` function."},{"line_number":56,"context_line":"        :param UUID resource_id: An ID of a resource created before calling"}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_e5bbd6da","line":53,"range":{"start_line":53,"start_character":20,"end_line":53,"end_character":29},"updated":"2018-11-12 02:26:10.000000000","message":"Ditto","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"4447bf60a2cef6c19fe5fc48cfc36b9fafd86983","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"        Either ``resources`` or ``resource_id`` should be used, not both."},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"        :param list resources: The list of resources received before calling"},{"line_number":54,"context_line":"            the ``override_role_and_validate_list`` function. To validate will"},{"line_number":55,"context_line":"            be used the ``_validate_len`` function."},{"line_number":56,"context_line":"        :param UUID resource_id: An ID of a resource created before calling"}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_1fe17697","line":53,"range":{"start_line":53,"start_character":20,"end_line":53,"end_character":29},"in_reply_to":"3f79a3b5_e5bbd6da","updated":"2018-11-12 14:17:32.000000000","message":"Done","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"1852e45b9144692dc24a237cd5b6839248ba8f32","unresolved":false,"context_lines":[{"line_number":53,"context_line":"        :param list resources: The list of resources received before calling"},{"line_number":54,"context_line":"            the ``override_role_and_validate_list`` function. To validate will"},{"line_number":55,"context_line":"            be used the ``_validate_len`` function."},{"line_number":56,"context_line":"        :param UUID resource_id: An ID of a resource created before calling"},{"line_number":57,"context_line":"            the ``override_role_and_validate_list`` function. To validate will"},{"line_number":58,"context_line":"            be used the ``_validate_resource`` function."},{"line_number":59,"context_line":"        :raises RbacValidateListException: if both ``resources`` and"}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_859c6270","line":56,"range":{"start_line":56,"start_character":20,"end_line":56,"end_character":31},"updated":"2018-11-12 02:26:10.000000000","message":"Ditto","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"4447bf60a2cef6c19fe5fc48cfc36b9fafd86983","unresolved":false,"context_lines":[{"line_number":53,"context_line":"        :param list resources: The list of resources received before calling"},{"line_number":54,"context_line":"            the ``override_role_and_validate_list`` function. To validate will"},{"line_number":55,"context_line":"            be used the ``_validate_len`` function."},{"line_number":56,"context_line":"        :param UUID resource_id: An ID of a resource created before calling"},{"line_number":57,"context_line":"            the ``override_role_and_validate_list`` function. To validate will"},{"line_number":58,"context_line":"            be used the ``_validate_resource`` function."},{"line_number":59,"context_line":"        :raises RbacValidateListException: if both ``resources`` and"}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_dffe9e37","line":56,"range":{"start_line":56,"start_character":20,"end_line":56,"end_character":31},"in_reply_to":"3f79a3b5_859c6270","updated":"2018-11-12 14:17:32.000000000","message":"Done","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"1852e45b9144692dc24a237cd5b6839248ba8f32","unresolved":false,"context_lines":[{"line_number":75,"context_line":"                \"resources and resource_id are mutually exclusive\")"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def _validate_len(self):"},{"line_number":78,"context_line":"        \"\"\"Validates that the number of resource is different."},{"line_number":79,"context_line":"        \"\"\""},{"line_number":80,"context_line":"        return self._old_len \u003e len(self.resources)"},{"line_number":81,"context_line":""}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_05e29202","line":78,"range":{"start_line":78,"start_character":52,"end_line":78,"end_character":61},"updated":"2018-11-12 02:26:10.000000000","message":"less than admin resources","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"4447bf60a2cef6c19fe5fc48cfc36b9fafd86983","unresolved":false,"context_lines":[{"line_number":75,"context_line":"                \"resources and resource_id are mutually exclusive\")"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def _validate_len(self):"},{"line_number":78,"context_line":"        \"\"\"Validates that the number of resource is different."},{"line_number":79,"context_line":"        \"\"\""},{"line_number":80,"context_line":"        return self._old_len \u003e len(self.resources)"},{"line_number":81,"context_line":""}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_9f8906c9","line":78,"range":{"start_line":78,"start_character":52,"end_line":78,"end_character":61},"in_reply_to":"3f79a3b5_05e29202","updated":"2018-11-12 14:17:32.000000000","message":"Done","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"1852e45b9144692dc24a237cd5b6839248ba8f32","unresolved":false,"context_lines":[{"line_number":80,"context_line":"        return self._old_len \u003e len(self.resources)"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    def _validate_resource(self):"},{"line_number":83,"context_line":"        \"\"\"Validates that the resource is not present in the list of resources."},{"line_number":84,"context_line":"        \"\"\""},{"line_number":85,"context_line":"        for resource in self.resources:"},{"line_number":86,"context_line":"            if resource[\u0027id\u0027] \u003d\u003d self._resource_id:"}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_e5e2f6fe","line":83,"range":{"start_line":83,"start_character":30,"end_line":83,"end_character":38},"updated":"2018-11-12 02:26:10.000000000","message":"admin resource","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"4447bf60a2cef6c19fe5fc48cfc36b9fafd86983","unresolved":false,"context_lines":[{"line_number":80,"context_line":"        return self._old_len \u003e len(self.resources)"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    def _validate_resource(self):"},{"line_number":83,"context_line":"        \"\"\"Validates that the resource is not present in the list of resources."},{"line_number":84,"context_line":"        \"\"\""},{"line_number":85,"context_line":"        for resource in self.resources:"},{"line_number":86,"context_line":"            if resource[\u0027id\u0027] \u003d\u003d self._resource_id:"}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_5fb92e79","line":83,"range":{"start_line":83,"start_character":30,"end_line":83,"end_character":38},"in_reply_to":"3f79a3b5_e5e2f6fe","updated":"2018-11-12 14:17:32.000000000","message":"Done","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"1852e45b9144692dc24a237cd5b6839248ba8f32","unresolved":false,"context_lines":[{"line_number":96,"context_line":"        if self.resources is None:"},{"line_number":97,"context_line":"            raise rbac_exceptions.RbacValidateListException("},{"line_number":98,"context_line":"                \"ctx.resources is not assigned\")"},{"line_number":99,"context_line":"        if self._validate_func():"},{"line_number":100,"context_line":"            raise rbac_exceptions.RbacPartialResponseBody()"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":""}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_8529c23a","line":99,"range":{"start_line":99,"start_character":16,"end_line":99,"end_character":30},"updated":"2018-11-12 02:26:10.000000000","message":"It\u0027s pretty confusing how this is \"opposite\": Usually if something validates, it succeeds. So how about reversing the conditional logic to make this:\n\n     if not self._validate_funct(): raise exc\n\nPoint being that we only raise an exception if the validation logic fails.","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"4447bf60a2cef6c19fe5fc48cfc36b9fafd86983","unresolved":false,"context_lines":[{"line_number":96,"context_line":"        if self.resources is None:"},{"line_number":97,"context_line":"            raise rbac_exceptions.RbacValidateListException("},{"line_number":98,"context_line":"                \"ctx.resources is not assigned\")"},{"line_number":99,"context_line":"        if self._validate_func():"},{"line_number":100,"context_line":"            raise rbac_exceptions.RbacPartialResponseBody()"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":""}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_7fbc2a6a","line":99,"range":{"start_line":99,"start_character":16,"end_line":99,"end_character":30},"in_reply_to":"3f79a3b5_8529c23a","updated":"2018-11-12 14:17:32.000000000","message":"Done","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"1852e45b9144692dc24a237cd5b6839248ba8f32","unresolved":false,"context_lines":[{"line_number":97,"context_line":"            raise rbac_exceptions.RbacValidateListException("},{"line_number":98,"context_line":"                \"ctx.resources is not assigned\")"},{"line_number":99,"context_line":"        if self._validate_func():"},{"line_number":100,"context_line":"            raise rbac_exceptions.RbacPartialResponseBody()"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"class RbacUtils(object):"}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_a5d15e30","line":100,"range":{"start_line":100,"start_character":12,"end_line":100,"end_character":59},"updated":"2018-11-12 02:26:10.000000000","message":"It will be better to do:\n\n    if not len(self.resources): raise rbac_exceptions RbacEmptyResponseBody()\n    elif len(self.resources) \u003c self._old_len: raise rbac_exceptions.RbacPartialResponseBody()","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"4447bf60a2cef6c19fe5fc48cfc36b9fafd86983","unresolved":false,"context_lines":[{"line_number":97,"context_line":"            raise rbac_exceptions.RbacValidateListException("},{"line_number":98,"context_line":"                \"ctx.resources is not assigned\")"},{"line_number":99,"context_line":"        if self._validate_func():"},{"line_number":100,"context_line":"            raise rbac_exceptions.RbacPartialResponseBody()"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"class RbacUtils(object):"}],"source_content_type":"text/x-python","patch_set":20,"id":"3f79a3b5_ff035a0f","line":100,"range":{"start_line":100,"start_character":12,"end_line":100,"end_character":59},"in_reply_to":"3f79a3b5_a5d15e30","updated":"2018-11-12 14:17:32.000000000","message":"Done","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"cede39e3d5a287d2caaf3fd2d70d1988cc80a935","unresolved":false,"context_lines":[{"line_number":75,"context_line":"                       \"exclusive\")"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def _validate_len(self):"},{"line_number":78,"context_line":"        \"\"\"Validates that the number of resource is less than admin resources."},{"line_number":79,"context_line":"        \"\"\""},{"line_number":80,"context_line":"        if not len(self.resources):"},{"line_number":81,"context_line":"            raise rbac_exceptions.RbacEmptyResponseBody()"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_54fd8c6e","line":78,"range":{"start_line":78,"start_character":40,"end_line":78,"end_character":48},"updated":"2018-11-12 21:31:44.000000000","message":"nit: resources","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"e23bc6bbd02ea7f88f98609171aeef238e4a5140","unresolved":false,"context_lines":[{"line_number":75,"context_line":"                       \"exclusive\")"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def _validate_len(self):"},{"line_number":78,"context_line":"        \"\"\"Validates that the number of resource is less than admin resources."},{"line_number":79,"context_line":"        \"\"\""},{"line_number":80,"context_line":"        if not len(self.resources):"},{"line_number":81,"context_line":"            raise rbac_exceptions.RbacEmptyResponseBody()"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_0f80569d","line":78,"range":{"start_line":78,"start_character":40,"end_line":78,"end_character":48},"in_reply_to":"3f79a3b5_54fd8c6e","updated":"2018-11-13 15:15:31.000000000","message":"Done","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"cede39e3d5a287d2caaf3fd2d70d1988cc80a935","unresolved":false,"context_lines":[{"line_number":80,"context_line":"        if not len(self.resources):"},{"line_number":81,"context_line":"            raise rbac_exceptions.RbacEmptyResponseBody()"},{"line_number":82,"context_line":"        elif self._admin_len \u003e len(self.resources):"},{"line_number":83,"context_line":"            raise rbac_exceptions.RbacPartialResponseBody()"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    def _validate_resource(self):"},{"line_number":86,"context_line":"        \"\"\"Validates that the admin resource is not present in the resources."}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_54590c8e","line":83,"range":{"start_line":83,"start_character":34,"end_line":83,"end_character":57},"updated":"2018-11-12 21:31:44.000000000","message":"This takes a kwarg called body, i.e.: body\u003dself.resources","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"e23bc6bbd02ea7f88f98609171aeef238e4a5140","unresolved":false,"context_lines":[{"line_number":80,"context_line":"        if not len(self.resources):"},{"line_number":81,"context_line":"            raise rbac_exceptions.RbacEmptyResponseBody()"},{"line_number":82,"context_line":"        elif self._admin_len \u003e len(self.resources):"},{"line_number":83,"context_line":"            raise rbac_exceptions.RbacPartialResponseBody()"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    def _validate_resource(self):"},{"line_number":86,"context_line":"        \"\"\"Validates that the admin resource is not present in the resources."}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_8f5a265b","line":83,"range":{"start_line":83,"start_character":34,"end_line":83,"end_character":57},"in_reply_to":"3f79a3b5_54590c8e","updated":"2018-11-13 15:15:31.000000000","message":"Done","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"cede39e3d5a287d2caaf3fd2d70d1988cc80a935","unresolved":false,"context_lines":[{"line_number":83,"context_line":"            raise rbac_exceptions.RbacPartialResponseBody()"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    def _validate_resource(self):"},{"line_number":86,"context_line":"        \"\"\"Validates that the admin resource is not present in the resources."},{"line_number":87,"context_line":"        \"\"\""},{"line_number":88,"context_line":"        for resource in self.resources:"},{"line_number":89,"context_line":"            if resource[\u0027id\u0027] \u003d\u003d self._admin_resource_id:"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_b4ce6056","line":86,"range":{"start_line":86,"start_character":45,"end_line":86,"end_character":59},"updated":"2018-11-12 21:31:44.000000000","message":"nit: is present","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"e23bc6bbd02ea7f88f98609171aeef238e4a5140","unresolved":false,"context_lines":[{"line_number":83,"context_line":"            raise rbac_exceptions.RbacPartialResponseBody()"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    def _validate_resource(self):"},{"line_number":86,"context_line":"        \"\"\"Validates that the admin resource is not present in the resources."},{"line_number":87,"context_line":"        \"\"\""},{"line_number":88,"context_line":"        for resource in self.resources:"},{"line_number":89,"context_line":"            if resource[\u0027id\u0027] \u003d\u003d self._admin_resource_id:"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_4f640e21","line":86,"range":{"start_line":86,"start_character":45,"end_line":86,"end_character":59},"in_reply_to":"3f79a3b5_b4ce6056","updated":"2018-11-13 15:15:31.000000000","message":"Done","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"cede39e3d5a287d2caaf3fd2d70d1988cc80a935","unresolved":false,"context_lines":[{"line_number":88,"context_line":"        for resource in self.resources:"},{"line_number":89,"context_line":"            if resource[\u0027id\u0027] \u003d\u003d self._admin_resource_id:"},{"line_number":90,"context_line":"                return"},{"line_number":91,"context_line":"        raise rbac_exceptions.RbacPartialResponseBody()"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    def _validate(self):"},{"line_number":94,"context_line":"        \"\"\"Calls the proper validation function."}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_d44c3ccc","line":91,"range":{"start_line":91,"start_character":30,"end_line":91,"end_character":53},"updated":"2018-11-12 21:31:44.000000000","message":"body\u003dself.resources","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"e23bc6bbd02ea7f88f98609171aeef238e4a5140","unresolved":false,"context_lines":[{"line_number":88,"context_line":"        for resource in self.resources:"},{"line_number":89,"context_line":"            if resource[\u0027id\u0027] \u003d\u003d self._admin_resource_id:"},{"line_number":90,"context_line":"                return"},{"line_number":91,"context_line":"        raise rbac_exceptions.RbacPartialResponseBody()"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    def _validate(self):"},{"line_number":94,"context_line":"        \"\"\"Calls the proper validation function."}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_0f6e16ff","line":91,"range":{"start_line":91,"start_character":30,"end_line":91,"end_character":53},"in_reply_to":"3f79a3b5_d44c3ccc","updated":"2018-11-13 15:15:31.000000000","message":"Done","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"cede39e3d5a287d2caaf3fd2d70d1988cc80a935","unresolved":false,"context_lines":[{"line_number":292,"context_line":"        return False"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"    @contextlib.contextmanager"},{"line_number":295,"context_line":"    def override_role_and_validate_list(self, test_obj, admin_resources\u003dNone,"},{"line_number":296,"context_line":"                                        admin_resource_id\u003dNone):"},{"line_number":297,"context_line":"        ctx \u003d _ValidateListContext(admin_resources, admin_resource_id)"},{"line_number":298,"context_line":"        with self.override_role(test_obj):"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_54e7ccaf","line":295,"range":{"start_line":295,"start_character":8,"end_line":295,"end_character":39},"updated":"2018-11-12 21:31:44.000000000","message":"Should add docstring here since this is public method, e.g.:\n\n        Call ``override_role`` and validate RBAC for a list API action.\n\n        List actions usually do soft authorization: partial or empty response\n        bodies are returned instead of excetpions. This helper validates\n        that unauthorized roles only return a subset of the available\n        resources.\n\n        Should only be used for validating list API actions.\n\n        :param list admin_resources: The list of resources received before\n            calling the ``override_role_and_validate_list`` function.\n        :param UUID admin_resource_id: An ID of a resource created before\n            calling the ``override_role_and_validate_list`` function.\n\n         Example::\n\n             [...]","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"e23bc6bbd02ea7f88f98609171aeef238e4a5140","unresolved":false,"context_lines":[{"line_number":292,"context_line":"        return False"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"    @contextlib.contextmanager"},{"line_number":295,"context_line":"    def override_role_and_validate_list(self, test_obj, admin_resources\u003dNone,"},{"line_number":296,"context_line":"                                        admin_resource_id\u003dNone):"},{"line_number":297,"context_line":"        ctx \u003d _ValidateListContext(admin_resources, admin_resource_id)"},{"line_number":298,"context_line":"        with self.override_role(test_obj):"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_aafb5012","line":295,"range":{"start_line":295,"start_character":8,"end_line":295,"end_character":39},"in_reply_to":"3f79a3b5_54e7ccaf","updated":"2018-11-13 15:15:31.000000000","message":"Done","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":16274,"name":"Mykola Yakovliev","email":"VegasQ@gmail.com","username":"vegasq"},"change_message_id":"b9bd4af91d2fa85c9a0c4d6071100ffb3cbd8885","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        self.resources \u003d None"},{"line_number":63,"context_line":"        if admin_resources is not None and not admin_resource_id:"},{"line_number":64,"context_line":"            self._admin_len \u003d len(admin_resources)"},{"line_number":65,"context_line":"            if not self._admin_len:"},{"line_number":66,"context_line":"                raise rbac_exceptions.RbacValidateListException("},{"line_number":67,"context_line":"                    reason\u003d\"the list of admin resources cannot be empty\")"},{"line_number":68,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":69,"context_line":"        elif admin_resource_id and admin_resources is None:"},{"line_number":70,"context_line":"            self._admin_resource_id \u003d admin_resource_id"}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_7ec8854d","line":67,"range":{"start_line":65,"start_character":12,"end_line":67,"end_character":73},"updated":"2018-11-14 16:27:40.000000000","message":"Just wondering, shouldn\u0027t we raise skip in here? Let\u0027s say we have trunks api:\n\nhttps://developer.openstack.org/api-ref/network/v2/index.html#list-trunks\n\nSince we do not ask a user to create trunk prior to list validation he will get this false negative result.\n\nIn the same situation with agents:\n\nhttps://developer.openstack.org/api-ref/network/v2/index.html#list-all-agents\n\nNo error will be raised since we most likely have at least a single agent.\n\nOr we should explicitly say that developer responsible for objects creation for listing validation?","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"05f992a390d6b0941eeba3fdff214f064ba3ed2b","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        self.resources \u003d None"},{"line_number":63,"context_line":"        if admin_resources is not None and not admin_resource_id:"},{"line_number":64,"context_line":"            self._admin_len \u003d len(admin_resources)"},{"line_number":65,"context_line":"            if not self._admin_len:"},{"line_number":66,"context_line":"                raise rbac_exceptions.RbacValidateListException("},{"line_number":67,"context_line":"                    reason\u003d\"the list of admin resources cannot be empty\")"},{"line_number":68,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":69,"context_line":"        elif admin_resource_id and admin_resources is None:"},{"line_number":70,"context_line":"            self._admin_resource_id \u003d admin_resource_id"}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_f224c461","line":67,"range":{"start_line":65,"start_character":12,"end_line":67,"end_character":73},"in_reply_to":"3f79a3b5_129380b2","updated":"2018-11-14 20:33:43.000000000","message":"In this case the Agent\u0027s tests should have its own skip method. If there is no agents, what should we tests?","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"a64574eb2903b36b8774db14281c214214514b91","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        self.resources \u003d None"},{"line_number":63,"context_line":"        if admin_resources is not None and not admin_resource_id:"},{"line_number":64,"context_line":"            self._admin_len \u003d len(admin_resources)"},{"line_number":65,"context_line":"            if not self._admin_len:"},{"line_number":66,"context_line":"                raise rbac_exceptions.RbacValidateListException("},{"line_number":67,"context_line":"                    reason\u003d\"the list of admin resources cannot be empty\")"},{"line_number":68,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":69,"context_line":"        elif admin_resource_id and admin_resources is None:"},{"line_number":70,"context_line":"            self._admin_resource_id \u003d admin_resource_id"}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_5fa6e010","line":67,"range":{"start_line":65,"start_character":12,"end_line":67,"end_character":73},"in_reply_to":"3f79a3b5_12cb807f","updated":"2018-11-14 23:00:38.000000000","message":"I agree with Mykola that some kind of preliminary check can be performed inside the test prior to calling this helper. In the case of agents, the test can just check: `if not admin_resources: raise self.skipException(...)`. Because in this case there\u0027s no way to properly validate the test.\n\nIf we just raise an exception that\u0027ll cause a failure in an environment where a specific type of agent isn\u0027t available. But Patrole should work across all environments, just like Tempest.","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"ffbfdd7448923d7da2137b05884d95f7f516970a","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        self.resources \u003d None"},{"line_number":63,"context_line":"        if admin_resources is not None and not admin_resource_id:"},{"line_number":64,"context_line":"            self._admin_len \u003d len(admin_resources)"},{"line_number":65,"context_line":"            if not self._admin_len:"},{"line_number":66,"context_line":"                raise rbac_exceptions.RbacValidateListException("},{"line_number":67,"context_line":"                    reason\u003d\"the list of admin resources cannot be empty\")"},{"line_number":68,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":69,"context_line":"        elif admin_resource_id and admin_resources is None:"},{"line_number":70,"context_line":"            self._admin_resource_id \u003d admin_resource_id"}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_620a2320","line":67,"range":{"start_line":65,"start_character":12,"end_line":67,"end_character":73},"in_reply_to":"3f79a3b5_5fa6e010","updated":"2018-11-15 00:02:57.000000000","message":"In case of neutron agents it doesn\u0027t matter, because the tests will fail on resource_setup step if there is no agents [0].\n\nI mean, if there is no objects in list how can we test the list function? Correct me if I\u0027m wrong, the main reason of implementing validate_list function is that not all actions covered by its own policies. if there is a special rule for a list action, like [1] then we don\u0027t need to use override_role_and_validate_list function, the override_role is enough. But in case of there is no special policy then there are several options:\n\n1. an action returns same result for any role, like [3] - we cannot write RBAC tests\n2. an action enforces `get/show` policy for each resource in the list, how neutron works - we should use override_role_and_validate_list function. And in this case the list action must return at least one object, otherwise I don\u0027t understand how we can test it. \n\nI prefer to raise RbacValidateListException inside the override_role_and_validate_list function, if this happened then It means that the test incorrect and we need to fix it. If we will raise skipException inside  override_role_and_validate_list function, not everyone will check the reason, why the test was skipped and the general result will be positive, false positive.\n\nif we need to modify the agent\u0027s test, then I will do it, but in the [4]\n\n[0] https://github.com/openstack/patrole/blob/master/patrole_tempest_plugin/tests/api/network/test_agents_rbac.py#L38\n\n[1] https://github.com/openstack/patrole/blob/master/patrole_tempest_plugin/tests/api/compute/test_agents_rbac.py#L45 \n\n[3] https://developer.openstack.org/api-ref/network/v2/index.html?expanded\u003dlist-extensions-detail#list-extensions\n\n[4] https://review.openstack.org/#/c/580762/","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":16274,"name":"Mykola Yakovliev","email":"VegasQ@gmail.com","username":"vegasq"},"change_message_id":"e6bac5227e6e9ba526cc74c673ba242f2ec1e196","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        self.resources \u003d None"},{"line_number":63,"context_line":"        if admin_resources is not None and not admin_resource_id:"},{"line_number":64,"context_line":"            self._admin_len \u003d len(admin_resources)"},{"line_number":65,"context_line":"            if not self._admin_len:"},{"line_number":66,"context_line":"                raise rbac_exceptions.RbacValidateListException("},{"line_number":67,"context_line":"                    reason\u003d\"the list of admin resources cannot be empty\")"},{"line_number":68,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":69,"context_line":"        elif admin_resource_id and admin_resources is None:"},{"line_number":70,"context_line":"            self._admin_resource_id \u003d admin_resource_id"}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_fec3238b","line":67,"range":{"start_line":65,"start_character":12,"end_line":67,"end_character":73},"in_reply_to":"3f79a3b5_620a2320","updated":"2018-11-15 15:51:15.000000000","message":"I have no hard feeling either way, especially since this function for neutron only.\n\nBut if you want to raise an exception here, documentation should say somewhere that user MUST create objects in DB to avoid false negative results. It\u0027s not clear from what I see.","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"6ec48445d136f04a63a17847b35bf5322b5c463c","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        self.resources \u003d None"},{"line_number":63,"context_line":"        if admin_resources is not None and not admin_resource_id:"},{"line_number":64,"context_line":"            self._admin_len \u003d len(admin_resources)"},{"line_number":65,"context_line":"            if not self._admin_len:"},{"line_number":66,"context_line":"                raise rbac_exceptions.RbacValidateListException("},{"line_number":67,"context_line":"                    reason\u003d\"the list of admin resources cannot be empty\")"},{"line_number":68,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":69,"context_line":"        elif admin_resource_id and admin_resources is None:"},{"line_number":70,"context_line":"            self._admin_resource_id \u003d admin_resource_id"}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_8ca9bb27","line":67,"range":{"start_line":65,"start_character":12,"end_line":67,"end_character":73},"in_reply_to":"3f79a3b5_7ec8854d","updated":"2018-11-14 18:58:27.000000000","message":"I think It\u0027s developer\u0027s responsibility. The validate_list function checks that an object created by a user with admin role is not in the list of resources received by a user with member role or the list of resources received by a user with admin role contains more resources than same list received by a user with member role.\nSo, My opinion is that if the list of objects for admin role is empty then it\u0027s incorrect usage of override_role_and_validate_list function or we just should not write tests for that list function.","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":16274,"name":"Mykola Yakovliev","email":"VegasQ@gmail.com","username":"vegasq"},"change_message_id":"1a221331581b3f2bd2001c29d42dad692dfd1fe4","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        self.resources \u003d None"},{"line_number":63,"context_line":"        if admin_resources is not None and not admin_resource_id:"},{"line_number":64,"context_line":"            self._admin_len \u003d len(admin_resources)"},{"line_number":65,"context_line":"            if not self._admin_len:"},{"line_number":66,"context_line":"                raise rbac_exceptions.RbacValidateListException("},{"line_number":67,"context_line":"                    reason\u003d\"the list of admin resources cannot be empty\")"},{"line_number":68,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":69,"context_line":"        elif admin_resource_id and admin_resources is None:"},{"line_number":70,"context_line":"            self._admin_resource_id \u003d admin_resource_id"}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_129380b2","line":67,"range":{"start_line":65,"start_character":12,"end_line":67,"end_character":73},"in_reply_to":"3f79a3b5_8ca9bb27","updated":"2018-11-14 20:17:08.000000000","message":"That is why I used agents as an example. You can\u0027t create agent with API. There might be setup (contrail 3.1 for example) where the extension is enabled (neutron ext-list) but agent list is empty. So You will throw an exception instead of saying that you just can\u0027t validate this functionality (what skip is created for).","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":16274,"name":"Mykola Yakovliev","email":"VegasQ@gmail.com","username":"vegasq"},"change_message_id":"ae8fb05cea31d1275021c189ccdb62b193cb01dd","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        self.resources \u003d None"},{"line_number":63,"context_line":"        if admin_resources is not None and not admin_resource_id:"},{"line_number":64,"context_line":"            self._admin_len \u003d len(admin_resources)"},{"line_number":65,"context_line":"            if not self._admin_len:"},{"line_number":66,"context_line":"                raise rbac_exceptions.RbacValidateListException("},{"line_number":67,"context_line":"                    reason\u003d\"the list of admin resources cannot be empty\")"},{"line_number":68,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":69,"context_line":"        elif admin_resource_id and admin_resources is None:"},{"line_number":70,"context_line":"            self._admin_resource_id \u003d admin_resource_id"}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_12cb807f","line":67,"range":{"start_line":65,"start_character":12,"end_line":67,"end_character":73},"in_reply_to":"3f79a3b5_f224c461","updated":"2018-11-14 20:41:07.000000000","message":"For it please refer to https://review.openstack.org/#/c/580762/","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"6e57537f121a2e0788a478d655edae0c4e137c9e","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        self.resources \u003d None"},{"line_number":63,"context_line":"        if admin_resources is not None and not admin_resource_id:"},{"line_number":64,"context_line":"            self._admin_len \u003d len(admin_resources)"},{"line_number":65,"context_line":"            if not self._admin_len:"},{"line_number":66,"context_line":"                raise rbac_exceptions.RbacValidateListException("},{"line_number":67,"context_line":"                    reason\u003d\"the list of admin resources cannot be empty\")"},{"line_number":68,"context_line":"            self._validate_func \u003d self._validate_len"},{"line_number":69,"context_line":"        elif admin_resource_id and admin_resources is None:"},{"line_number":70,"context_line":"            self._admin_resource_id \u003d admin_resource_id"}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_f6b01844","line":67,"range":{"start_line":65,"start_character":12,"end_line":67,"end_character":73},"in_reply_to":"3f79a3b5_fec3238b","updated":"2018-11-16 18:18:55.000000000","message":"Patrole doesn\u0027t have a stable library so it is OK if we move things around or rename things on a whim. Anyone who consumes Patrole downstream or elsewhere does so at their own discretion: We cannot guarantee a stable interface until we cut a 1.0 release.\n\nRelease notes though are still nice to communicate such changes. If we bog ourselves down too much with deprecation cycles then it will take even longer to release a stable lib.","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":16274,"name":"Mykola Yakovliev","email":"VegasQ@gmail.com","username":"vegasq"},"change_message_id":"ae8fb05cea31d1275021c189ccdb62b193cb01dd","unresolved":false,"context_lines":[{"line_number":292,"context_line":"        return False"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"    @contextlib.contextmanager"},{"line_number":295,"context_line":"    def override_role_and_validate_list(self, test_obj, admin_resources\u003dNone,"},{"line_number":296,"context_line":"                                        admin_resource_id\u003dNone):"},{"line_number":297,"context_line":"        \"\"\"Call ``override_role`` and validate RBAC for a list API action."},{"line_number":298,"context_line":""}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_b2dbac4a","line":295,"range":{"start_line":295,"start_character":8,"end_line":295,"end_character":39},"updated":"2018-11-14 20:41:07.000000000","message":"Can it be moved on tests.api.network level to omit confusion? This kind of list validation is neutron specific due to my understanding, and it shouldn\u0027t be available to non-neutron tests or 3rd party tools that use patrole.\n\nOr at least it should be renamed to  ``override_role_and_validate_neutron_list`` or something like it.","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"6e57537f121a2e0788a478d655edae0c4e137c9e","unresolved":false,"context_lines":[{"line_number":292,"context_line":"        return False"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"    @contextlib.contextmanager"},{"line_number":295,"context_line":"    def override_role_and_validate_list(self, test_obj, admin_resources\u003dNone,"},{"line_number":296,"context_line":"                                        admin_resource_id\u003dNone):"},{"line_number":297,"context_line":"        \"\"\"Call ``override_role`` and validate RBAC for a list API action."},{"line_number":298,"context_line":""}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_9679a482","line":295,"range":{"start_line":295,"start_character":8,"end_line":295,"end_character":39},"in_reply_to":"3f79a3b5_7e89536e","updated":"2018-11-16 18:18:55.000000000","message":"I\u0027m not sure if the behavior is unique to just Neutron, but I can\u0027t think of any other service that does policy enforcement for list like Neutron. Even still, as I mention above, rbac_utils isn\u0027t a stable lib, so we can move this later if we believe it is warranted.","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"ffbfdd7448923d7da2137b05884d95f7f516970a","unresolved":false,"context_lines":[{"line_number":292,"context_line":"        return False"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"    @contextlib.contextmanager"},{"line_number":295,"context_line":"    def override_role_and_validate_list(self, test_obj, admin_resources\u003dNone,"},{"line_number":296,"context_line":"                                        admin_resource_id\u003dNone):"},{"line_number":297,"context_line":"        \"\"\"Call ``override_role`` and validate RBAC for a list API action."},{"line_number":298,"context_line":""}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_c23d378e","line":295,"range":{"start_line":295,"start_character":8,"end_line":295,"end_character":39},"in_reply_to":"3f79a3b5_b2dbac4a","updated":"2018-11-15 00:02:57.000000000","message":"I don\u0027t understand why it\u0027s should be moved to neutron? Why it\u0027s neutron specific? I\u0027m trying to make it more generic, not only for neutron and this is why I don\u0027t apply your suggestion about using a decorator","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":16274,"name":"Mykola Yakovliev","email":"VegasQ@gmail.com","username":"vegasq"},"change_message_id":"e6bac5227e6e9ba526cc74c673ba242f2ec1e196","unresolved":false,"context_lines":[{"line_number":292,"context_line":"        return False"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"    @contextlib.contextmanager"},{"line_number":295,"context_line":"    def override_role_and_validate_list(self, test_obj, admin_resources\u003dNone,"},{"line_number":296,"context_line":"                                        admin_resource_id\u003dNone):"},{"line_number":297,"context_line":"        \"\"\"Call ``override_role`` and validate RBAC for a list API action."},{"line_number":298,"context_line":""}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_7e89536e","line":295,"range":{"start_line":295,"start_character":8,"end_line":295,"end_character":39},"in_reply_to":"3f79a3b5_c23d378e","updated":"2018-11-15 15:51:15.000000000","message":"Correct me if I\u0027m wrong, but here is how neutron works with lists:\n\nhttps://github.com/openstack/neutron/blob/master/neutron/api/v2/base.py#L319\n\nAnd here is an example from nova:\n\nhttps://github.com/openstack/nova/blob/master/nova/api/openstack/compute/floating_ips.py#L135\n\nI think It might be a good idea to go thru different projects in openstack and check deeper. But for all I know - neutron is unique in its behavior.","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":16274,"name":"Mykola Yakovliev","email":"VegasQ@gmail.com","username":"vegasq"},"change_message_id":"b9bd4af91d2fa85c9a0c4d6071100ffb3cbd8885","unresolved":false,"context_lines":[{"line_number":312,"context_line":"        Example::"},{"line_number":313,"context_line":""},{"line_number":314,"context_line":"            # the resource created by admin"},{"line_number":315,"context_line":"            admin_resource_id \u003d \\"},{"line_number":316,"context_line":"                self.ntp_client.create_policy_dscp_marking_rule()"},{"line_number":317,"context_line":"            with self.rbac_utils.override_role_and_validate_list("},{"line_number":318,"context_line":"                    self, admin_resource_id\u003dadmin_resource_id) as ctx:"},{"line_number":319,"context_line":"                # the list of resources available for member role"}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_1ecf11b3","line":316,"range":{"start_line":315,"start_character":0,"end_line":316,"end_character":65},"updated":"2018-11-14 16:27:40.000000000","message":"nit: [\"policy_dscp_marking_rule\"][\"id\u0027]","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"6ec48445d136f04a63a17847b35bf5322b5c463c","unresolved":false,"context_lines":[{"line_number":312,"context_line":"        Example::"},{"line_number":313,"context_line":""},{"line_number":314,"context_line":"            # the resource created by admin"},{"line_number":315,"context_line":"            admin_resource_id \u003d \\"},{"line_number":316,"context_line":"                self.ntp_client.create_policy_dscp_marking_rule()"},{"line_number":317,"context_line":"            with self.rbac_utils.override_role_and_validate_list("},{"line_number":318,"context_line":"                    self, admin_resource_id\u003dadmin_resource_id) as ctx:"},{"line_number":319,"context_line":"                # the list of resources available for member role"}],"source_content_type":"text/x-python","patch_set":22,"id":"3f79a3b5_cc3d73e7","line":316,"range":{"start_line":315,"start_character":0,"end_line":316,"end_character":65},"in_reply_to":"3f79a3b5_1ecf11b3","updated":"2018-11-14 18:58:27.000000000","message":"Done","commit_id":"b285c10cc6dee024b93051f85c776a496e059278"}],"patrole_tempest_plugin/tests/api/network/rbac_base.py":[{"author":{"_account_id":23140,"name":"Jess Egler","email":"jess.egler@gmail.com","username":"jessegler"},"change_message_id":"57617477d4721baafe05292b07471de68e099418","unresolved":false,"context_lines":[{"line_number":35,"context_line":"        :param list_func: Function to get a list of the resources to which"},{"line_number":36,"context_line":"            the tenant has access."},{"line_number":37,"context_line":"        :param resource_id: the ID of a resource to which the tenant shouldn\u0027t"},{"line_number":38,"context_line":"            have access."},{"line_number":39,"context_line":"        :param add_resource_id_to_list_kwargs: Add ``resource_id`` to"},{"line_number":40,"context_line":"            ``list_kwargs`` if ``resource_id`` is not None."},{"line_number":41,"context_line":"        :param list_kwargs: Additional arguments for ``list_func``."}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_9133ee61","line":38,"updated":"2018-10-08 23:19:59.000000000","message":"This function should be able to handle various policies without requiring a code change, so I don\u0027t think this will work.\n\nWhat if the policy is changed from admin_only to regular_user? Patrole should be able to test that the policy (whatever is specified in the policy.json) is appropriately applied.","commit_id":"d03b4777670bca9dc50268e78a84de519a408193"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"2f8483f52b34ca4dcf0e77567db87f621d8634d6","unresolved":false,"context_lines":[{"line_number":45,"context_line":"        \"\"\""},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"        if resource_id is None:"},{"line_number":48,"context_line":"            old_len \u003d len(list_func(**list_kwargs)[resources_name])"},{"line_number":49,"context_line":"            if not old_len:"},{"line_number":50,"context_line":"                self.skipTest(\"The \u0027%s\u0027 function returned an empty \""},{"line_number":51,"context_line":"                              \"list.\" % list_func.__name__)"}],"source_content_type":"text/x-python","patch_set":9,"id":"3f79a3b5_72c13f81","line":48,"updated":"2018-10-10 17:48:28.000000000","message":"May we instead do:\n\n\n        class override_role_and_validate_list(object):\n\n           def __init__(self, admin_client, resource_name, list_func_name, *list_args, **list_kwargs):\n               # initialize all this stuff\n               self.resources \u003d None\n\n           def __enter__(self):\n               admin_list_func \u003d getattr(admin_client, list_func_name, None)\n            \n                if not admin_list_func:\n                    raise RuntimeError(\u0027List function: %s was not found for service client %r\u0027 % (list_func_name, admin_client)\n            \n                self.admin_resources \u003d admin_list_func(*list_args, **list_kwargs)[resource_name]\n                if not self.admin_resources:\n                    raise self.skipException(\"The \u0027%s\u0027 function return an empty list so cannot validate list action for: %s\" % (\n    self.__class__.__name__, list_func_name)\n            \n                with self.rbac_utils.override_role():\n                    yield self\n\n          def __exit__(self):\n              if not isinstance(self.resources, list):\n                  raise RuntimeError(\u0027ctxt.resources was not set... blah, blah\u0027)\n              if len(self.resources) !\u003d len(self.admin_resources):\n                  raise \u003cpartial-exception-class-name\u003e\n              elif not self.resources:\n                  raise \u003cempty-exception-class-name\u003e\n\nThen usage is:\n\n    @rbac_rule_validation.action(...)\n    def test_list_foo(self):\n        with self.override_role_and_validate_list(...) as ctxt:\n            ctxt.resources \u003d self.foo_client.list_resources()[resource_name]\n\nIf that doesn\u0027t work you can just drop the contextmanager pattern and just use a direct function call or something.\n\nWe should also try to leverage the exceptions from here instead: https://review.openstack.org/#/c/606869/","commit_id":"0a4bf6efa15eb1f37211c3e68882d7160d353792"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"8493cfdfc4ea8db7f5b93b1373d8f1b4b3904ee9","unresolved":false,"context_lines":[{"line_number":45,"context_line":"        \"\"\""},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"        if resource_id is None:"},{"line_number":48,"context_line":"            old_len \u003d len(list_func(**list_kwargs)[resources_name])"},{"line_number":49,"context_line":"            if not old_len:"},{"line_number":50,"context_line":"                self.skipTest(\"The \u0027%s\u0027 function returned an empty \""},{"line_number":51,"context_line":"                              \"list.\" % list_func.__name__)"}],"source_content_type":"text/x-python","patch_set":9,"id":"3f79a3b5_8db0798f","line":48,"in_reply_to":"3f79a3b5_72c13f81","updated":"2018-10-11 01:17:19.000000000","message":"Done","commit_id":"0a4bf6efa15eb1f37211c3e68882d7160d353792"}],"patrole_tempest_plugin/tests/unit/test_rbac_utils.py":[{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"cede39e3d5a287d2caaf3fd2d70d1988cc80a935","unresolved":false,"context_lines":[{"line_number":273,"context_line":"        self.assertRaises(rbac_exceptions.RbacValidateListException,"},{"line_number":274,"context_line":"                          ctx._validate)"},{"line_number":275,"context_line":""},{"line_number":276,"context_line":"    def test_validate_len(self):"},{"line_number":277,"context_line":"        ctx \u003d self._get_context(admin_resources\u003d[1, 2, 3, 4])"},{"line_number":278,"context_line":"        self.assertEqual(ctx._validate_len, ctx._validate_func)"},{"line_number":279,"context_line":"        self.assertEqual(4, ctx._admin_len)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_1405d468","line":276,"range":{"start_line":276,"start_character":8,"end_line":276,"end_character":25},"updated":"2018-11-12 21:31:44.000000000","message":"This one should be _negative","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"e23bc6bbd02ea7f88f98609171aeef238e4a5140","unresolved":false,"context_lines":[{"line_number":273,"context_line":"        self.assertRaises(rbac_exceptions.RbacValidateListException,"},{"line_number":274,"context_line":"                          ctx._validate)"},{"line_number":275,"context_line":""},{"line_number":276,"context_line":"    def test_validate_len(self):"},{"line_number":277,"context_line":"        ctx \u003d self._get_context(admin_resources\u003d[1, 2, 3, 4])"},{"line_number":278,"context_line":"        self.assertEqual(ctx._validate_len, ctx._validate_func)"},{"line_number":279,"context_line":"        self.assertEqual(4, ctx._admin_len)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_4ac39c8d","line":276,"range":{"start_line":276,"start_character":8,"end_line":276,"end_character":25},"in_reply_to":"3f79a3b5_1405d468","updated":"2018-11-13 15:15:31.000000000","message":"Done","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"cede39e3d5a287d2caaf3fd2d70d1988cc80a935","unresolved":false,"context_lines":[{"line_number":289,"context_line":"        self.assertRaises(rbac_exceptions.RbacEmptyResponseBody,"},{"line_number":290,"context_line":"                          ctx._validate_len)"},{"line_number":291,"context_line":""},{"line_number":292,"context_line":"    def test_validate_len_negative(self):"},{"line_number":293,"context_line":"        ctx \u003d self._get_context(admin_resources\u003d[1, 2, 3, 4])"},{"line_number":294,"context_line":""},{"line_number":295,"context_line":"        # the number of resources and admin resources are same"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_d41e7cbc","line":292,"range":{"start_line":292,"start_character":8,"end_line":292,"end_character":34},"updated":"2018-11-12 21:31:44.000000000","message":"This would should be test_validate_len","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"e23bc6bbd02ea7f88f98609171aeef238e4a5140","unresolved":false,"context_lines":[{"line_number":289,"context_line":"        self.assertRaises(rbac_exceptions.RbacEmptyResponseBody,"},{"line_number":290,"context_line":"                          ctx._validate_len)"},{"line_number":291,"context_line":""},{"line_number":292,"context_line":"    def test_validate_len_negative(self):"},{"line_number":293,"context_line":"        ctx \u003d self._get_context(admin_resources\u003d[1, 2, 3, 4])"},{"line_number":294,"context_line":""},{"line_number":295,"context_line":"        # the number of resources and admin resources are same"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_aa3350c3","line":292,"range":{"start_line":292,"start_character":8,"end_line":292,"end_character":34},"in_reply_to":"3f79a3b5_d41e7cbc","updated":"2018-11-13 15:15:31.000000000","message":"Done","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"cede39e3d5a287d2caaf3fd2d70d1988cc80a935","unresolved":false,"context_lines":[{"line_number":296,"context_line":"        ctx.resources \u003d [1, 2, 3, 4]"},{"line_number":297,"context_line":"        self.assertIsNone(ctx._validate_len())"},{"line_number":298,"context_line":""},{"line_number":299,"context_line":"    def test_validate_resource(self):"},{"line_number":300,"context_line":"        ctx \u003d self._get_context(admin_resource_id\u003d1)"},{"line_number":301,"context_line":"        self.assertEqual(ctx._validate_resource, ctx._validate_func)"},{"line_number":302,"context_line":"        self.assertEqual(1, ctx._admin_resource_id)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_941804cf","line":299,"range":{"start_line":299,"start_character":8,"end_line":299,"end_character":30},"updated":"2018-11-12 21:31:44.000000000","message":"test_validate_resource_negative","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"e23bc6bbd02ea7f88f98609171aeef238e4a5140","unresolved":false,"context_lines":[{"line_number":296,"context_line":"        ctx.resources \u003d [1, 2, 3, 4]"},{"line_number":297,"context_line":"        self.assertIsNone(ctx._validate_len())"},{"line_number":298,"context_line":""},{"line_number":299,"context_line":"    def test_validate_resource(self):"},{"line_number":300,"context_line":"        ctx \u003d self._get_context(admin_resource_id\u003d1)"},{"line_number":301,"context_line":"        self.assertEqual(ctx._validate_resource, ctx._validate_func)"},{"line_number":302,"context_line":"        self.assertEqual(1, ctx._admin_resource_id)"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_4a387c9d","line":299,"range":{"start_line":299,"start_character":8,"end_line":299,"end_character":30},"in_reply_to":"3f79a3b5_941804cf","updated":"2018-11-13 15:15:31.000000000","message":"Done","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"cede39e3d5a287d2caaf3fd2d70d1988cc80a935","unresolved":false,"context_lines":[{"line_number":307,"context_line":"        self.assertRaises(rbac_exceptions.RbacPartialResponseBody,"},{"line_number":308,"context_line":"                          ctx._validate_resource)"},{"line_number":309,"context_line":""},{"line_number":310,"context_line":"    def test_validate_resource_negative(self):"},{"line_number":311,"context_line":"        ctx \u003d self._get_context(admin_resource_id\u003d1)"},{"line_number":312,"context_line":""},{"line_number":313,"context_line":"        # there is admin resource in the resources"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_b4150098","line":310,"range":{"start_line":310,"start_character":8,"end_line":310,"end_character":39},"updated":"2018-11-12 21:31:44.000000000","message":"test_validate_resource","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"e23bc6bbd02ea7f88f98609171aeef238e4a5140","unresolved":false,"context_lines":[{"line_number":307,"context_line":"        self.assertRaises(rbac_exceptions.RbacPartialResponseBody,"},{"line_number":308,"context_line":"                          ctx._validate_resource)"},{"line_number":309,"context_line":""},{"line_number":310,"context_line":"    def test_validate_resource_negative(self):"},{"line_number":311,"context_line":"        ctx \u003d self._get_context(admin_resource_id\u003d1)"},{"line_number":312,"context_line":""},{"line_number":313,"context_line":"        # there is admin resource in the resources"}],"source_content_type":"text/x-python","patch_set":21,"id":"3f79a3b5_6a3d388c","line":310,"range":{"start_line":310,"start_character":8,"end_line":310,"end_character":39},"in_reply_to":"3f79a3b5_b4150098","updated":"2018-11-13 15:15:31.000000000","message":"Done","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"}],"releasenotes/notes/override-role-and-validate-list-d3b80f773674a652.yaml":[{"author":{"_account_id":16274,"name":"Mykola Yakovliev","email":"VegasQ@gmail.com","username":"vegasq"},"change_message_id":"618ddf2b7a185b4ba148932163b8caa0b823e6bc","unresolved":false,"context_lines":[{"line_number":14,"context_line":"          with (self.rbac_utils.override_role_and_validate_list("},{"line_number":15,"context_line":"                  self, resources\u003dresources)) as ctx:"},{"line_number":16,"context_line":"              # the list of resources available for member role"},{"line_number":17,"context_line":"              ctx.resources \u003d (self.ntp_client.list_network_ip_availabilities()"},{"line_number":18,"context_line":"                               [\"network_ip_availabilities\"])"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"      * Validating that a resource, created before ``override_role``, is not"}],"source_content_type":"text/x-yaml","patch_set":14,"id":"3f79a3b5_5e38cc3a","line":17,"range":{"start_line":17,"start_character":14,"end_line":17,"end_character":30},"updated":"2018-11-05 21:31:06.000000000","message":"I\u0027ve been looking on it for a while. What do you think if we won\u0027t assign anything to ctx within test itself?\n\nIt looks a bit alien to what we have in all other tests. Can we try to make a decorator that will do it for us?\n\nsomething like this:\n\n``\n    @contextmanager\n    def override_role_and_validate_list(self, test_obj,\n                                         client, method_name, resource_name,\n                                         resources\u003dNone, resource_id\u003dNone):\n        ctx \u003d ValidateListContext(resources, resource_id)\n\n        def decor(fn):\n            def wrapper(*args, **kwargs):\n                res \u003d fn(*args, **kwargs)\n                ctx.resources \u003d res[resource_name]\n                return res\n            return wrapper\n\n        original_list_method \u003d getattr(client, method_name)\n        setattr(client, method_name, decor(original_list_method))\n\n        with self.override_role(test_obj):\n            yield ctx\n            ctx.validate()\n\n        setattr(client, method_name, original_list_method)\n\n``\n\n\nWith it test will look like:\n\n``\n    def test_list_networks(self):\n        resource_id \u003d self.network[\u0027id\u0027]\n        with self.rbac_utils.override_role_and_validate_list(\n                self, self.networks_client,  \"list_networks\", \"networks\",\n                resource_id\u003dresource_id):\n            self.networks_client.list_networks(id\u003dresource_id)\n``\n\nWe already changing a context manager, but we can preserve how the user should call a method.","commit_id":"a8a9568ce040b27a9f89775e83cf8890889f7f37"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"02c5c1d08eb72c73e5518ad72ca9022f188834a4","unresolved":false,"context_lines":[{"line_number":14,"context_line":"          with (self.rbac_utils.override_role_and_validate_list("},{"line_number":15,"context_line":"                  self, resources\u003dresources)) as ctx:"},{"line_number":16,"context_line":"              # the list of resources available for member role"},{"line_number":17,"context_line":"              ctx.resources \u003d (self.ntp_client.list_network_ip_availabilities()"},{"line_number":18,"context_line":"                               [\"network_ip_availabilities\"])"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"      * Validating that a resource, created before ``override_role``, is not"}],"source_content_type":"text/x-yaml","patch_set":14,"id":"3f79a3b5_44209ab1","line":17,"range":{"start_line":17,"start_character":14,"end_line":17,"end_character":30},"in_reply_to":"3f79a3b5_5e38cc3a","updated":"2018-11-09 22:46:10.000000000","message":"I like your idea, but this implementation is more generic and it doesn\u0027t depend on the structure of a result. Let\u0027s keep It for now.","commit_id":"a8a9568ce040b27a9f89775e83cf8890889f7f37"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"26fdc115b46d308acab68a2f143defeeb86e7597","unresolved":false,"context_lines":[{"line_number":14,"context_line":"          with (self.rbac_utils.override_role_and_validate_list("},{"line_number":15,"context_line":"                  self, resources\u003dresources)) as ctx:"},{"line_number":16,"context_line":"              # the list of resources available for member role"},{"line_number":17,"context_line":"              ctx.resources \u003d (self.ntp_client.list_network_ip_availabilities()"},{"line_number":18,"context_line":"                               [\"network_ip_availabilities\"])"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"      * Validating that a resource, created before ``override_role``, is not"}],"source_content_type":"text/x-yaml","patch_set":14,"id":"3f79a3b5_3631660b","line":17,"range":{"start_line":17,"start_character":14,"end_line":17,"end_character":30},"in_reply_to":"3f79a3b5_5e38cc3a","updated":"2018-11-06 14:39:21.000000000","message":"Thanks, will think about It","commit_id":"a8a9568ce040b27a9f89775e83cf8890889f7f37"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ab58dd1e1da5fc6876d96c408d02964b93fc338f","unresolved":false,"context_lines":[{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    In order to test the list actions which doesn\u0027t have its own policy,"},{"line_number":5,"context_line":"    implemented the ``override_role_and_validate_list`` function."},{"line_number":6,"context_line":"    The cuntions has two modes:"},{"line_number":7,"context_line":"      * Validating the number of the resources in a ResponseBody before"},{"line_number":8,"context_line":"        calling the ``override_role`` and after:"},{"line_number":9,"context_line":""}],"source_content_type":"text/x-yaml","patch_set":15,"id":"3f79a3b5_253d58b8","line":6,"range":{"start_line":6,"start_character":8,"end_line":6,"end_character":16},"updated":"2018-11-10 02:36:18.000000000","message":"function?","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"8c97d216193276781f888bf3e14128478d9f463b","unresolved":false,"context_lines":[{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    In order to test the list actions which doesn\u0027t have its own policy,"},{"line_number":5,"context_line":"    implemented the ``override_role_and_validate_list`` function."},{"line_number":6,"context_line":"    The cuntions has two modes:"},{"line_number":7,"context_line":"      * Validating the number of the resources in a ResponseBody before"},{"line_number":8,"context_line":"        calling the ``override_role`` and after:"},{"line_number":9,"context_line":""}],"source_content_type":"text/x-yaml","patch_set":15,"id":"3f79a3b5_05193cd0","line":6,"range":{"start_line":6,"start_character":8,"end_line":6,"end_character":16},"in_reply_to":"3f79a3b5_253d58b8","updated":"2018-11-10 03:51:45.000000000","message":"Done","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ab58dd1e1da5fc6876d96c408d02964b93fc338f","unresolved":false,"context_lines":[{"line_number":11,"context_line":""},{"line_number":12,"context_line":"          # the list of resources available for admin role"},{"line_number":13,"context_line":"          resources \u003d self.ntp_client.list_network_ip_availabilities"},{"line_number":14,"context_line":"          with (self.rbac_utils.override_role_and_validate_list("},{"line_number":15,"context_line":"                  self, resources\u003dresources)) as ctx:"},{"line_number":16,"context_line":"              # the list of resources available for member role"},{"line_number":17,"context_line":"              ctx.resources \u003d (self.ntp_client.list_network_ip_availabilities()"}],"source_content_type":"text/x-yaml","patch_set":15,"id":"3f79a3b5_e574409d","line":14,"range":{"start_line":14,"start_character":15,"end_line":14,"end_character":16},"updated":"2018-11-10 02:36:18.000000000","message":"nit: This outer paranthesis is not needed.","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"8c97d216193276781f888bf3e14128478d9f463b","unresolved":false,"context_lines":[{"line_number":11,"context_line":""},{"line_number":12,"context_line":"          # the list of resources available for admin role"},{"line_number":13,"context_line":"          resources \u003d self.ntp_client.list_network_ip_availabilities"},{"line_number":14,"context_line":"          with (self.rbac_utils.override_role_and_validate_list("},{"line_number":15,"context_line":"                  self, resources\u003dresources)) as ctx:"},{"line_number":16,"context_line":"              # the list of resources available for member role"},{"line_number":17,"context_line":"              ctx.resources \u003d (self.ntp_client.list_network_ip_availabilities()"}],"source_content_type":"text/x-yaml","patch_set":15,"id":"3f79a3b5_e5776006","line":14,"range":{"start_line":14,"start_character":15,"end_line":14,"end_character":16},"in_reply_to":"3f79a3b5_e574409d","updated":"2018-11-10 03:51:45.000000000","message":"Done","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ab58dd1e1da5fc6876d96c408d02964b93fc338f","unresolved":false,"context_lines":[{"line_number":23,"context_line":"        .. code-block:: python"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"          # the resource created by admin"},{"line_number":26,"context_line":"          resource_id \u003d self.create_policy_dscp_marking_rule()"},{"line_number":27,"context_line":"          with (self.rbac_utils.override_role_and_validate_list("},{"line_number":28,"context_line":"                  self, resource_id\u003dresource_id)) as ctx:"},{"line_number":29,"context_line":"              # the list of resources available for member role"}],"source_content_type":"text/x-yaml","patch_set":15,"id":"3f79a3b5_656030d1","line":26,"range":{"start_line":26,"start_character":24,"end_line":26,"end_character":29},"updated":"2018-11-10 02:36:18.000000000","message":"self.os_admin is clearer.","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"8c97d216193276781f888bf3e14128478d9f463b","unresolved":false,"context_lines":[{"line_number":23,"context_line":"        .. code-block:: python"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"          # the resource created by admin"},{"line_number":26,"context_line":"          resource_id \u003d self.create_policy_dscp_marking_rule()"},{"line_number":27,"context_line":"          with (self.rbac_utils.override_role_and_validate_list("},{"line_number":28,"context_line":"                  self, resource_id\u003dresource_id)) as ctx:"},{"line_number":29,"context_line":"              # the list of resources available for member role"}],"source_content_type":"text/x-yaml","patch_set":15,"id":"3f79a3b5_45689420","line":26,"range":{"start_line":26,"start_character":24,"end_line":26,"end_character":29},"in_reply_to":"3f79a3b5_656030d1","updated":"2018-11-10 03:51:45.000000000","message":"Replaced to ntp_client","commit_id":"ef4ca5a5bb68d5389be2d31d7ac47e139a28d1c0"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"1852e45b9144692dc24a237cd5b6839248ba8f32","unresolved":false,"context_lines":[{"line_number":24,"context_line":"      .. code-block:: python"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"        # the resource created by admin"},{"line_number":27,"context_line":"        resource_id \u003d self.ntp_client.create_policy_dscp_marking_rule()"},{"line_number":28,"context_line":"        with self.rbac_utils.override_role_and_validate_list("},{"line_number":29,"context_line":"                self, resource_id\u003dresource_id) as ctx:"},{"line_number":30,"context_line":"            # the list of resources available for member role"}],"source_content_type":"text/x-yaml","patch_set":20,"id":"3f79a3b5_25c6ae6a","line":27,"range":{"start_line":27,"start_character":8,"end_line":27,"end_character":71},"updated":"2018-11-12 02:26:10.000000000","message":"Alternatively could do:\n\n        resource_id \u003d self.ntp_client.create_policy_dscp_marking_rule()\n        resources \u003d self.ntp_client.list_policy_dscp_marking_rules\n        with self.rbac_utils.override_role_and_validate_list(\n                self, resources\u003dresources) as ctx:\n\nThis leads to simpler validation logic but 1 more API call and slightly more difficult usage. Up to you.","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"4447bf60a2cef6c19fe5fc48cfc36b9fafd86983","unresolved":false,"context_lines":[{"line_number":24,"context_line":"      .. code-block:: python"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"        # the resource created by admin"},{"line_number":27,"context_line":"        resource_id \u003d self.ntp_client.create_policy_dscp_marking_rule()"},{"line_number":28,"context_line":"        with self.rbac_utils.override_role_and_validate_list("},{"line_number":29,"context_line":"                self, resource_id\u003dresource_id) as ctx:"},{"line_number":30,"context_line":"            # the list of resources available for member role"}],"source_content_type":"text/x-yaml","patch_set":20,"id":"3f79a3b5_e2e181fe","line":27,"range":{"start_line":27,"start_character":8,"end_line":27,"end_character":71},"in_reply_to":"3f79a3b5_25c6ae6a","updated":"2018-11-12 14:17:32.000000000","message":"This is for first mode L11, will update","commit_id":"ae99e2b05a5fcf45597f8b18163d288ca78acf34"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"cede39e3d5a287d2caaf3fd2d70d1988cc80a935","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    In order to test the list actions which doesn\u0027t have its own policy,"},{"line_number":5,"context_line":"    implemented the ``override_role_and_validate_list`` function."},{"line_number":6,"context_line":"    The function has two modes:"},{"line_number":7,"context_line":""}],"source_content_type":"text/x-yaml","patch_set":21,"id":"3f79a3b5_f460583b","line":4,"updated":"2018-11-12 21:31:44.000000000","message":"This can be added to a documentation section later under RbacUtils but for now this is great.","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":8911,"name":"Sergey Vilgelm","email":"sergey@vilgelm.info","username":"sergey.vilgelm"},"change_message_id":"e23bc6bbd02ea7f88f98609171aeef238e4a5140","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    In order to test the list actions which doesn\u0027t have its own policy,"},{"line_number":5,"context_line":"    implemented the ``override_role_and_validate_list`` function."},{"line_number":6,"context_line":"    The function has two modes:"},{"line_number":7,"context_line":""}],"source_content_type":"text/x-yaml","patch_set":21,"id":"3f79a3b5_8a253461","line":4,"in_reply_to":"3f79a3b5_f460583b","updated":"2018-11-13 15:15:31.000000000","message":"I can add in a following patch set","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":16274,"name":"Mykola Yakovliev","email":"VegasQ@gmail.com","username":"vegasq"},"change_message_id":"b9bd4af91d2fa85c9a0c4d6071100ffb3cbd8885","unresolved":false,"context_lines":[{"line_number":17,"context_line":"            policy_id\u003dself.policy_id)[\"dscp_marking_rules\"]"},{"line_number":18,"context_line":"        with self.rbac_utils.override_role_and_validate_list("},{"line_number":19,"context_line":"                self, admin_resources\u003dadmin_resources) as ctx:"},{"line_number":20,"context_line":"            # the list of resources available for member role"},{"line_number":21,"context_line":"            ctx.resources \u003d self.ntp_client.list_dscp_marking_rules("},{"line_number":22,"context_line":"                policy_id\u003dself.policy_id)[\"dscp_marking_rules\"]"},{"line_number":23,"context_line":""}],"source_content_type":"text/x-yaml","patch_set":21,"id":"3f79a3b5_9e3001ed","line":20,"range":{"start_line":20,"start_character":50,"end_line":20,"end_character":56},"updated":"2018-11-14 16:27:40.000000000","message":"nit: overwritten?","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"},{"author":{"_account_id":16274,"name":"Mykola Yakovliev","email":"VegasQ@gmail.com","username":"vegasq"},"change_message_id":"b9bd4af91d2fa85c9a0c4d6071100ffb3cbd8885","unresolved":false,"context_lines":[{"line_number":27,"context_line":"      .. code-block:: python"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"        # the resource created by admin"},{"line_number":30,"context_line":"        admin_resource_id \u003d self.ntp_client.create_policy_dscp_marking_rule()"},{"line_number":31,"context_line":"        with self.rbac_utils.override_role_and_validate_list("},{"line_number":32,"context_line":"                self, admin_resource_id\u003dadmin_resource_id) as ctx:"},{"line_number":33,"context_line":"            # the list of resources available for member role"}],"source_content_type":"text/x-yaml","patch_set":21,"id":"3f79a3b5_1e7391b5","line":30,"range":{"start_line":30,"start_character":8,"end_line":30,"end_character":77},"updated":"2018-11-14 16:27:40.000000000","message":"nit: [\"policy_dscp_marking_rule\"][\"id\"]","commit_id":"714c9de6f4ded79362145da730123a1ffca434d6"}]}
