)]}'
{"releasenotes/notes/autohold-revamp-047011cedd3c8da9.yaml":[{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"14aca61570d5788efe664e82348a873b3cef4a0e","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":"    A new zuul CLI command, autohold-delete has been added support deleting"},{"line_number":5,"context_line":"    autohold requests that are now stored in ZooKeeper rather than memory."}],"source_content_type":"text/x-yaml","patch_set":13,"id":"5faad753_b30c84a5","line":3,"updated":"2019-09-13 18:17:54.000000000","message":"nit: perhaps starts mentioning that autohold request being stored persistently in ZooKeeper, autohold-delete is an extra effect","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"7816e16446d5cd4d3e6b3c194f0667c932d640f7","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":"    A new zuul CLI command, autohold-delete has been added support deleting"},{"line_number":5,"context_line":"    autohold requests that are now stored in ZooKeeper rather than memory."}],"source_content_type":"text/x-yaml","patch_set":13,"id":"5faad753_864ec835","line":3,"in_reply_to":"5faad753_b30c84a5","updated":"2019-09-16 12:48:39.000000000","message":"Done","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"}],"tests/unit/test_scheduler.py":[{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"b5e06c417be0c59a903a6397c1d108d69414c080","unresolved":false,"context_lines":[{"line_number":1700,"context_line":"        self.assertIsNotNone(request)"},{"line_number":1701,"context_line":""},{"line_number":1702,"context_line":"        # Delete and verify no more requests"},{"line_number":1703,"context_line":"        self.sched.autohold_delete(request.id)"},{"line_number":1704,"context_line":"        request_list \u003d self.zk.getHoldRequests()"},{"line_number":1705,"context_line":"        self.assertEqual([], request_list)"},{"line_number":1706,"context_line":""},{"line_number":1707,"context_line":"    def _test_autohold_scoped(self, change_obj, change, ref):"},{"line_number":1708,"context_line":"        client \u003d zuul.rpcclient.RPCClient(\u0027127.0.0.1\u0027,"}],"source_content_type":"text/x-python","patch_set":6,"id":"bfb3d3c7_e22d0e95","line":1705,"range":{"start_line":1703,"start_character":1,"end_line":1705,"end_character":42},"updated":"2019-05-30 17:57:30.000000000","message":"This should use client.autohold_delete()","commit_id":"004c65bb0b66a4fdc8f13c5e939fe9edd8b90a2f"}],"zuul/cmd/client.py":[{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"2ad212629c42327fad1b86e7dccbe0a2ed950fe1","unresolved":false,"context_lines":[{"line_number":444,"context_line":""},{"line_number":445,"context_line":"    def autohold_delete(self):"},{"line_number":446,"context_line":"        client \u003d zuul.rpcclient.RPCClient("},{"line_number":447,"context_line":"            self.server, self.port, self.ssl_key, self.ssl_cert, self.ssl_ca)"},{"line_number":448,"context_line":"        return client.autohold_delete(self.args.id)"},{"line_number":449,"context_line":""},{"line_number":450,"context_line":"    def autohold_list(self):"}],"source_content_type":"text/x-python","patch_set":13,"id":"5faad753_b3956435","line":447,"range":{"start_line":447,"start_character":17,"end_line":447,"end_character":23},"updated":"2019-09-13 18:09:52.000000000","message":"there is no such server attribute. Why not using the get_client() procedure?","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"7816e16446d5cd4d3e6b3c194f0667c932d640f7","unresolved":false,"context_lines":[{"line_number":444,"context_line":""},{"line_number":445,"context_line":"    def autohold_delete(self):"},{"line_number":446,"context_line":"        client \u003d zuul.rpcclient.RPCClient("},{"line_number":447,"context_line":"            self.server, self.port, self.ssl_key, self.ssl_cert, self.ssl_ca)"},{"line_number":448,"context_line":"        return client.autohold_delete(self.args.id)"},{"line_number":449,"context_line":""},{"line_number":450,"context_line":"    def autohold_list(self):"}],"source_content_type":"text/x-python","patch_set":13,"id":"5faad753_a676646f","line":447,"range":{"start_line":447,"start_character":17,"end_line":447,"end_character":23},"in_reply_to":"5faad753_b3956435","updated":"2019-09-16 12:48:39.000000000","message":"Done","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"08820056a9323f5e17895d13f10e2f73e09dd540","unresolved":false,"context_lines":[{"line_number":444,"context_line":""},{"line_number":445,"context_line":"    def autohold_delete(self):"},{"line_number":446,"context_line":"        client \u003d zuul.rpcclient.RPCClient("},{"line_number":447,"context_line":"            self.server, self.port, self.ssl_key, self.ssl_cert, self.ssl_ca)"},{"line_number":448,"context_line":"        return client.autohold_delete(self.args.id)"},{"line_number":449,"context_line":""},{"line_number":450,"context_line":"    def autohold_list(self):"}],"source_content_type":"text/x-python","patch_set":13,"id":"5faad753_73028c71","line":447,"range":{"start_line":447,"start_character":17,"end_line":447,"end_character":23},"in_reply_to":"5faad753_b3956435","updated":"2019-09-13 18:17:52.000000000","message":"I think this was probably missed in the rebase against the admin changes from Matthieu.","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"}],"zuul/scheduler.py":[{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"3d87e59cbf1400df3f4a099f5e429a93b6ee616a","unresolved":false,"context_lines":[{"line_number":562,"context_line":"        request.job \u003d job_name"},{"line_number":563,"context_line":"        request.ref_filter \u003d ref_filter"},{"line_number":564,"context_line":"        request.reason \u003d reason"},{"line_number":565,"context_line":"        request.count \u003d count"},{"line_number":566,"context_line":"        request.node_expiration \u003d node_hold_expiration"},{"line_number":567,"context_line":""},{"line_number":568,"context_line":"        # No need to lock it since we are creating a new one."}],"source_content_type":"text/x-python","patch_set":13,"id":"5faad753_f3151ce6","line":565,"range":{"start_line":565,"start_character":16,"end_line":565,"end_character":21},"updated":"2019-09-13 18:02:24.000000000","message":"This should be max_count","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"7816e16446d5cd4d3e6b3c194f0667c932d640f7","unresolved":false,"context_lines":[{"line_number":562,"context_line":"        request.job \u003d job_name"},{"line_number":563,"context_line":"        request.ref_filter \u003d ref_filter"},{"line_number":564,"context_line":"        request.reason \u003d reason"},{"line_number":565,"context_line":"        request.count \u003d count"},{"line_number":566,"context_line":"        request.node_expiration \u003d node_hold_expiration"},{"line_number":567,"context_line":""},{"line_number":568,"context_line":"        # No need to lock it since we are creating a new one."}],"source_content_type":"text/x-python","patch_set":13,"id":"5faad753_8667a8b7","line":565,"range":{"start_line":565,"start_character":16,"end_line":565,"end_character":21},"in_reply_to":"5faad753_f3151ce6","updated":"2019-09-16 12:48:39.000000000","message":"Done","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"08820056a9323f5e17895d13f10e2f73e09dd540","unresolved":false,"context_lines":[{"line_number":562,"context_line":"        request.job \u003d job_name"},{"line_number":563,"context_line":"        request.ref_filter \u003d ref_filter"},{"line_number":564,"context_line":"        request.reason \u003d reason"},{"line_number":565,"context_line":"        request.count \u003d count"},{"line_number":566,"context_line":"        request.node_expiration \u003d node_hold_expiration"},{"line_number":567,"context_line":""},{"line_number":568,"context_line":"        # No need to lock it since we are creating a new one."}],"source_content_type":"text/x-python","patch_set":13,"id":"5faad753_d3c26034","line":565,"range":{"start_line":565,"start_character":16,"end_line":565,"end_character":21},"in_reply_to":"5faad753_f3151ce6","updated":"2019-09-13 18:17:52.000000000","message":"Oh, that\u0027s a good spot.\n\nNow I\u0027m concerned about why our testing didn\u0027t catch this. That should have thrown an exception.","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"6e652a511c842aaed3344e0ee29d30851df0d7f4","unresolved":false,"context_lines":[{"line_number":597,"context_line":"                          hold_request_id)"},{"line_number":598,"context_line":"            return"},{"line_number":599,"context_line":""},{"line_number":600,"context_line":"        # (TODO): Release any nodes held for this request here"},{"line_number":601,"context_line":""},{"line_number":602,"context_line":"        self.log.debug(\"Removing autohold %s\", hold_request)"},{"line_number":603,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":14,"id":"3fa7e38b_f8d83980","line":600,"updated":"2019-09-16 16:55:07.000000000","message":"I don\u0027t think this got done later in the stack.  Should this be part of this feature?  It seems that if we do, then we can say that the entire hold UX has moved into Zuul (so in no cases does anyone need to log into a nodepool machine and delete autoheld nodes).","commit_id":"716ac1f2e18394dcb47ac6e02e12313b6fdf18ec"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"12cc7e036e2a5555f30a0904709d966feee33ec7","unresolved":false,"context_lines":[{"line_number":597,"context_line":"                          hold_request_id)"},{"line_number":598,"context_line":"            return"},{"line_number":599,"context_line":""},{"line_number":600,"context_line":"        # (TODO): Release any nodes held for this request here"},{"line_number":601,"context_line":""},{"line_number":602,"context_line":"        self.log.debug(\"Removing autohold %s\", hold_request)"},{"line_number":603,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":14,"id":"3fa7e38b_98c82575","line":600,"in_reply_to":"3fa7e38b_f8d83980","updated":"2019-09-16 17:03:54.000000000","message":"Comment is just outdated. It is eventually done within the deleteHoldRequest() call itself, rather than here. See https://review.opendev.org/#/c/664060/14/zuul/zk.py","commit_id":"716ac1f2e18394dcb47ac6e02e12313b6fdf18ec"}],"zuul/web/__init__.py":[{"author":{"_account_id":7186,"name":"Matthieu Huin","email":"mhuin@redhat.com","username":"mhu"},"change_message_id":"a8852db7e8a498bcd71f358c4b56744af9508a5c","unresolved":false,"context_lines":[{"line_number":352,"context_line":""},{"line_number":353,"context_line":"    @cherrypy.expose"},{"line_number":354,"context_line":"    @cherrypy.tools.json_out(content_type\u003d\u0027application/json; charset\u003dutf-8\u0027)"},{"line_number":355,"context_line":"    def autohold(self, tenant, project\u003dNone):"},{"line_number":356,"context_line":"        # we don\u0027t use json_in because a payload is not mandatory with GET"},{"line_number":357,"context_line":"        # Note: GET handling is redundant with autohold_list"},{"line_number":358,"context_line":"        # and could be removed."},{"line_number":359,"context_line":"        if cherrypy.request.method \u003d\u003d \u0027GET\u0027:"},{"line_number":360,"context_line":"            return self._autohold_list(tenant, project)"},{"line_number":361,"context_line":"        elif cherrypy.request.method \u003d\u003d \u0027POST\u0027:"},{"line_number":362,"context_line":"            basic_error \u003d self._basic_auth_header_check()"},{"line_number":363,"context_line":"            if basic_error is not None:"},{"line_number":364,"context_line":"                return basic_error"},{"line_number":365,"context_line":"            # AuthN/AuthZ"},{"line_number":366,"context_line":"            rawToken \u003d \\"},{"line_number":367,"context_line":"                cherrypy.request.headers[\u0027Authorization\u0027][len(\u0027Bearer \u0027):]"},{"line_number":368,"context_line":"            try:"},{"line_number":369,"context_line":"                claims \u003d self.zuulweb.authenticators.authenticate(rawToken)"},{"line_number":370,"context_line":"            except exceptions.AuthTokenException as e:"},{"line_number":371,"context_line":"                for header, contents in e.getAdditionalHeaders().items():"},{"line_number":372,"context_line":"                    cherrypy.response.headers[header] \u003d contents"},{"line_number":373,"context_line":"                cherrypy.response.status \u003d e.HTTPError"},{"line_number":374,"context_line":"                return \u0027\u003ch1\u003e%s\u003c/h1\u003e\u0027 % e.error_description"},{"line_number":375,"context_line":"            self.is_authorized(claims, tenant)"},{"line_number":376,"context_line":"            msg \u003d \u0027User \"%s\" requesting \"%s\" on %s/%s\u0027"},{"line_number":377,"context_line":"            self.log.info("},{"line_number":378,"context_line":"                msg % (claims[\u0027__zuul_uid_claim\u0027], \u0027autohold\u0027,"},{"line_number":379,"context_line":"                       tenant, project))"},{"line_number":380,"context_line":""},{"line_number":381,"context_line":"            length \u003d int(cherrypy.request.headers[\u0027Content-Length\u0027])"},{"line_number":382,"context_line":"            body \u003d cherrypy.request.body.read(length)"}],"source_content_type":"text/x-python","patch_set":13,"id":"7faddb67_021a3417","line":379,"range":{"start_line":355,"start_character":0,"end_line":379,"end_character":40},"updated":"2019-08-27 17:01:12.000000000","message":"You can base autohold_by_request_id (see below) on this boilerplate code:\n\n- replace args with request_id\n- test the HTTP verbs for GET (autohold-info) and DELETE (autohold-delete)\n- keep the AuthN/Z part then add the actual logic after\n\nThe autohold-delete call should return HTTP 202 (accepted but not enacted yet) upon success since I assume this\u0027ll be handled asynchronously; this can be done with\n\ncherrypy.response.status \u003d \u0027202\u0027","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"},{"author":{"_account_id":7186,"name":"Matthieu Huin","email":"mhuin@redhat.com","username":"mhu"},"change_message_id":"a8852db7e8a498bcd71f358c4b56744af9508a5c","unresolved":false,"context_lines":[{"line_number":422,"context_line":"                    if (project is None or"},{"line_number":423,"context_line":"                            request[\u0027project\u0027].endswith(project)):"},{"line_number":424,"context_line":"                        result.append("},{"line_number":425,"context_line":"                            {\u0027tenant\u0027: request[\u0027tenant\u0027],"},{"line_number":426,"context_line":"                             \u0027project\u0027: request[\u0027project\u0027],"},{"line_number":427,"context_line":"                             \u0027job\u0027: request[\u0027job\u0027],"},{"line_number":428,"context_line":"                             \u0027ref_filter\u0027: request[\u0027ref_filter\u0027],"},{"line_number":429,"context_line":"                             \u0027count\u0027: request[\u0027max_count\u0027],"},{"line_number":430,"context_line":"                             \u0027reason\u0027: request[\u0027reason\u0027],"},{"line_number":431,"context_line":"                             \u0027node_hold_expiration\u0027: request[\u0027node_expiration\u0027]"},{"line_number":432,"context_line":"                            })"},{"line_number":433,"context_line":"            return result"},{"line_number":434,"context_line":""},{"line_number":435,"context_line":"    @cherrypy.expose"}],"source_content_type":"text/x-python","patch_set":13,"id":"7faddb67_7f63851a","line":432,"range":{"start_line":425,"start_character":0,"end_line":432,"end_character":29},"updated":"2019-08-27 17:01:12.000000000","message":"You can probably just append the request dictionary directly, unless there\u0027s more info than needed in it. It should include the request ID as well","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"},{"author":{"_account_id":7186,"name":"Matthieu Huin","email":"mhuin@redhat.com","username":"mhu"},"change_message_id":"a8852db7e8a498bcd71f358c4b56744af9508a5c","unresolved":false,"context_lines":[{"line_number":1007,"context_line":"                          controller\u003dapi, action\u003d\u0027index\u0027)"},{"line_number":1008,"context_line":"        route_map.connect(\u0027api\u0027, \u0027/api/info\u0027,"},{"line_number":1009,"context_line":"                          controller\u003dapi, action\u003d\u0027info\u0027)"},{"line_number":1010,"context_line":"        route_map.connect(\u0027api\u0027, \u0027/api/connections\u0027,"},{"line_number":1011,"context_line":"                          controller\u003dapi, action\u003d\u0027connections\u0027)"},{"line_number":1012,"context_line":"        route_map.connect(\u0027api\u0027, \u0027/api/tenants\u0027,"},{"line_number":1013,"context_line":"                          controller\u003dapi, action\u003d\u0027tenants\u0027)"},{"line_number":1014,"context_line":"        route_map.connect(\u0027api\u0027, \u0027/api/tenant/{tenant}/info\u0027,"}],"source_content_type":"text/x-python","patch_set":13,"id":"7faddb67_827624a3","line":1011,"range":{"start_line":1010,"start_character":0,"end_line":1011,"end_character":63},"updated":"2019-08-27 17:01:12.000000000","message":"You can add\n\nroute_map.connect(\u0027api\u0027, \u0027/api/autohold/{request_id}\u0027,\n                          controller\u003dapi\u0027, action\u003d\u0027autohold_by_request_id\u0027)\n\nand then define autohold_by_request_id similarly to autohold above, but with the HTTP DELETE verb instead of POST.","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"}],"zuul/zk.py":[{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"14aca61570d5788efe664e82348a873b3cef4a0e","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    REQUEST_ROOT \u003d \u0027/nodepool/requests\u0027"},{"line_number":44,"context_line":"    REQUEST_LOCK_ROOT \u003d \"/nodepool/requests-lock\""},{"line_number":45,"context_line":"    NODE_ROOT \u003d \u0027/nodepool/nodes\u0027"},{"line_number":46,"context_line":"    HOLD_REQUEST_ROOT \u003d \u0027/zuul/hold-requests/\u0027"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    # Log zookeeper retry every 10 seconds"},{"line_number":49,"context_line":"    retry_log_rate \u003d 10"}],"source_content_type":"text/x-python","patch_set":13,"id":"5faad753_f3ed1cb7","line":46,"range":{"start_line":46,"start_character":44,"end_line":46,"end_character":45},"updated":"2019-09-13 18:17:54.000000000","message":"the / could be dropped in this PS for consistency.","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"7816e16446d5cd4d3e6b3c194f0667c932d640f7","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    REQUEST_ROOT \u003d \u0027/nodepool/requests\u0027"},{"line_number":44,"context_line":"    REQUEST_LOCK_ROOT \u003d \"/nodepool/requests-lock\""},{"line_number":45,"context_line":"    NODE_ROOT \u003d \u0027/nodepool/nodes\u0027"},{"line_number":46,"context_line":"    HOLD_REQUEST_ROOT \u003d \u0027/zuul/hold-requests/\u0027"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    # Log zookeeper retry every 10 seconds"},{"line_number":49,"context_line":"    retry_log_rate \u003d 10"}],"source_content_type":"text/x-python","patch_set":13,"id":"5faad753_86bfa8a8","line":46,"range":{"start_line":46,"start_character":44,"end_line":46,"end_character":45},"in_reply_to":"5faad753_f3ed1cb7","updated":"2019-09-16 12:48:39.000000000","message":"Note: Sure, but I did that to drop a lot of ugly \"/\" appending below.","commit_id":"865738290b934ff5fa3051cd44c26946d56f79a1"}]}
