From 5b33fa245536b11e53ec9ebe362deee21ea0db21 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Fri, 20 Jan 2023 09:26:45 +0100 Subject: [PATCH] OCPBUGS-6086: OpenStack: Force JSON content-type in Swift Some OpenStack object storages respond with `204 No Content` to list requests when there are no containers or objects to list. In these cases, when responding to requests with an `Accept: text/plain` or no `Accept` header, some object storages omit the `content-type` header in their status-204 responses. Now, Gophercloud throws an error when the response does not contain a `content-type` header. With this change, we work around the issue by forcing Gophercloud to request a JSON response from the object storage when listing containers. When passed an `Accept: application/json` header, the server responds with `220 OK` and a `content-type` header in our tests. This solution gives us a fix that is easily backportable because it doesn't require any dependency bump. --- pkg/destroy/openstack/openstack.go | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/pkg/destroy/openstack/openstack.go b/pkg/destroy/openstack/openstack.go index f849e14fe12..ae059d79490 100644 --- a/pkg/destroy/openstack/openstack.go +++ b/pkg/destroy/openstack/openstack.go @@ -992,7 +992,20 @@ func deleteContainers(opts *clientconfig.ClientOpts, filter Filter, logger logru logger.Error(err) return false, nil } - listOpts := containers.ListOpts{Full: false} + // Listing with `Full == true` so that Gophercloud sets the `Accept` + // header to `application/json`. If `Full` is not true, Gophercloud + // sets `Accept: text/plain`, to which some objectstorage instances may + // respond with an HTTP status code of 204 in case there are no + // occurrencies to list. Some, but not all, of these objectstorage + // instances omit the `content-type` header from their 204 responses. + // While being perfectly correct, this case is mishandled by the + // currently vendored version of Gophercloud. On the other hand, the + // JSON response always HTTP status code 200, a JSON content (possibly + // `{}`), and most importantly a `content-type` header. + // + // This option can be reverted to `false` once Gophercloud learns to + // correctly handle empty 204 responses. + listOpts := containers.ListOpts{Full: true} allPages, err := containers.List(conn, listOpts).AllPages() if err != nil { @@ -1040,6 +1053,20 @@ func deleteContainers(opts *clientconfig.ClientOpts, filter Filter, logger logru if metadata[titlekey] == val { logger.Debugf("Bulk deleting container %q objects", container) pager := objects.List(conn, container, &objects.ListOpts{ + // Listing with `Full == true` so that Gophercloud sets the `Accept` + // header to `application/json`. If `Full` is not true, Gophercloud + // sets `Accept: text/plain`, to which some objectstorage instances may + // respond with an HTTP status code of 204 in case there are no + // occurrences to list. Some, but not all, of these objectstorage + // instances omit the `content-type` header from their 204 responses. + // While being perfectly correct, this case is mishandled by the + // currently vendored version of Gophercloud. On the other hand, the + // JSON response always HTTP status code 200, a JSON content (possibly + // `{}`), and most importantly a `content-type` header. + // + // This option can be reverted to `false` once Gophercloud learns to + // correctly handle empty 204 responses. + Full: true, Limit: 50, }) err = pager.EachPage(func(page pagination.Page) (bool, error) {