)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":34373,"name":"Jason Paroly","email":"jparoly@redhat.com","username":"jparoly"},"change_message_id":"3de0ba1cd080bebe4e093c586ee9e318d0855c6d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"1b452570_36974dc0","updated":"2026-03-16 15:50:36.000000000","message":"Sorry for reviewing maybe too early but once I got started I figured it may help you out.  If not, and you were already going to clean it up, feel free to close these out.  I am trying to get my feet wet with tempest code reviews so please pardon the interruption :-).  I used claude to help with this review.  Thank you.","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"a01e80b267f3190084cc0b2141631549bf953b2f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"c98dfb76_33e25c7f","updated":"2026-04-10 19:32:55.000000000","message":"@jparoly@redhat.com thank you for providing enhanced review 😊. I have updated my code as per the feedback. Let me know if there is anything else I can add","commit_id":"fac7b4694385a5f3c10413a40b0c33d33c1345f1"},{"author":{"_account_id":32704,"name":"Alfredo Garcia","display_name":"Alfredo Garcia","email":"alfrgarc@redhat.com","username":"alfrgarc","status":"Senior Software Quality Engineer @ Red Hat"},"change_message_id":"90299463f142208c115f88678fc237d35b238f21","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"482c5cfd_a871b40b","updated":"2026-04-16 13:54:41.000000000","message":"Ack, thank you for addressing my concerns. The change LGTM","commit_id":"fac7b4694385a5f3c10413a40b0c33d33c1345f1"},{"author":{"_account_id":34373,"name":"Jason Paroly","email":"jparoly@redhat.com","username":"jparoly"},"change_message_id":"5a82344e6393aade2d127db906e106c4adeb6376","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"7c06ee69_89938896","updated":"2026-04-17 13:51:24.000000000","message":"looks like \"autopep8\" file was added?  looks empty.  Is this intentional, normal?","commit_id":"fac7b4694385a5f3c10413a40b0c33d33c1345f1"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"d678b20d8b04da290997747cf7bbfaf838864fed","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"64c412e9_3f6fba89","in_reply_to":"7c06ee69_89938896","updated":"2026-04-17 14:04:26.000000000","message":"Done","commit_id":"fac7b4694385a5f3c10413a40b0c33d33c1345f1"},{"author":{"_account_id":32704,"name":"Alfredo Garcia","display_name":"Alfredo Garcia","email":"alfrgarc@redhat.com","username":"alfrgarc","status":"Senior Software Quality Engineer @ Red Hat"},"change_message_id":"64652215b882f171f4d826aec201531357f99a52","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"d89c7f15_18e1d94e","updated":"2026-04-21 12:48:53.000000000","message":"Re-adding my +1. The changes still LGTM and the gates are passing","commit_id":"46b735aa0dc06dd7e689fa10eaf66267533e80ca"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"0ee68602c6136f6534de56abef4e75c106ca50e0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"fc4e4f52_3371919e","updated":"2026-05-07 19:15:30.000000000","message":"also, test is skipped i tempest-full-py3 job, do you know which job enable Symlink and run these new tests.\n\nsetUpClass (tempest.api.object_storage.test_object_symlink.ObjectSymlinkTest) ... SKIPPED: Symlink not supported in this environment\n\nhttps://zuul.opendev.org/t/openstack/build/d237895635e7495fa0c2e57859562a8d/log/job-output.txt#23922","commit_id":"46b735aa0dc06dd7e689fa10eaf66267533e80ca"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"d4698ad5d4bd548ab8ae90edd9c70e73606e77c8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"5b1c5f75_e94a09dd","updated":"2026-04-17 16:20:53.000000000","message":"recheck network issue","commit_id":"46b735aa0dc06dd7e689fa10eaf66267533e80ca"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"1a13653fcbfed6c0b990dd1e1bd39e6e20337fa4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"0eac111a_f84656d0","updated":"2026-06-04 18:28:55.000000000","message":"Also, let me know which job run these tests. those are skipped in tempest-full-py3 https://zuul.opendev.org/t/openstack/build/6226b775680d48b38c49d34ea0ea21f1/log/job-output.txt#23902","commit_id":"e316d82b1f4f79a13464ed49d6e481bb3168ee23"},{"author":{"_account_id":10459,"name":"Luigi Toscano","email":"ltoscano@redhat.com","username":"ltoscano"},"change_message_id":"d6ecba707059a0def03a7d2200c3d7df8558dd4d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"40abc8c4_4fd37fa2","updated":"2026-06-18 12:15:56.000000000","message":"It looks like the failure of openstack-tox-docs is something that needs to be addressed:\n\n\nThe following test modules lack an automodule RST entry:\n  tempest.api.object_storage.test_object_symlink","commit_id":"0c43dcfcae1d4e00f09657de0ff63289dea36f23"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"3c211a55e39e9b40976947cd2d05c07b4f75d0f6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"ab3df637_a24c726d","in_reply_to":"40abc8c4_4fd37fa2","updated":"2026-06-18 13:39:56.000000000","message":"Done, addressed the following issue related to .rst file","commit_id":"0c43dcfcae1d4e00f09657de0ff63289dea36f23"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"d404db2e65c2556ded2fd5d525dd76becea4a840","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":11,"id":"ec07e1ad_da703d95","updated":"2026-06-20 01:53:32.000000000","message":"thanks, all test passing https://zuul.opendev.org/t/openstack/build/f5dcf09b92d448e99d01e40b7fb3bd55/log/job-output.txt#24033","commit_id":"08b9c41b95f3a8405a8211ffcf8e2195b5c40fe5"}],"tempest/api/object_storage/test_object_symlink.py":[{"author":{"_account_id":34373,"name":"Jason Paroly","email":"jparoly@redhat.com","username":"jparoly"},"change_message_id":"3de0ba1cd080bebe4e093c586ee9e318d0855c6d","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2013 NTT Corporation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":2,"id":"8f2c6ca6_0559dcca","line":1,"updated":"2026-03-16 15:50:36.000000000","message":"This appears to be copy-pasted from another file. Should be updated to reflect the actual copyright holder and year (2026)","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"a01e80b267f3190084cc0b2141631549bf953b2f","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2013 NTT Corporation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":2,"id":"e05d3fc3_8eef6003","line":1,"in_reply_to":"8f2c6ca6_0559dcca","updated":"2026-04-10 19:32:55.000000000","message":"Done","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":34373,"name":"Jason Paroly","email":"jparoly@redhat.com","username":"jparoly"},"change_message_id":"3de0ba1cd080bebe4e093c586ee9e318d0855c6d","unresolved":true,"context_lines":[{"line_number":21,"context_line":"from tempest.lib import exceptions as lib_exc"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"class SymlinkCLITest(base.BaseObjectTest):"},{"line_number":25,"context_line":"    \"\"\"Tempest test for Swift symbolic link objects (symlinks)\"\"\""},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"5c854b99_c3eb978c","line":24,"updated":"2026-03-16 15:50:36.000000000","message":"The class is named SymlinkCLITest but these are API tests, not CLI tests\n  - Should follow the pattern of other object storage tests: ObjectSymlinkTest or SymlinkTest   ???","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"a01e80b267f3190084cc0b2141631549bf953b2f","unresolved":false,"context_lines":[{"line_number":21,"context_line":"from tempest.lib import exceptions as lib_exc"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"class SymlinkCLITest(base.BaseObjectTest):"},{"line_number":25,"context_line":"    \"\"\"Tempest test for Swift symbolic link objects (symlinks)\"\"\""},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"291d3ced_f207a975","line":24,"in_reply_to":"5c854b99_c3eb978c","updated":"2026-04-10 19:32:55.000000000","message":"Done","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":34373,"name":"Jason Paroly","email":"jparoly@redhat.com","username":"jparoly"},"change_message_id":"3de0ba1cd080bebe4e093c586ee9e318d0855c6d","unresolved":true,"context_lines":[{"line_number":24,"context_line":"class SymlinkCLITest(base.BaseObjectTest):"},{"line_number":25,"context_line":"    \"\"\"Tempest test for Swift symbolic link objects (symlinks)\"\"\""},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    def setUp(self):"},{"line_number":28,"context_line":"        super(SymlinkCLITest, self).setUp()"},{"line_number":29,"context_line":"        self.containers \u003d []"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    def tearDown(self):"},{"line_number":32,"context_line":"        object_storage.delete_containers("},{"line_number":33,"context_line":"            self.containers, self.container_client, self.object_client"},{"line_number":34,"context_line":"        )"},{"line_number":35,"context_line":"        super(SymlinkCLITest, self).tearDown()"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def _create_container(self):"},{"line_number":38,"context_line":"        container_name \u003d data_utils.rand_name(\u0027symlink-container\u0027)"}],"source_content_type":"text/x-python","patch_set":2,"id":"b7168b1a_7f6aaf54","line":35,"range":{"start_line":27,"start_character":3,"end_line":35,"end_character":46},"updated":"2026-03-16 15:50:36.000000000","message":"Inefficient Resource Management ?\n  The test uses instance-level setUp()/tearDown() methods which create/delete containers for each test method. Looking at other tests like test_object_expiry.py and test_object_services.py, the pattern should\n  be:\n\n  @classmethod\n  def resource_setup(cls):\n      super(ObjectSymlinkTest, cls).resource_setup()\n      cls.container_name \u003d cls.create_container()\n\n  @classmethod\n  def resource_cleanup(cls):\n      cls.delete_containers()\n      super(ObjectSymlinkTest, cls).resource_cleanup()","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"a01e80b267f3190084cc0b2141631549bf953b2f","unresolved":false,"context_lines":[{"line_number":24,"context_line":"class SymlinkCLITest(base.BaseObjectTest):"},{"line_number":25,"context_line":"    \"\"\"Tempest test for Swift symbolic link objects (symlinks)\"\"\""},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    def setUp(self):"},{"line_number":28,"context_line":"        super(SymlinkCLITest, self).setUp()"},{"line_number":29,"context_line":"        self.containers \u003d []"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    def tearDown(self):"},{"line_number":32,"context_line":"        object_storage.delete_containers("},{"line_number":33,"context_line":"            self.containers, self.container_client, self.object_client"},{"line_number":34,"context_line":"        )"},{"line_number":35,"context_line":"        super(SymlinkCLITest, self).tearDown()"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def _create_container(self):"},{"line_number":38,"context_line":"        container_name \u003d data_utils.rand_name(\u0027symlink-container\u0027)"}],"source_content_type":"text/x-python","patch_set":2,"id":"e9cec942_36d40f0d","line":35,"range":{"start_line":27,"start_character":3,"end_line":35,"end_character":46},"in_reply_to":"b7168b1a_7f6aaf54","updated":"2026-04-10 19:32:55.000000000","message":"Done","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":34373,"name":"Jason Paroly","email":"jparoly@redhat.com","username":"jparoly"},"change_message_id":"3de0ba1cd080bebe4e093c586ee9e318d0855c6d","unresolved":true,"context_lines":[{"line_number":49,"context_line":"    def test_symlink(self):"},{"line_number":50,"context_line":"        \"\"\"Test symlink creation and download\"\"\""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        # Step 1: Create container"},{"line_number":53,"context_line":"        container_name \u003d self._create_container()"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        # Step 2: Upload object"}],"source_content_type":"text/x-python","patch_set":2,"id":"780baf08_81121c9e","line":52,"updated":"2026-03-16 15:50:36.000000000","message":"no need for verbose comments like this.  the code speaks for itself here.\nThe \"Step 1:\", \"Step 2:\", \"Step 3:\" style comments (lines 52-101) are inconsistent with the codebase style. Other tests use simpler inline comments like # create object, # verify metadata.","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"a01e80b267f3190084cc0b2141631549bf953b2f","unresolved":false,"context_lines":[{"line_number":49,"context_line":"    def test_symlink(self):"},{"line_number":50,"context_line":"        \"\"\"Test symlink creation and download\"\"\""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        # Step 1: Create container"},{"line_number":53,"context_line":"        container_name \u003d self._create_container()"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        # Step 2: Upload object"}],"source_content_type":"text/x-python","patch_set":2,"id":"d3355da3_c552a306","line":52,"in_reply_to":"780baf08_81121c9e","updated":"2026-04-10 19:32:55.000000000","message":"Acknowledged","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":34373,"name":"Jason Paroly","email":"jparoly@redhat.com","username":"jparoly"},"change_message_id":"3de0ba1cd080bebe4e093c586ee9e318d0855c6d","unresolved":true,"context_lines":[{"line_number":69,"context_line":"        self.assertEqual(201, resp.status)"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"        # Step 4: Verify symlink metadata"},{"line_number":72,"context_line":"        link_name \u003d \u0027link.txt\u0027  # the symlink object"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"        # Get the container listing"},{"line_number":75,"context_line":"        params \u003d {\u0027limit\u0027: 9999, \u0027format\u0027: \u0027json\u0027}"}],"source_content_type":"text/x-python","patch_set":2,"id":"501d7487_f7505ae3","line":72,"updated":"2026-03-16 15:50:36.000000000","message":"already defined in line 61","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"a01e80b267f3190084cc0b2141631549bf953b2f","unresolved":false,"context_lines":[{"line_number":69,"context_line":"        self.assertEqual(201, resp.status)"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"        # Step 4: Verify symlink metadata"},{"line_number":72,"context_line":"        link_name \u003d \u0027link.txt\u0027  # the symlink object"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"        # Get the container listing"},{"line_number":75,"context_line":"        params \u003d {\u0027limit\u0027: 9999, \u0027format\u0027: \u0027json\u0027}"}],"source_content_type":"text/x-python","patch_set":2,"id":"75e6fae0_570f7233","line":72,"in_reply_to":"501d7487_f7505ae3","updated":"2026-04-10 19:32:55.000000000","message":"Done","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":34373,"name":"Jason Paroly","email":"jparoly@redhat.com","username":"jparoly"},"change_message_id":"3de0ba1cd080bebe4e093c586ee9e318d0855c6d","unresolved":true,"context_lines":[{"line_number":139,"context_line":"    def test_broken_symlink(self):"},{"line_number":140,"context_line":"        \"\"\"Test behavior when symlink target does not exist\"\"\""},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"        container_name \u003d self._create_container()"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"        # Step 2: Create a symlink pointing to a non-existent object"},{"line_number":145,"context_line":"        link_name \u003d \"broken_link.txt\""},{"line_number":146,"context_line":"        missing_object \u003d \"missing.txt\""},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"        target \u003d f\"{container_name}/{missing_object}\""},{"line_number":149,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"33c4a892_a1728b8f","line":146,"range":{"start_line":142,"start_character":5,"end_line":146,"end_character":38},"updated":"2026-03-16 15:50:36.000000000","message":"There\u0027s a \"Step 2\" but no \"Step 1\" but comments do not need \"step...\" part like noted in the prior comment.","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"a01e80b267f3190084cc0b2141631549bf953b2f","unresolved":false,"context_lines":[{"line_number":139,"context_line":"    def test_broken_symlink(self):"},{"line_number":140,"context_line":"        \"\"\"Test behavior when symlink target does not exist\"\"\""},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"        container_name \u003d self._create_container()"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"        # Step 2: Create a symlink pointing to a non-existent object"},{"line_number":145,"context_line":"        link_name \u003d \"broken_link.txt\""},{"line_number":146,"context_line":"        missing_object \u003d \"missing.txt\""},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"        target \u003d f\"{container_name}/{missing_object}\""},{"line_number":149,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"14038c46_2103d6c4","line":146,"range":{"start_line":142,"start_character":5,"end_line":146,"end_character":38},"in_reply_to":"33c4a892_a1728b8f","updated":"2026-04-10 19:32:55.000000000","message":"Done","commit_id":"a354af1c1889d841b91fd243ce00001e3e065748"},{"author":{"_account_id":32704,"name":"Alfredo Garcia","display_name":"Alfredo Garcia","email":"alfrgarc@redhat.com","username":"alfrgarc","status":"Senior Software Quality Engineer @ Red Hat"},"change_message_id":"ad0f3fdf44ff9934179e8de536358f2921f68e97","unresolved":true,"context_lines":[{"line_number":79,"context_line":"        self._upload_object(container_name, object_name, file_content)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"        link_name \u003d \"link.txt\""},{"line_number":82,"context_line":"        target \u003d f\"{container_name}/{object_name}\""},{"line_number":83,"context_line":"        headers \u003d {\"X-Symlink-Target\": target, \"Content-Length\": \"0\"}"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"        resp, _ \u003d self.object_client.create_object("}],"source_content_type":"text/x-python","patch_set":3,"id":"af991833_c04fe5a7","line":82,"updated":"2026-04-14 15:13:14.000000000","message":"Should this include an additional leading forward slash?\nf\"/{container_name}/{object_name}\"","commit_id":"fac7b4694385a5f3c10413a40b0c33d33c1345f1"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"b74626409bb925f4df4480456a73fa9f0469795d","unresolved":true,"context_lines":[{"line_number":79,"context_line":"        self._upload_object(container_name, object_name, file_content)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"        link_name \u003d \"link.txt\""},{"line_number":82,"context_line":"        target \u003d f\"{container_name}/{object_name}\""},{"line_number":83,"context_line":"        headers \u003d {\"X-Symlink-Target\": target, \"Content-Length\": \"0\"}"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"        resp, _ \u003d self.object_client.create_object("}],"source_content_type":"text/x-python","patch_set":3,"id":"f53bcf26_11e74274","line":82,"in_reply_to":"af991833_c04fe5a7","updated":"2026-04-16 08:11:22.000000000","message":"The Swift API requires the exact format \u003ccontainer\u003e/\u003cobject\u003e. Adding a leading / (i.e. /container/object) is invalid and causes 412 Precondition Failed.","commit_id":"fac7b4694385a5f3c10413a40b0c33d33c1345f1"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"e99fd886cc4d6247346ea045113cb56dffabf8fd","unresolved":false,"context_lines":[{"line_number":79,"context_line":"        self._upload_object(container_name, object_name, file_content)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"        link_name \u003d \"link.txt\""},{"line_number":82,"context_line":"        target \u003d f\"{container_name}/{object_name}\""},{"line_number":83,"context_line":"        headers \u003d {\"X-Symlink-Target\": target, \"Content-Length\": \"0\"}"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"        resp, _ \u003d self.object_client.create_object("}],"source_content_type":"text/x-python","patch_set":3,"id":"a6f294db_aa932410","line":82,"in_reply_to":"f53bcf26_11e74274","updated":"2026-04-16 08:11:46.000000000","message":"Done","commit_id":"fac7b4694385a5f3c10413a40b0c33d33c1345f1"},{"author":{"_account_id":32704,"name":"Alfredo Garcia","display_name":"Alfredo Garcia","email":"alfrgarc@redhat.com","username":"alfrgarc","status":"Senior Software Quality Engineer @ Red Hat"},"change_message_id":"ad0f3fdf44ff9934179e8de536358f2921f68e97","unresolved":true,"context_lines":[{"line_number":129,"context_line":"    def test_broken_symlink(self):"},{"line_number":130,"context_line":"        container_name \u003d self._create_container()"},{"line_number":131,"context_line":"        link_name \u003d \"broken_link.txt\""},{"line_number":132,"context_line":"        target \u003d f\"{container_name}/missing.txt\""},{"line_number":133,"context_line":"        headers \u003d {\"X-Symlink-Target\": target, \"Content-Length\": \"0\"}"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        # Swift may reject broken symlinks; skip if not allowed"}],"source_content_type":"text/x-python","patch_set":3,"id":"b79cd4ba_13882418","line":132,"updated":"2026-04-14 15:13:14.000000000","message":"Same here, should there be a leading forward slash?\nf\"/{container_name}/{object_name}\"","commit_id":"fac7b4694385a5f3c10413a40b0c33d33c1345f1"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"b74626409bb925f4df4480456a73fa9f0469795d","unresolved":false,"context_lines":[{"line_number":129,"context_line":"    def test_broken_symlink(self):"},{"line_number":130,"context_line":"        container_name \u003d self._create_container()"},{"line_number":131,"context_line":"        link_name \u003d \"broken_link.txt\""},{"line_number":132,"context_line":"        target \u003d f\"{container_name}/missing.txt\""},{"line_number":133,"context_line":"        headers \u003d {\"X-Symlink-Target\": target, \"Content-Length\": \"0\"}"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        # Swift may reject broken symlinks; skip if not allowed"}],"source_content_type":"text/x-python","patch_set":3,"id":"8d18caf7_f18dfeea","line":132,"in_reply_to":"b79cd4ba_13882418","updated":"2026-04-16 08:11:22.000000000","message":"Done","commit_id":"fac7b4694385a5f3c10413a40b0c33d33c1345f1"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"0ee68602c6136f6534de56abef4e75c106ca50e0","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2026 NTT Corporation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":4,"id":"f65c2e93_22377d34","line":1,"range":{"start_line":1,"start_character":17,"end_line":1,"end_character":32},"updated":"2026-05-07 19:15:30.000000000","message":"is this correct?","commit_id":"46b735aa0dc06dd7e689fa10eaf66267533e80ca"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"4f716b6a6f07bc312b0a8a756500066b5d2afa39","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2026 NTT Corporation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":4,"id":"1cedf125_f25ef080","line":1,"range":{"start_line":1,"start_character":17,"end_line":1,"end_character":32},"in_reply_to":"f65c2e93_22377d34","updated":"2026-06-19 00:23:17.000000000","message":"Done","commit_id":"46b735aa0dc06dd7e689fa10eaf66267533e80ca"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"0ee68602c6136f6534de56abef4e75c106ca50e0","unresolved":true,"context_lines":[{"line_number":50,"context_line":"            raise cls.skipException("},{"line_number":51,"context_line":"                \"Symlink not supported in this environment\")"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"        # Clean up the check container"},{"line_number":54,"context_line":"        object_storage.delete_containers("},{"line_number":55,"context_line":"            cls.containers, cls.container_client, cls.object_client)"},{"line_number":56,"context_line":"        cls.containers \u003d []"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    @classmethod"}],"source_content_type":"text/x-python","patch_set":4,"id":"6de7ad37_7eab861e","line":55,"range":{"start_line":53,"start_character":0,"end_line":55,"end_character":68},"updated":"2026-05-07 19:15:30.000000000","message":"you are deleting the containers before test run, is that what you wanted?","commit_id":"46b735aa0dc06dd7e689fa10eaf66267533e80ca"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"4f716b6a6f07bc312b0a8a756500066b5d2afa39","unresolved":false,"context_lines":[{"line_number":50,"context_line":"            raise cls.skipException("},{"line_number":51,"context_line":"                \"Symlink not supported in this environment\")"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"        # Clean up the check container"},{"line_number":54,"context_line":"        object_storage.delete_containers("},{"line_number":55,"context_line":"            cls.containers, cls.container_client, cls.object_client)"},{"line_number":56,"context_line":"        cls.containers \u003d []"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    @classmethod"}],"source_content_type":"text/x-python","patch_set":4,"id":"896c12ec_08524bd4","line":55,"range":{"start_line":53,"start_character":0,"end_line":55,"end_character":68},"in_reply_to":"6de7ad37_7eab861e","updated":"2026-06-19 00:23:17.000000000","message":"Done","commit_id":"46b735aa0dc06dd7e689fa10eaf66267533e80ca"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"1a13653fcbfed6c0b990dd1e1bd39e6e20337fa4","unresolved":true,"context_lines":[{"line_number":32,"context_line":"        # Check if symlink is supported in this environment"},{"line_number":33,"context_line":"        container_name \u003d data_utils.rand_name(\u0027symlink-check\u0027)"},{"line_number":34,"context_line":"        cls.container_client.create_container(container_name)"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"        headers \u003d {"},{"line_number":37,"context_line":"            \"X-Symlink-Target\": \"nonexistent/container\","},{"line_number":38,"context_line":"            \"Content-Length\": \"0\""},{"line_number":39,"context_line":"        }"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        symlink_supported \u003d True"},{"line_number":42,"context_line":"        try:"},{"line_number":43,"context_line":"            resp, _ \u003d cls.object_client.create_object("},{"line_number":44,"context_line":"                container_name, \"test-link\", b\u0027\u0027, headers\u003dheaders"},{"line_number":45,"context_line":"            )"},{"line_number":46,"context_line":"        except (lib_exc.UnexpectedContentType, lib_exc.BadRequest):"},{"line_number":47,"context_line":"            symlink_supported \u003d False"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"        try:"},{"line_number":50,"context_line":"            cls.object_client.delete_object(container_name, \"test-link\")"}],"source_content_type":"text/x-python","patch_set":5,"id":"9f1b0d68_d6e595a1","line":47,"range":{"start_line":35,"start_character":0,"end_line":47,"end_character":37},"updated":"2026-06-04 18:28:55.000000000","message":"is this is only way to know if Symlink is supported or not? or is it configurable in swift?","commit_id":"e316d82b1f4f79a13464ed49d6e481bb3168ee23"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"ebdc71dc60878e39536ba95555354c7cd1822136","unresolved":false,"context_lines":[{"line_number":32,"context_line":"        # Check if symlink is supported in this environment"},{"line_number":33,"context_line":"        container_name \u003d data_utils.rand_name(\u0027symlink-check\u0027)"},{"line_number":34,"context_line":"        cls.container_client.create_container(container_name)"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"        headers \u003d {"},{"line_number":37,"context_line":"            \"X-Symlink-Target\": \"nonexistent/container\","},{"line_number":38,"context_line":"            \"Content-Length\": \"0\""},{"line_number":39,"context_line":"        }"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        symlink_supported \u003d True"},{"line_number":42,"context_line":"        try:"},{"line_number":43,"context_line":"            resp, _ \u003d cls.object_client.create_object("},{"line_number":44,"context_line":"                container_name, \"test-link\", b\u0027\u0027, headers\u003dheaders"},{"line_number":45,"context_line":"            )"},{"line_number":46,"context_line":"        except (lib_exc.UnexpectedContentType, lib_exc.BadRequest):"},{"line_number":47,"context_line":"            symlink_supported \u003d False"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"        try:"},{"line_number":50,"context_line":"            cls.object_client.delete_object(container_name, \"test-link\")"}],"source_content_type":"text/x-python","patch_set":5,"id":"fc6a3c8a_170e2427","line":47,"range":{"start_line":35,"start_character":0,"end_line":47,"end_character":37},"in_reply_to":"69f4d17f_e7d56a4d","updated":"2026-06-18 13:51:24.000000000","message":"Implemented: Capabilities API approach (querying\ncls.capabilities_client.list_capabilities()), looks like the previous approach is not working, now lets see how it goes from here.","commit_id":"e316d82b1f4f79a13464ed49d6e481bb3168ee23"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"14484c7ae9c80e3d400bbe4d782761b40f50b026","unresolved":false,"context_lines":[{"line_number":32,"context_line":"        # Check if symlink is supported in this environment"},{"line_number":33,"context_line":"        container_name \u003d data_utils.rand_name(\u0027symlink-check\u0027)"},{"line_number":34,"context_line":"        cls.container_client.create_container(container_name)"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"        headers \u003d {"},{"line_number":37,"context_line":"            \"X-Symlink-Target\": \"nonexistent/container\","},{"line_number":38,"context_line":"            \"Content-Length\": \"0\""},{"line_number":39,"context_line":"        }"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        symlink_supported \u003d True"},{"line_number":42,"context_line":"        try:"},{"line_number":43,"context_line":"            resp, _ \u003d cls.object_client.create_object("},{"line_number":44,"context_line":"                container_name, \"test-link\", b\u0027\u0027, headers\u003dheaders"},{"line_number":45,"context_line":"            )"},{"line_number":46,"context_line":"        except (lib_exc.UnexpectedContentType, lib_exc.BadRequest):"},{"line_number":47,"context_line":"            symlink_supported \u003d False"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"        try:"},{"line_number":50,"context_line":"            cls.object_client.delete_object(container_name, \"test-link\")"}],"source_content_type":"text/x-python","patch_set":5,"id":"69f4d17f_e7d56a4d","line":47,"range":{"start_line":35,"start_character":0,"end_line":47,"end_character":37},"in_reply_to":"9f1b0d68_d6e595a1","updated":"2026-06-18 09:31:07.000000000","message":"Thank you for the feedback! also I believe there\u0027s is another way to check if symlink is supported or not by Capabilities API approach (querying\ncls.capabilities_client.list_capabilities()), which is the standard Swift discovery method.\n  \nI implemented by, creating a valid target first(instead of broken symlink to \"nonexistent/container\"), adding finally block for cleanup, and fixing the order.\n  \nLet me know if you\u0027d prefer the Capabilities API instead.\n\nI also checked the tempest-full-py3 logs and under pipeline section in: log/controller/logs/etc/swift/proxy-server_conf.txt, symlink is enabled, maybe it was failing with the broken symlink logic in my code, which I tried fixing it.","commit_id":"e316d82b1f4f79a13464ed49d6e481bb3168ee23"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"4f716b6a6f07bc312b0a8a756500066b5d2afa39","unresolved":false,"context_lines":[{"line_number":32,"context_line":"        # Check if symlink is supported in this environment"},{"line_number":33,"context_line":"        container_name \u003d data_utils.rand_name(\u0027symlink-check\u0027)"},{"line_number":34,"context_line":"        cls.container_client.create_container(container_name)"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"        headers \u003d {"},{"line_number":37,"context_line":"            \"X-Symlink-Target\": \"nonexistent/container\","},{"line_number":38,"context_line":"            \"Content-Length\": \"0\""},{"line_number":39,"context_line":"        }"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        symlink_supported \u003d True"},{"line_number":42,"context_line":"        try:"},{"line_number":43,"context_line":"            resp, _ \u003d cls.object_client.create_object("},{"line_number":44,"context_line":"                container_name, \"test-link\", b\u0027\u0027, headers\u003dheaders"},{"line_number":45,"context_line":"            )"},{"line_number":46,"context_line":"        except (lib_exc.UnexpectedContentType, lib_exc.BadRequest):"},{"line_number":47,"context_line":"            symlink_supported \u003d False"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"        try:"},{"line_number":50,"context_line":"            cls.object_client.delete_object(container_name, \"test-link\")"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa89281a_31b44742","line":47,"range":{"start_line":35,"start_character":0,"end_line":47,"end_character":37},"in_reply_to":"fc6a3c8a_170e2427","updated":"2026-06-19 00:23:17.000000000","message":"Thanks, this lgtm. Now i can see test running but it is failing\n\nhttps://zuul.opendev.org/t/openstack/build/c0dec3be6710487096d0137ae0a8d87a/log/job-output.txt#23928\n\n Captured traceback:\n2026-06-18 15:01:01.804110 | controller | ~~~~~~~~~~~~~~~~~~~\n2026-06-18 15:01:01.804128 | controller |     Traceback (most recent call last):\n2026-06-18 15:01:01.804152 | controller |\n2026-06-18 15:01:01.804165 | controller |       File \"/opt/stack/tempest/tempest/api/object_storage/test_object_symlink.py\", line 130, in test_broken_symlink\n2026-06-18 15:01:01.804181 | controller |     resp, _ \u003d self.object_client.create_object(\n2026-06-18 15:01:01.804193 | controller |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n2026-06-18 15:01:01.804205 | controller |\n2026-06-18 15:01:01.804217 | controller |       File \"/opt/stack/tempest/tempest/lib/services/object_storage/object_client.py\", line 51, in create_object\n2026-06-18 15:01:01.804228 | controller |     resp, body \u003d self.put(url, data, headers, chunked\u003dchunked)\n2026-06-18 15:01:01.804240 | controller |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n2026-06-18 15:01:01.804251 | controller |\n2026-06-18 15:01:01.804263 | controller |       File \"/opt/stack/tempest/tempest/lib/common/rest_client.py\", line 395, in put\n2026-06-18 15:01:01.804274 | controller |     return self.request(\u0027PUT\u0027, url, extra_headers, headers, body, chunked)\n2026-06-18 15:01:01.804286 | controller |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n2026-06-18 15:01:01.804298 | controller |\n2026-06-18 15:01:01.804310 | controller |       File \"/opt/stack/tempest/tempest/lib/common/rest_client.py\", line 767, in request\n2026-06-18 15:01:01.804321 | controller |     self._error_checker(resp, resp_body)\n2026-06-18 15:01:01.804333 | controller |\n2026-06-18 15:01:01.804344 | controller |       File \"/opt/stack/tempest/tempest/lib/common/rest_client.py\", line 861, in _error_checker\n2026-06-18 15:01:01.804355 | controller |     raise exceptions.UnexpectedContentType(str(resp.status),\n2026-06-18 15:01:01.804385 | controller |\n2026-06-18 15:01:01.804396 | controller |     tempest.lib.exceptions.UnexpectedContentType: Unexpected content type provided\n2026-06-18 15:01:01.804405 | controller | Details: 400","commit_id":"e316d82b1f4f79a13464ed49d6e481bb3168ee23"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"1a13653fcbfed6c0b990dd1e1bd39e6e20337fa4","unresolved":true,"context_lines":[{"line_number":51,"context_line":"        except lib_exc.NotFound:"},{"line_number":52,"context_line":"            pass"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        cls.container_client.delete_container(container_name)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"        if not symlink_supported:"},{"line_number":57,"context_line":"            raise cls.skipException("}],"source_content_type":"text/x-python","patch_set":5,"id":"42533380_5717c8c9","line":54,"range":{"start_line":54,"start_character":0,"end_line":54,"end_character":61},"updated":"2026-06-04 18:28:55.000000000","message":"I will say, to add this as cleanup right after L34 so that we do not leak this container if any other failure during object creation/deletion.","commit_id":"e316d82b1f4f79a13464ed49d6e481bb3168ee23"},{"author":{"_account_id":38173,"name":"Tanvi Nautiyal","email":"tnautiya@redhat.com","username":"tnautiyal"},"change_message_id":"14484c7ae9c80e3d400bbe4d782761b40f50b026","unresolved":false,"context_lines":[{"line_number":51,"context_line":"        except lib_exc.NotFound:"},{"line_number":52,"context_line":"            pass"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        cls.container_client.delete_container(container_name)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"        if not symlink_supported:"},{"line_number":57,"context_line":"            raise cls.skipException("}],"source_content_type":"text/x-python","patch_set":5,"id":"6c737eaf_411e8b5e","line":54,"range":{"start_line":54,"start_character":0,"end_line":54,"end_character":61},"in_reply_to":"42533380_5717c8c9","updated":"2026-06-18 09:31:07.000000000","message":"Fixed! I\u0027ve added a finally block to ensure cleanup always happens, even if unexpected exceptions occur during object creation/deletion. The container deletion now happens in the finally block right after the try statement,preventing any potential container leaks.","commit_id":"e316d82b1f4f79a13464ed49d6e481bb3168ee23"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"56526b49cfbbe4fba3f7f199b441a135db6d8644","unresolved":false,"context_lines":[{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    @decorators.idempotent_id(\u0027e13c6786-bbe8-4f8b-9b79-1216fe5879d1\u0027)"},{"line_number":108,"context_line":"    def test_cross_container_symlink(self):"},{"line_number":109,"context_line":"        \"\"\"Test creating a symlink pointing to an object in another container\"\"\""},{"line_number":110,"context_line":"        source_container \u003d self._create_container()"},{"line_number":111,"context_line":"        object_name \u003d \"file.txt\""},{"line_number":112,"context_line":"        file_content \u003d os.urandom(20)"}],"source_content_type":"text/x-python","patch_set":10,"id":"2bf19211_73b388dd","line":109,"updated":"2026-06-19 17:13:04.000000000","message":"pep8: E501 line too long (80 \u003e 79 characters)","commit_id":"d930c49820aee44b0e58db9dc309c26852c99f26"}]}
