From a0b5dd46def95a1114f63af69174d6da60c2cf4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Thu, 6 Jul 2023 10:45:32 +0900 Subject: [PATCH 001/118] [v1][CI] Drop periodic jobs from stable branch Periodic jobs can't run against non-default branches with github action. Remove them from our stable branches to avoid confusion. According to the github documentation [1]: Scheduled workflows run on the latest commit on the default or base branch. [1] https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule --- .github/workflows/codeql-analysis.yml | 2 -- .github/workflows/functional-baremetal.yaml | 2 -- .github/workflows/functional-basic.yaml | 2 -- .github/workflows/functional-blockstorage.yaml | 2 -- .github/workflows/functional-clustering.yaml | 2 -- .github/workflows/functional-compute.yaml | 2 -- .github/workflows/functional-containerinfra.yaml | 2 -- .github/workflows/functional-dns.yaml | 2 -- .github/workflows/functional-fwaas_v2.yaml | 2 -- .github/workflows/functional-identity.yaml | 2 -- .github/workflows/functional-imageservice.yaml | 2 -- .github/workflows/functional-keymanager.yaml | 2 -- .github/workflows/functional-loadbalancer.yaml | 2 -- .github/workflows/functional-messaging.yaml | 2 -- .github/workflows/functional-networking.yaml | 2 -- .github/workflows/functional-objectstorage.yaml | 2 -- .github/workflows/functional-orchestration.yaml | 2 -- .github/workflows/functional-placement.yaml | 2 -- .github/workflows/functional-sharedfilesystems.yaml | 2 -- 19 files changed, 38 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index db762de4d7..3832784cb4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -6,8 +6,6 @@ on: pull_request: # The branches below must be a subset of the branches above branches: [ master ] - schedule: - - cron: '18 8 * * 6' jobs: analyze: diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index 0ae2f53a29..277245d1c6 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**baremetal**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-baremetal: strategy: diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index 727fb9d1e0..982e006151 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -6,8 +6,6 @@ on: - '**.md' - '**.gitignore' - '**LICENSE' - schedule: - - cron: '0 0 */3 * *' jobs: functional-basic: strategy: diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index 07624e7cb1..4dfd04de59 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**blockstorage**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-blockstorage: strategy: diff --git a/.github/workflows/functional-clustering.yaml b/.github/workflows/functional-clustering.yaml index 110920487b..fa9a8a5a46 100644 --- a/.github/workflows/functional-clustering.yaml +++ b/.github/workflows/functional-clustering.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**clustering**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-clustering: strategy: diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index 188064e4dc..99448f7e48 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**compute**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-compute: strategy: diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index 4f1aca8db3..9dbd8dc5da 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**containerinfra**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-containerinfra: strategy: diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index ec9b829d96..a14e0fbf02 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -4,8 +4,6 @@ on: paths: - '**openstack/dns**' - '**functional-dns.yaml' - schedule: - - cron: '0 0 */3 * *' jobs: functional-dns: strategy: diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml index 4c0b4463ee..ecd53ef5be 100644 --- a/.github/workflows/functional-fwaas_v2.yaml +++ b/.github/workflows/functional-fwaas_v2.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**networking/extensions/fwaas_v2**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-fwaas_v2: strategy: diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml index 9cf1a44b8b..df0764beb0 100644 --- a/.github/workflows/functional-identity.yaml +++ b/.github/workflows/functional-identity.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**identity**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-identity: strategy: diff --git a/.github/workflows/functional-imageservice.yaml b/.github/workflows/functional-imageservice.yaml index 7b1c3fefd9..77ee23bad4 100644 --- a/.github/workflows/functional-imageservice.yaml +++ b/.github/workflows/functional-imageservice.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**imageservice**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-imageservice: strategy: diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml index cd270e7416..42f097c655 100644 --- a/.github/workflows/functional-keymanager.yaml +++ b/.github/workflows/functional-keymanager.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**keymanager**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-keymanager: strategy: diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml index 843f3645c5..0b8cc40f6b 100644 --- a/.github/workflows/functional-loadbalancer.yaml +++ b/.github/workflows/functional-loadbalancer.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**loadbalancer**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-loadbalancer: strategy: diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml index b727eafbce..8314a1b496 100644 --- a/.github/workflows/functional-messaging.yaml +++ b/.github/workflows/functional-messaging.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**messaging**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-messaging: strategy: diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index 3f69e5abbe..feca87453b 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**networking**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-networking: strategy: diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml index f43f6cad8a..125a7add35 100644 --- a/.github/workflows/functional-objectstorage.yaml +++ b/.github/workflows/functional-objectstorage.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**objectstorage**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-objectstorage: strategy: diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml index 12dbe82a63..90391c4520 100644 --- a/.github/workflows/functional-orchestration.yaml +++ b/.github/workflows/functional-orchestration.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**orchestration**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-orchestration: strategy: diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml index 57d5990b0a..71b24efcce 100644 --- a/.github/workflows/functional-placement.yaml +++ b/.github/workflows/functional-placement.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**placement**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-placement: strategy: diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml index b72c33e75c..7d552435ef 100644 --- a/.github/workflows/functional-sharedfilesystems.yaml +++ b/.github/workflows/functional-sharedfilesystems.yaml @@ -3,8 +3,6 @@ on: pull_request: paths: - '**sharedfilesystems**' - schedule: - - cron: '0 0 */3 * *' jobs: functional-sharedfilesystems: strategy: From 0a5bb2b306e046f4035b6d311a2b43036815902c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Mon, 10 Jul 2023 09:53:55 +0900 Subject: [PATCH 002/118] [v1] Remove the Ensure labels workflow These labels are synced from the master branch. --- .github/semver-labels.yaml | 9 --------- .github/workflows/semver-labels.yaml | 18 ------------------ 2 files changed, 27 deletions(-) delete mode 100644 .github/semver-labels.yaml delete mode 100644 .github/workflows/semver-labels.yaml diff --git a/.github/semver-labels.yaml b/.github/semver-labels.yaml deleted file mode 100644 index 7e9c8811b5..0000000000 --- a/.github/semver-labels.yaml +++ /dev/null @@ -1,9 +0,0 @@ -- name: semver:major - description: Breaking change - color: '9E1957' -- name: semver:minor - description: Backwards-compatible change - color: 'FBCA04' -- name: semver:patch - description: No API change - color: '6E7624' diff --git a/.github/workflows/semver-labels.yaml b/.github/workflows/semver-labels.yaml deleted file mode 100644 index ccaf44522b..0000000000 --- a/.github/workflows/semver-labels.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: Ensure labels -on: - push: - branches: - - master - paths: - - .github/semver-labels.yaml - - .github/workflows/semver-labels.yaml -jobs: - semver: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: micnncim/action-label-syncer@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - manifest: .github/semver-labels.yaml From 457c1cfe72af78492f9004e22954fc57394959e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Mon, 10 Jul 2023 09:56:56 +0900 Subject: [PATCH 003/118] [v1] Allow running 'CodeQL' job for non-master branches Drop the branch filter that was in place to allow running the `CodeQL` job from any branch. Partial backport of 9a407d6. --- .github/workflows/codeql-analysis.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 3832784cb4..38cf2bfb08 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,11 +1,6 @@ name: "CodeQL" -on: - push: - branches: [ master ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ master ] +on: [push, pull_request] jobs: analyze: From 2d1a32f709c97a50706b74a7dc4739a8a9514d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Mon, 10 Jul 2023 10:05:48 +0900 Subject: [PATCH 004/118] [v1] Update Readme Remove obsolete link to travis-ci, and update branch for coveralls.io badge. --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 89b08156fe..e2520361de 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Gophercloud: an OpenStack SDK for Go -[![Build Status](https://travis-ci.org/gophercloud/gophercloud.svg?branch=master)](https://travis-ci.org/gophercloud/gophercloud) -[![Coverage Status](https://coveralls.io/repos/github/gophercloud/gophercloud/badge.svg?branch=master)](https://coveralls.io/github/gophercloud/gophercloud?branch=master) +[![Coverage Status](https://coveralls.io/repos/github/gophercloud/gophercloud/badge.svg?branch=v1)](https://coveralls.io/github/gophercloud/gophercloud?branch=v1) Gophercloud is an OpenStack Go SDK. From 73dd87c5fc6441dda2f3292a18fe912ef023c734 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Tue, 1 Aug 2023 11:21:54 -0400 Subject: [PATCH 005/118] README: minor change to test backport workflow --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e2520361de..4e6e57dadb 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ You will need to retrieve the following: Credentials, a pre-generated token, or any other supported authentication mechanism. -For users that have the OpenStack dashboard installed, there's a shortcut. If +For users who have the OpenStack dashboard installed, there's a shortcut. If you visit the `project/api_access` path in Horizon and click on the "Download OpenStack RC File" button at the top right hand corner, you can download either a `clouds.yaml` file or an `openrc` bash file that exports all From b1d38dd1cc7b069dad1ab2bb40e385471c2a2d52 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Wed, 28 Jun 2023 15:31:34 -0400 Subject: [PATCH 006/118] tests: run MultiAttach with a capable Cinder Type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting from the Queens release, it is possible to attach a volume to multiple hosts/servers, using a volume type with multiattach capability. Cinder previously had a `multiattach` parameter that could be passed during the volume creation. This parameter was recently removed [1], and caused our jobs to fail. This commit change the tests to no longer use the removed parameter. Fixes #2657. Co-Authored-By: Martin André [1] https://github.com/openstack/cinder/commit/d4535c77493a7b362091b962f42f2613dea65dbe --- .../openstack/blockstorage/v3/blockstorage.go | 32 ++++++++++++++++++- .../openstack/blockstorage/v3/volumes_test.go | 11 ++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/acceptance/openstack/blockstorage/v3/blockstorage.go b/acceptance/openstack/blockstorage/v3/blockstorage.go index 5e05024a1c..1645f327b6 100644 --- a/acceptance/openstack/blockstorage/v3/blockstorage.go +++ b/acceptance/openstack/blockstorage/v3/blockstorage.go @@ -177,6 +177,36 @@ func CreateVolumeTypeNoExtraSpecs(t *testing.T, client *gophercloud.ServiceClien return vt, nil } +// CreateVolumeTypeMultiAttach will create a volume type with a random name and +// extra specs for multi-attach. An error will be returned if the volume type was +// unable to be created. +func CreateVolumeTypeMultiAttach(t *testing.T, client *gophercloud.ServiceClient) (*volumetypes.VolumeType, error) { + name := tools.RandomString("ACPTTEST", 16) + description := "create_from_gophercloud" + t.Logf("Attempting to create volume type: %s", name) + + createOpts := volumetypes.CreateOpts{ + Name: name, + ExtraSpecs: map[string]string{"multiattach": " True"}, + Description: description, + } + + vt, err := volumetypes.Create(client, createOpts).Extract() + if err != nil { + return nil, err + } + + tools.PrintResource(t, vt) + th.AssertEquals(t, vt.IsPublic, true) + th.AssertEquals(t, vt.Name, name) + th.AssertEquals(t, vt.Description, description) + th.AssertEquals(t, vt.ExtraSpecs["multiattach"], " True") + + t.Logf("Successfully created volume type: %s", vt.ID) + + return vt, nil +} + // CreatePrivateVolumeType will create a private volume type with a random // name and no extra specs. An error will be returned if the volume type was // unable to be created. @@ -268,7 +298,7 @@ func DeleteVolumeType(t *testing.T, client *gophercloud.ServiceClient, vt *volum err := volumetypes.Delete(client, vt.ID).ExtractErr() if err != nil { - t.Fatalf("Unable to delete volume %s: %v", vt.ID, err) + t.Fatalf("Unable to delete volume type %s: %v", vt.ID, err) } t.Logf("Successfully deleted volume type: %s", vt.ID) diff --git a/acceptance/openstack/blockstorage/v3/volumes_test.go b/acceptance/openstack/blockstorage/v3/volumes_test.go index 186b32f039..b86f70863a 100644 --- a/acceptance/openstack/blockstorage/v3/volumes_test.go +++ b/acceptance/openstack/blockstorage/v3/volumes_test.go @@ -67,30 +67,33 @@ func TestVolumes(t *testing.T) { } func TestVolumesMultiAttach(t *testing.T) { + clients.RequireAdmin(t) clients.RequireLong(t) client, err := clients.NewBlockStorageV3Client() th.AssertNoErr(t, err) + vt, err := CreateVolumeTypeMultiAttach(t, client) + th.AssertNoErr(t, err) + defer DeleteVolumeType(t, client, vt) + volumeName := tools.RandomString("ACPTTEST", 16) volOpts := volumes.CreateOpts{ Size: 1, Name: volumeName, Description: "Testing creation of multiattach enabled volume", - Multiattach: true, + VolumeType: vt.ID, } vol, err := volumes.Create(client, volOpts).Extract() th.AssertNoErr(t, err) + defer DeleteVolume(t, client, vol) err = volumes.WaitForStatus(client, vol.ID, "available", 60) th.AssertNoErr(t, err) th.AssertEquals(t, vol.Multiattach, true) - - err = volumes.Delete(client, vol.ID, volumes.DeleteOpts{}).ExtractErr() - th.AssertNoErr(t, err) } func TestVolumesCascadeDelete(t *testing.T) { From 7ac6befb2db699aa48e60c1a44a19be2c831813c Mon Sep 17 00:00:00 2001 From: georgeb Date: Wed, 7 Jun 2023 17:12:16 +0200 Subject: [PATCH 007/118] Add CRUD support for encryption in volume v3 types Add Create/Delete/Update/Get support for encryption of volume types --- .../blockstorage/v3/volumetypes_test.go | 42 +++++++ openstack/blockstorage/v3/volumetypes/doc.go | 58 +++++++++ .../blockstorage/v3/volumetypes/requests.go | 105 ++++++++++++++++ .../blockstorage/v3/volumetypes/results.go | 99 +++++++++++++++ .../v3/volumetypes/testing/fixtures.go | 117 ++++++++++++++++++ .../v3/volumetypes/testing/requests_test.go | 96 ++++++++++++++ openstack/blockstorage/v3/volumetypes/urls.go | 20 +++ 7 files changed, 537 insertions(+) diff --git a/acceptance/openstack/blockstorage/v3/volumetypes_test.go b/acceptance/openstack/blockstorage/v3/volumetypes_test.go index b640a63f55..73fa32722a 100644 --- a/acceptance/openstack/blockstorage/v3/volumetypes_test.go +++ b/acceptance/openstack/blockstorage/v3/volumetypes_test.go @@ -163,3 +163,45 @@ func TestVolumeTypesAccess(t *testing.T) { th.AssertEquals(t, len(accessList), 0) } + +func TestEncryptionVolumeTypes(t *testing.T) { + clients.RequireAdmin(t) + + client, err := clients.NewBlockStorageV3Client() + th.AssertNoErr(t, err) + + vt, err := CreateVolumeType(t, client) + th.AssertNoErr(t, err) + defer DeleteVolumeType(t, client, vt) + + createEncryptionOpts := volumetypes.EncryptionOptions{ + KeySize: 256, + Provider: "luks", + ControlLocation: "front-end", + Cipher: "aes-xts-plain64", + } + + eVT, err := volumetypes.CreateEncryption(client, vt.ID, createEncryptionOpts) + th.AssertNoErr(t, err) + defer DeleteEncryption(t, client, evt) + + geVT, err := volumetypes.GetEncryption(client, vt.ID).Extract() + th.AssertNoErr(t, err) + tools.PrintResource(t, geVT) + + key := "cipher" + gesVT, err := volumetypes.GetEncryptionSpec(client, vt.ID, key).Extract() + th.AssertNoErr(t, err) + tools.PrintResource(t, gesVT) + + + updateEncryptionOpts := volumetypes.EncryptionUpdateOpts{ + ControlLocation: "back-end", + } + + newEVT, err := volumetypes.Update(client, vt.ID, updateEncryptionOpts).Extract() + th.AssertNoErr(t, err) + + tools.PrintResource(t, newEVT) + th.AssertEquals(t, "back-end", newEVT.ControlLocation) +} diff --git a/openstack/blockstorage/v3/volumetypes/doc.go b/openstack/blockstorage/v3/volumetypes/doc.go index 55a2170bc2..d532e7262a 100644 --- a/openstack/blockstorage/v3/volumetypes/doc.go +++ b/openstack/blockstorage/v3/volumetypes/doc.go @@ -160,5 +160,63 @@ Example to Remove/Revoke Access to a Volume Type if err != nil { panic(err) } + +Example to Create the Encryption of a Volume Type + typeID := "7ffaca22-f646-41d4-b79d-d7e4452ef8cc" + volumeType, err := volumetypes.CreateEncryption(client, typeID, .CreateEncryptionOpts{ + KeySize: 256, + Provider: "luks", + ControlLocation: "front-end", + Cipher: "aes-xts-plain64", + }).Extract() + if err != nil{ + panic(err) + } + fmt.Println(volumeType) + +Example to Delete the Encryption of a Volume Type + + typeID := "7ffaca22-f646-41d4-b79d-d7e4452ef8cc" + encryptionID := ""81e069c6-7394-4856-8df7-3b237ca61f74 + err := volumetypes.DeleteEncryption(client, typeID, encryptionID).ExtractErr() + if err != nil{ + panic(err) + } + +Example to Update the Encryption of a Volume Type + + typeID := "7ffaca22-f646-41d4-b79d-d7e4452ef8cc" + volumetype, err = volumetypes.UpdateEncryption(client, typeID, volumetypes.UpdateEncryptionOpts{ + KeySize: 256, + Provider: "luks", + ControlLocation: "front-end", + Cipher: "aes-xts-plain64", + }).Extract() + if err != nil{ + panic(err) + } + fmt.Println(volumetype) + +Example to Show an Encryption of a Volume Type + + typeID := "7ffaca22-f646-41d4-b79d-d7e4452ef8cc" + volumeType, err := volumetypes.GetEncrytpion(client, typeID).Extract() + if err != nil{ + panic(err) + } + fmt.Println(volumeType) + +Example to Show an Encryption Spec of a Volume Type + + typeID := "7ffaca22-f646-41d4-b79d-d7e4452ef8cc" + key := "cipher" + volumeType, err := volumetypes.GetEncrytpionSpec(client, typeID).Extract() + if err != nil{ + panic(err) + } + fmt.Println(volumeType) + + + */ package volumetypes diff --git a/openstack/blockstorage/v3/volumetypes/requests.go b/openstack/blockstorage/v3/volumetypes/requests.go index 5b272bf05b..4b7e561bc2 100644 --- a/openstack/blockstorage/v3/volumetypes/requests.go +++ b/openstack/blockstorage/v3/volumetypes/requests.go @@ -304,3 +304,108 @@ func RemoveAccess(client *gophercloud.ServiceClient, id string, opts RemoveAcces _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } + +// CreateEncryptionOptsBuilder allows extensions to add additional parameters to the +// Create Encryption request. +type CreateEncryptionOptsBuilder interface { + ToEncryptionCreateMap() (map[string]interface{}, error) +} + +// CreateEncryptionOpts contains options for creating an Encryption Type object. +// This object is passed to the volumetypes.CreateEncryption function. +// For more information about these parameters,see the Encryption Type object. +type CreateEncryptionOpts struct { + // The size of the encryption key. + KeySize int `json:"key_size"` + // The class of that provides the encryption support. + Provider string `json:"provider" required:"true"` + // Notional service where encryption is performed. + ControlLocation string `json:"control_location"` + // The encryption algorithm or mode. + Cipher string `json:"cipher"` +} + +// ToEncryptionCreateMap assembles a request body based on the contents of a +// CreateEncryptionOpts. +func (opts CreateEncryptionOpts) ToEncryptionCreateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "encryption") +} + +// CreateEncryption will creates an Encryption Type object based on the CreateEncryptionOpts. +// To extract the Encryption Type object from the response, call the Extract method on the +// EncryptionCreateResult. +func CreateEncryption(client *gophercloud.ServiceClient, id string, opts CreateEncryptionOptsBuilder) (r CreateEncryptionResult) { + b, err := opts.ToEncryptionCreateMap() + if err != nil { + r.Err = err + return + } + resp, err := client.Post(createEncryptionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// Delete will delete an encryption type for an existing Volume Type with the provided ID. +func DeleteEncryption(client *gophercloud.ServiceClient, id, encryptionID string) (r DeleteEncryptionResult) { + resp, err := client.Delete(deleteEncryptionURL(client, id, encryptionID), nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// GetEncryption retrieves the encryption type for an existing VolumeType with the provided ID. +func GetEncryption(client *gophercloud.ServiceClient, id string) (r GetEncryptionResult){ + resp, err := client.Get(getEncryptionURL(client, id), &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// GetEncryptionSpecs retrieves the encryption type specs for an existing VolumeType with the provided ID. +func GetEncryptionSpec(client *gophercloud.ServiceClient, id, key string) (r GetEncryptionSpecResult) { + resp, err := client.Get(getEncryptionSpecURL(client, id, key), &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// UpdateEncryptionOptsBuilder allows extensions to add additional parameters to the +// Update encryption request. +type UpdateEncryptionOptsBuilder interface { + ToUpdateEncryptionMap() (map[string]interface{}, error) +} + +// Update Encryption Opts contains options for creating an Update Encryption Type. This object is passed to +// the volumetypes.UpdateEncryption function. For more information about these parameters, +// see the Update Encryption Type object. +type UpdateEncryptionOpts struct { + // The size of the encryption key. + KeySize int `json:"key_size"` + // The class of that provides the encryption support. + Provider string `json:"provider"` + // Notional service where encryption is performed. + ControlLocation string `json:"control_location"` + // The encryption algorithm or mode. + Cipher string `json:"cipher"` +} + +// ToEncryptionCreateMap assembles a request body based on the contents of a +// UpdateEncryptionOpts. +func (opts UpdateEncryptionOpts) ToUpdateEncryptionMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "encryption") +} + +// Update will update an existing encryption for a Volume Type based on the values in UpdateEncryptionOpts. +// To extract the UpdateEncryption Type object from the response, call the Extract method on the +// UpdateEncryptionResult. +func UpdateEncryption(client *gophercloud.ServiceClient, id,encryptionID string, opts UpdateEncryptionOptsBuilder) (r UpdateEncryptionResult) { + b, err := opts.ToUpdateEncryptionMap() + if err != nil { + r.Err = err + return + } + resp, err := client.Put(updateEncryptionURL(client, id, encryptionID), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} diff --git a/openstack/blockstorage/v3/volumetypes/results.go b/openstack/blockstorage/v3/volumetypes/results.go index 916b476da5..e4ff961ace 100644 --- a/openstack/blockstorage/v3/volumetypes/results.go +++ b/openstack/blockstorage/v3/volumetypes/results.go @@ -200,3 +200,102 @@ type AddAccessResult struct { type RemoveAccessResult struct { gophercloud.ErrResult } + + +type EncryptionType struct { + // Unique identifier for the volume type. + VolumeTypeID string `json:"volume_type_id"` + // Notional service where encryption is performed. + ControlLocation string `json:"control_location"` + // Unique identifier for encryption type. + EncryptionID string `json:"encryption_id"` + // Size of encryption key. + KeySize int `json:"key_size"` + // Class that provides encryption support. + Provider string `json:"provider"` + // The encryption algorithm or mode. + Cipher string `json:"cipher"` +} + +type encryptionResult struct { + gophercloud.Result +} + +func (r encryptionResult) Extract() (*EncryptionType, error) { + var s EncryptionType + err := r.ExtractInto(&s) + return &s, err +} + +// ExtractInto converts our response data into a volume type struct +func (r encryptionResult) ExtractInto(v interface{}) error { + return r.Result.ExtractIntoStructPtr(v, "encryption") +} + +type CreateEncryptionResult struct { + encryptionResult +} + +// UpdateResult contains the response body and error from an UpdateEncryption request. +type UpdateEncryptionResult struct { + encryptionResult +} + +// DeleteEncryptionResult contains the response body and error from a DeleteEncryprion request. +type DeleteEncryptionResult struct { + gophercloud.ErrResult +} + +type GetEncryptionType struct { + // Unique identifier for the volume type. + VolumeTypeID string `json:"volume_type_id"` + // Notional service where encryption is performed. + ControlLocation string `json:"control_location"` + // Shows if the resource is deleted or Notional + Deleted bool `json:"deleted"` + // Shows the date and time the resource was created. + CreatedAt string `json:"created_at"` + // Shows the date and time when resource was updated. + UpdatedAt string `json:"updated_at"` + // Unique identifier for encryption type. + EncryptionID string `json:"encryption_id"` + // Size of encryption key. + KeySize int `json:"key_size"` + // Class that provides encryption support. + Provider string `json:"provider"` + // Shows the date and time the reousrce was deleted. + DeletedAt string `json:"deleted_at"` + // The encryption algorithm or mode. + Cipher string `json:"cipher"` +} + +type encryptionShowResult struct { + gophercloud.Result +} + +// Extract interprets any extraSpecResult as an ExtraSpec, if possible. +func (r encryptionShowResult) Extract() (* GetEncryptionType, error) { + var s GetEncryptionType + err := r.ExtractInto(&s) + return &s, err +} + +type GetEncryptionResult struct { + encryptionShowResult +} + +type encryptionShowSpecResult struct{ + gophercloud.Result +} + +// Extract interprets any empty interface Result as an empty interface. +func (r encryptionShowSpecResult) Extract() (map[string]interface{}, error) { + var s map[string]interface{} + err := r.ExtractInto(&s) + return s, err +} + +type GetEncryptionSpecResult struct{ + encryptionShowSpecResult +} + diff --git a/openstack/blockstorage/v3/volumetypes/testing/fixtures.go b/openstack/blockstorage/v3/volumetypes/testing/fixtures.go index eb617f19e5..bee9cee1e0 100644 --- a/openstack/blockstorage/v3/volumetypes/testing/fixtures.go +++ b/openstack/blockstorage/v3/volumetypes/testing/fixtures.go @@ -258,3 +258,120 @@ func HandleExtraSpecDeleteSuccessfully(t *testing.T) { w.WriteHeader(http.StatusAccepted) }) } + +func MockEncryptionCreateResponse(t *testing.T) { + th.Mux.HandleFunc("/types/a5082c24-2a27-43a4-b48e-fcec1240e36b/encryption", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, ` +{ + "encryption": { + "key_size": 256, + "provider": "luks", + "control_location": "front-end", + "cipher": "aes-xts-plain64" + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "encryption": { + "volume_type_id": "a5082c24-2a27-43a4-b48e-fcec1240e36b", + "control_location": "front-end", + "encryption_id": "81e069c6-7394-4856-8df7-3b237ca61f74", + "key_size": 256, + "provider": "luks", + "cipher": "aes-xts-plain64" + } +} + `) + }) +} + +func MockDeleteEncryptionResponse(t *testing.T) { + th.Mux.HandleFunc("/types/a5082c24-2a27-43a4-b48e-fcec1240e36b/encryption/81e069c6-7394-4856-8df7-3b237ca61f74", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusAccepted) + }) +} + +func MockEncryptionUpdateResponse(t *testing.T) { + th.Mux.HandleFunc("/types/a5082c24-2a27-43a4-b48e-fcec1240e36b/encryption/81e069c6-7394-4856-8df7-3b237ca61f74", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, ` +{ + "encryption": { + "key_size": 256, + "provider": "luks", + "control_location": "front-end", + "cipher": "aes-xts-plain64" + } +} + `) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "encryption": { + "control_location": "front-end", + "key_size": 256, + "provider": "luks", + "cipher": "aes-xts-plain64" + } +} + `) + }) +} + +func MockEncryptionGetResponse(t *testing.T) { + th.Mux.HandleFunc("/types/a5082c24-2a27-43a4-b48e-fcec1240e36b/encryption", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "volume_type_id": "a5082c24-2a27-43a4-b48e-fcec1240e36b", + "control_location": "front-end", + "deleted": false, + "created_at": "2016-12-28T02:32:25.000000", + "updated_at": null, + "encryption_id": "81e069c6-7394-4856-8df7-3b237ca61f74", + "key_size": 256, + "provider": "luks", + "deleted_at": null, + "cipher": "aes-xts-plain64" +} + `) + }) +} + +func MockEncryptionGetSpecResponse(t *testing.T) { + th.Mux.HandleFunc("/types/a5082c24-2a27-43a4-b48e-fcec1240e36b/encryption/cipher", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, ` +{ + "cipher": "aes-xts-plain64" +} + `) + }) +} diff --git a/openstack/blockstorage/v3/volumetypes/testing/requests_test.go b/openstack/blockstorage/v3/volumetypes/testing/requests_test.go index eb6f2e7c0e..f3d6098490 100644 --- a/openstack/blockstorage/v3/volumetypes/testing/requests_test.go +++ b/openstack/blockstorage/v3/volumetypes/testing/requests_test.go @@ -276,3 +276,99 @@ func TestVolumeTypeRemoveAccess(t *testing.T) { th.AssertNoErr(t, err) } + +func TestCreateEncryption(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + MockEncryptionCreateResponse(t) + + options := &volumetypes.CreateEncryptionOpts{ + KeySize: 256, + Provider: "luks", + ControlLocation: "front-end", + Cipher: "aes-xts-plain64", + } + id := "a5082c24-2a27-43a4-b48e-fcec1240e36b" + n, err := volumetypes.CreateEncryption(client.ServiceClient(), id, options).Extract() + th.AssertNoErr(t, err) + + th.AssertEquals(t, "a5082c24-2a27-43a4-b48e-fcec1240e36b", n.VolumeTypeID) + th.AssertEquals(t, "front-end", n.ControlLocation) + th.AssertEquals(t, "81e069c6-7394-4856-8df7-3b237ca61f74", n.EncryptionID) + th.AssertEquals(t, 256, n.KeySize) + th.AssertEquals(t, "luks", n.Provider) + th.AssertEquals(t, "aes-xts-plain64", n.Cipher) +} + +func TestDeleteEncryption(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + MockDeleteEncryptionResponse(t) + + res := volumetypes.DeleteEncryption(client.ServiceClient(), "a5082c24-2a27-43a4-b48e-fcec1240e36b", "81e069c6-7394-4856-8df7-3b237ca61f74" ) + th.AssertNoErr(t, res.Err) +} + +func TestUpdateEncryption(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + MockEncryptionUpdateResponse(t) + + options := &volumetypes.UpdateEncryptionOpts{ + KeySize: 256, + Provider: "luks", + ControlLocation: "front-end", + Cipher: "aes-xts-plain64", + } + id := "a5082c24-2a27-43a4-b48e-fcec1240e36b" + encryptionID := "81e069c6-7394-4856-8df7-3b237ca61f74" + n, err := volumetypes.UpdateEncryption(client.ServiceClient(), id, encryptionID, options).Extract() + th.AssertNoErr(t, err) + + th.AssertEquals(t, "front-end", n.ControlLocation) + th.AssertEquals(t, 256, n.KeySize) + th.AssertEquals(t, "luks", n.Provider) + th.AssertEquals(t, "aes-xts-plain64", n.Cipher) +} + +func TestGetEncryption(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + MockEncryptionGetResponse(t) + id := "a5082c24-2a27-43a4-b48e-fcec1240e36b" + n, err := volumetypes.GetEncryption(client.ServiceClient(), id).Extract() + th.AssertNoErr(t, err) + + th.AssertEquals(t, "a5082c24-2a27-43a4-b48e-fcec1240e36b", n.VolumeTypeID) + th.AssertEquals(t, "front-end", n.ControlLocation) + th.AssertEquals(t, false, n.Deleted) + th.AssertEquals(t, "2016-12-28T02:32:25.000000", n.CreatedAt) + th.AssertEquals(t, "", n.UpdatedAt) + th.AssertEquals(t, "81e069c6-7394-4856-8df7-3b237ca61f74", n.EncryptionID) + th.AssertEquals(t, 256, n.KeySize) + th.AssertEquals(t, "luks", n.Provider) + th.AssertEquals(t, "", n.DeletedAt) + th.AssertEquals(t, "aes-xts-plain64", n.Cipher) +} + +func TestGetEncryptionSpec(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + MockEncryptionGetSpecResponse(t) + id := "a5082c24-2a27-43a4-b48e-fcec1240e36b" + n, err := volumetypes.GetEncryptionSpec(client.ServiceClient(), id, "cipher").Extract() + th.AssertNoErr(t, err) + + key := "cipher" + testVar, exists := n[key] + if exists { + th.AssertEquals(t, "aes-xts-plain64", testVar) + } else { + t.Fatalf("Key %s does not exist in map.", key) + } +} diff --git a/openstack/blockstorage/v3/volumetypes/urls.go b/openstack/blockstorage/v3/volumetypes/urls.go index c63ee47e62..9ba503d314 100644 --- a/openstack/blockstorage/v3/volumetypes/urls.go +++ b/openstack/blockstorage/v3/volumetypes/urls.go @@ -49,3 +49,23 @@ func accessURL(client *gophercloud.ServiceClient, id string) string { func accessActionURL(client *gophercloud.ServiceClient, id string) string { return client.ServiceURL("types", id, "action") } + +func createEncryptionURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("types", id, "encryption") +} + +func deleteEncryptionURL(client *gophercloud.ServiceClient, id, encryptionID string) string { + return client.ServiceURL("types", id, "encryption", encryptionID) +} + +func getEncryptionURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("types", id, "encryption") +} + +func getEncryptionSpecURL(client *gophercloud.ServiceClient, id, key string) string { + return client.ServiceURL("types", id, "encryption", key) +} + +func updateEncryptionURL(client *gophercloud.ServiceClient, id, encryptionID string) string { + return client.ServiceURL("types", id, "encryption", encryptionID) +} From 8353428d01a350ac677cc12d20d25937d0ea754f Mon Sep 17 00:00:00 2001 From: georgeb Date: Mon, 12 Jun 2023 11:32:41 +0200 Subject: [PATCH 008/118] fixup: Correct some acceptance test errors --- .../openstack/blockstorage/v3/volumetypes_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/acceptance/openstack/blockstorage/v3/volumetypes_test.go b/acceptance/openstack/blockstorage/v3/volumetypes_test.go index 73fa32722a..c01218d51f 100644 --- a/acceptance/openstack/blockstorage/v3/volumetypes_test.go +++ b/acceptance/openstack/blockstorage/v3/volumetypes_test.go @@ -174,16 +174,16 @@ func TestEncryptionVolumeTypes(t *testing.T) { th.AssertNoErr(t, err) defer DeleteVolumeType(t, client, vt) - createEncryptionOpts := volumetypes.EncryptionOptions{ + createEncryptionOpts := volumetypes.CreateEncryptionOpts{ KeySize: 256, Provider: "luks", ControlLocation: "front-end", Cipher: "aes-xts-plain64", } - eVT, err := volumetypes.CreateEncryption(client, vt.ID, createEncryptionOpts) + eVT, err := volumetypes.CreateEncryption(client, vt.ID, createEncryptionOpts).Extract() th.AssertNoErr(t, err) - defer DeleteEncryption(t, client, evt) + defer volumetypes.DeleteEncryption(client, eVT.VolumeTypeID, eVT.EncryptionID) geVT, err := volumetypes.GetEncryption(client, vt.ID).Extract() th.AssertNoErr(t, err) @@ -195,13 +195,13 @@ func TestEncryptionVolumeTypes(t *testing.T) { tools.PrintResource(t, gesVT) - updateEncryptionOpts := volumetypes.EncryptionUpdateOpts{ + updateEncryptionOpts := volumetypes.UpdateEncryptionOpts{ ControlLocation: "back-end", } - newEVT, err := volumetypes.Update(client, vt.ID, updateEncryptionOpts).Extract() + newEVT, err := volumetypes.UpdateEncryption(client, vt.ID, eVT.EncryptionID, updateEncryptionOpts).Extract() + tools.PrintResource(t, newEVT) th.AssertNoErr(t, err) - tools.PrintResource(t, newEVT) - th.AssertEquals(t, "back-end", newEVT.ControlLocation) + th.AssertEquals(t, "back-end", newEVT.ControlLocation) } From 71924994cbe408a2600b7a9f045fcd5f521ed5eb Mon Sep 17 00:00:00 2001 From: georgeb Date: Tue, 20 Jun 2023 17:29:13 +0200 Subject: [PATCH 009/118] fixup: Correct some unit test errors --- .../blockstorage/v3/volumetypes_test.go | 31 +++++----- openstack/blockstorage/v3/volumetypes/doc.go | 52 ++++++++-------- .../blockstorage/v3/volumetypes/requests.go | 36 +++++------ .../blockstorage/v3/volumetypes/results.go | 42 ++++++------- .../v3/volumetypes/testing/fixtures.go | 4 +- .../v3/volumetypes/testing/requests_test.go | 62 +++++++++---------- openstack/blockstorage/v3/volumetypes/urls.go | 8 +-- 7 files changed, 115 insertions(+), 120 deletions(-) diff --git a/acceptance/openstack/blockstorage/v3/volumetypes_test.go b/acceptance/openstack/blockstorage/v3/volumetypes_test.go index c01218d51f..6ac7086c3a 100644 --- a/acceptance/openstack/blockstorage/v3/volumetypes_test.go +++ b/acceptance/openstack/blockstorage/v3/volumetypes_test.go @@ -174,34 +174,33 @@ func TestEncryptionVolumeTypes(t *testing.T) { th.AssertNoErr(t, err) defer DeleteVolumeType(t, client, vt) - createEncryptionOpts := volumetypes.CreateEncryptionOpts{ - KeySize: 256, - Provider: "luks", - ControlLocation: "front-end", - Cipher: "aes-xts-plain64", - } + createEncryptionOpts := volumetypes.CreateEncryptionOpts{ + KeySize: 256, + Provider: "luks", + ControlLocation: "front-end", + Cipher: "aes-xts-plain64", + } - eVT, err := volumetypes.CreateEncryption(client, vt.ID, createEncryptionOpts).Extract() - th.AssertNoErr(t, err) - defer volumetypes.DeleteEncryption(client, eVT.VolumeTypeID, eVT.EncryptionID) + eVT, err := volumetypes.CreateEncryption(client, vt.ID, createEncryptionOpts).Extract() + th.AssertNoErr(t, err) + defer volumetypes.DeleteEncryption(client, eVT.VolumeTypeID, eVT.EncryptionID) geVT, err := volumetypes.GetEncryption(client, vt.ID).Extract() th.AssertNoErr(t, err) - tools.PrintResource(t, geVT) + tools.PrintResource(t, geVT) - key := "cipher" + key := "cipher" gesVT, err := volumetypes.GetEncryptionSpec(client, vt.ID, key).Extract() th.AssertNoErr(t, err) - tools.PrintResource(t, gesVT) - + tools.PrintResource(t, gesVT) updateEncryptionOpts := volumetypes.UpdateEncryptionOpts{ - ControlLocation: "back-end", + ControlLocation: "back-end", } newEVT, err := volumetypes.UpdateEncryption(client, vt.ID, eVT.EncryptionID, updateEncryptionOpts).Extract() - tools.PrintResource(t, newEVT) + tools.PrintResource(t, newEVT) th.AssertNoErr(t, err) - th.AssertEquals(t, "back-end", newEVT.ControlLocation) + th.AssertEquals(t, "back-end", newEVT.ControlLocation) } diff --git a/openstack/blockstorage/v3/volumetypes/doc.go b/openstack/blockstorage/v3/volumetypes/doc.go index d532e7262a..03cad7ecbd 100644 --- a/openstack/blockstorage/v3/volumetypes/doc.go +++ b/openstack/blockstorage/v3/volumetypes/doc.go @@ -162,26 +162,27 @@ Example to Remove/Revoke Access to a Volume Type } Example to Create the Encryption of a Volume Type - typeID := "7ffaca22-f646-41d4-b79d-d7e4452ef8cc" - volumeType, err := volumetypes.CreateEncryption(client, typeID, .CreateEncryptionOpts{ - KeySize: 256, - Provider: "luks", - ControlLocation: "front-end", - Cipher: "aes-xts-plain64", - }).Extract() - if err != nil{ - panic(err) - } - fmt.Println(volumeType) + + typeID := "7ffaca22-f646-41d4-b79d-d7e4452ef8cc" + volumeType, err := volumetypes.CreateEncryption(client, typeID, .CreateEncryptionOpts{ + KeySize: 256, + Provider: "luks", + ControlLocation: "front-end", + Cipher: "aes-xts-plain64", + }).Extract() + if err != nil{ + panic(err) + } + fmt.Println(volumeType) Example to Delete the Encryption of a Volume Type - typeID := "7ffaca22-f646-41d4-b79d-d7e4452ef8cc" - encryptionID := ""81e069c6-7394-4856-8df7-3b237ca61f74 - err := volumetypes.DeleteEncryption(client, typeID, encryptionID).ExtractErr() - if err != nil{ - panic(err) - } + typeID := "7ffaca22-f646-41d4-b79d-d7e4452ef8cc" + encryptionID := ""81e069c6-7394-4856-8df7-3b237ca61f74 + err := volumetypes.DeleteEncryption(client, typeID, encryptionID).ExtractErr() + if err != nil{ + panic(err) + } Example to Update the Encryption of a Volume Type @@ -208,15 +209,12 @@ Example to Show an Encryption of a Volume Type Example to Show an Encryption Spec of a Volume Type - typeID := "7ffaca22-f646-41d4-b79d-d7e4452ef8cc" - key := "cipher" - volumeType, err := volumetypes.GetEncrytpionSpec(client, typeID).Extract() - if err != nil{ - panic(err) - } - fmt.Println(volumeType) - - - + typeID := "7ffaca22-f646-41d4-b79d-d7e4452ef8cc" + key := "cipher" + volumeType, err := volumetypes.GetEncrytpionSpec(client, typeID).Extract() + if err != nil{ + panic(err) + } + fmt.Println(volumeType) */ package volumetypes diff --git a/openstack/blockstorage/v3/volumetypes/requests.go b/openstack/blockstorage/v3/volumetypes/requests.go index 4b7e561bc2..e06f7a4638 100644 --- a/openstack/blockstorage/v3/volumetypes/requests.go +++ b/openstack/blockstorage/v3/volumetypes/requests.go @@ -315,14 +315,14 @@ type CreateEncryptionOptsBuilder interface { // This object is passed to the volumetypes.CreateEncryption function. // For more information about these parameters,see the Encryption Type object. type CreateEncryptionOpts struct { - // The size of the encryption key. - KeySize int `json:"key_size"` - // The class of that provides the encryption support. - Provider string `json:"provider" required:"true"` - // Notional service where encryption is performed. - ControlLocation string `json:"control_location"` - // The encryption algorithm or mode. - Cipher string `json:"cipher"` + // The size of the encryption key. + KeySize int `json:"key_size"` + // The class of that provides the encryption support. + Provider string `json:"provider" required:"true"` + // Notional service where encryption is performed. + ControlLocation string `json:"control_location"` + // The encryption algorithm or mode. + Cipher string `json:"cipher"` } // ToEncryptionCreateMap assembles a request body based on the contents of a @@ -355,7 +355,7 @@ func DeleteEncryption(client *gophercloud.ServiceClient, id, encryptionID string } // GetEncryption retrieves the encryption type for an existing VolumeType with the provided ID. -func GetEncryption(client *gophercloud.ServiceClient, id string) (r GetEncryptionResult){ +func GetEncryption(client *gophercloud.ServiceClient, id string) (r GetEncryptionResult) { resp, err := client.Get(getEncryptionURL(client, id), &r.Body, nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return @@ -378,14 +378,14 @@ type UpdateEncryptionOptsBuilder interface { // the volumetypes.UpdateEncryption function. For more information about these parameters, // see the Update Encryption Type object. type UpdateEncryptionOpts struct { - // The size of the encryption key. - KeySize int `json:"key_size"` - // The class of that provides the encryption support. - Provider string `json:"provider"` - // Notional service where encryption is performed. - ControlLocation string `json:"control_location"` - // The encryption algorithm or mode. - Cipher string `json:"cipher"` + // The size of the encryption key. + KeySize int `json:"key_size"` + // The class of that provides the encryption support. + Provider string `json:"provider"` + // Notional service where encryption is performed. + ControlLocation string `json:"control_location"` + // The encryption algorithm or mode. + Cipher string `json:"cipher"` } // ToEncryptionCreateMap assembles a request body based on the contents of a @@ -397,7 +397,7 @@ func (opts UpdateEncryptionOpts) ToUpdateEncryptionMap() (map[string]interface{} // Update will update an existing encryption for a Volume Type based on the values in UpdateEncryptionOpts. // To extract the UpdateEncryption Type object from the response, call the Extract method on the // UpdateEncryptionResult. -func UpdateEncryption(client *gophercloud.ServiceClient, id,encryptionID string, opts UpdateEncryptionOptsBuilder) (r UpdateEncryptionResult) { +func UpdateEncryption(client *gophercloud.ServiceClient, id, encryptionID string, opts UpdateEncryptionOptsBuilder) (r UpdateEncryptionResult) { b, err := opts.ToUpdateEncryptionMap() if err != nil { r.Err = err diff --git a/openstack/blockstorage/v3/volumetypes/results.go b/openstack/blockstorage/v3/volumetypes/results.go index e4ff961ace..4d1d1cf2df 100644 --- a/openstack/blockstorage/v3/volumetypes/results.go +++ b/openstack/blockstorage/v3/volumetypes/results.go @@ -201,14 +201,13 @@ type RemoveAccessResult struct { gophercloud.ErrResult } - type EncryptionType struct { // Unique identifier for the volume type. - VolumeTypeID string `json:"volume_type_id"` + VolumeTypeID string `json:"volume_type_id"` // Notional service where encryption is performed. ControlLocation string `json:"control_location"` // Unique identifier for encryption type. - EncryptionID string `json:"encryption_id"` + EncryptionID string `json:"encryption_id"` // Size of encryption key. KeySize int `json:"key_size"` // Class that provides encryption support. @@ -247,25 +246,25 @@ type DeleteEncryptionResult struct { } type GetEncryptionType struct { - // Unique identifier for the volume type. - VolumeTypeID string `json:"volume_type_id"` + // Unique identifier for the volume type. + VolumeTypeID string `json:"volume_type_id"` // Notional service where encryption is performed. ControlLocation string `json:"control_location"` - // Shows if the resource is deleted or Notional - Deleted bool `json:"deleted"` - // Shows the date and time the resource was created. - CreatedAt string `json:"created_at"` - // Shows the date and time when resource was updated. - UpdatedAt string `json:"updated_at"` - // Unique identifier for encryption type. - EncryptionID string `json:"encryption_id"` + // Shows if the resource is deleted or Notional + Deleted bool `json:"deleted"` + // Shows the date and time the resource was created. + CreatedAt string `json:"created_at"` + // Shows the date and time when resource was updated. + UpdatedAt string `json:"updated_at"` + // Unique identifier for encryption type. + EncryptionID string `json:"encryption_id"` // Size of encryption key. KeySize int `json:"key_size"` // Class that provides encryption support. Provider string `json:"provider"` - // Shows the date and time the reousrce was deleted. - DeletedAt string `json:"deleted_at"` - // The encryption algorithm or mode. + // Shows the date and time the reousrce was deleted. + DeletedAt string `json:"deleted_at"` + // The encryption algorithm or mode. Cipher string `json:"cipher"` } @@ -274,7 +273,7 @@ type encryptionShowResult struct { } // Extract interprets any extraSpecResult as an ExtraSpec, if possible. -func (r encryptionShowResult) Extract() (* GetEncryptionType, error) { +func (r encryptionShowResult) Extract() (*GetEncryptionType, error) { var s GetEncryptionType err := r.ExtractInto(&s) return &s, err @@ -284,8 +283,8 @@ type GetEncryptionResult struct { encryptionShowResult } -type encryptionShowSpecResult struct{ - gophercloud.Result +type encryptionShowSpecResult struct { + gophercloud.Result } // Extract interprets any empty interface Result as an empty interface. @@ -295,7 +294,6 @@ func (r encryptionShowSpecResult) Extract() (map[string]interface{}, error) { return s, err } -type GetEncryptionSpecResult struct{ - encryptionShowSpecResult +type GetEncryptionSpecResult struct { + encryptionShowSpecResult } - diff --git a/openstack/blockstorage/v3/volumetypes/testing/fixtures.go b/openstack/blockstorage/v3/volumetypes/testing/fixtures.go index bee9cee1e0..a8cb0345cc 100644 --- a/openstack/blockstorage/v3/volumetypes/testing/fixtures.go +++ b/openstack/blockstorage/v3/volumetypes/testing/fixtures.go @@ -340,7 +340,7 @@ func MockEncryptionGetResponse(t *testing.T) { th.TestMethod(t, r, "GET") th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) - w.Header().Add("Content-Type", "application/json") + w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) fmt.Fprintf(w, ` @@ -365,7 +365,7 @@ func MockEncryptionGetSpecResponse(t *testing.T) { th.TestMethod(t, r, "GET") th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) - w.Header().Add("Content-Type", "application/json") + w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) fmt.Fprintf(w, ` diff --git a/openstack/blockstorage/v3/volumetypes/testing/requests_test.go b/openstack/blockstorage/v3/volumetypes/testing/requests_test.go index f3d6098490..033158df55 100644 --- a/openstack/blockstorage/v3/volumetypes/testing/requests_test.go +++ b/openstack/blockstorage/v3/volumetypes/testing/requests_test.go @@ -284,13 +284,13 @@ func TestCreateEncryption(t *testing.T) { MockEncryptionCreateResponse(t) options := &volumetypes.CreateEncryptionOpts{ - KeySize: 256, - Provider: "luks", + KeySize: 256, + Provider: "luks", ControlLocation: "front-end", - Cipher: "aes-xts-plain64", + Cipher: "aes-xts-plain64", } - id := "a5082c24-2a27-43a4-b48e-fcec1240e36b" - n, err := volumetypes.CreateEncryption(client.ServiceClient(), id, options).Extract() + id := "a5082c24-2a27-43a4-b48e-fcec1240e36b" + n, err := volumetypes.CreateEncryption(client.ServiceClient(), id, options).Extract() th.AssertNoErr(t, err) th.AssertEquals(t, "a5082c24-2a27-43a4-b48e-fcec1240e36b", n.VolumeTypeID) @@ -298,7 +298,7 @@ func TestCreateEncryption(t *testing.T) { th.AssertEquals(t, "81e069c6-7394-4856-8df7-3b237ca61f74", n.EncryptionID) th.AssertEquals(t, 256, n.KeySize) th.AssertEquals(t, "luks", n.Provider) - th.AssertEquals(t, "aes-xts-plain64", n.Cipher) + th.AssertEquals(t, "aes-xts-plain64", n.Cipher) } func TestDeleteEncryption(t *testing.T) { @@ -307,7 +307,7 @@ func TestDeleteEncryption(t *testing.T) { MockDeleteEncryptionResponse(t) - res := volumetypes.DeleteEncryption(client.ServiceClient(), "a5082c24-2a27-43a4-b48e-fcec1240e36b", "81e069c6-7394-4856-8df7-3b237ca61f74" ) + res := volumetypes.DeleteEncryption(client.ServiceClient(), "a5082c24-2a27-43a4-b48e-fcec1240e36b", "81e069c6-7394-4856-8df7-3b237ca61f74") th.AssertNoErr(t, res.Err) } @@ -318,20 +318,20 @@ func TestUpdateEncryption(t *testing.T) { MockEncryptionUpdateResponse(t) options := &volumetypes.UpdateEncryptionOpts{ - KeySize: 256, - Provider: "luks", + KeySize: 256, + Provider: "luks", ControlLocation: "front-end", - Cipher: "aes-xts-plain64", + Cipher: "aes-xts-plain64", } - id := "a5082c24-2a27-43a4-b48e-fcec1240e36b" - encryptionID := "81e069c6-7394-4856-8df7-3b237ca61f74" - n, err := volumetypes.UpdateEncryption(client.ServiceClient(), id, encryptionID, options).Extract() + id := "a5082c24-2a27-43a4-b48e-fcec1240e36b" + encryptionID := "81e069c6-7394-4856-8df7-3b237ca61f74" + n, err := volumetypes.UpdateEncryption(client.ServiceClient(), id, encryptionID, options).Extract() th.AssertNoErr(t, err) th.AssertEquals(t, "front-end", n.ControlLocation) th.AssertEquals(t, 256, n.KeySize) th.AssertEquals(t, "luks", n.Provider) - th.AssertEquals(t, "aes-xts-plain64", n.Cipher) + th.AssertEquals(t, "aes-xts-plain64", n.Cipher) } func TestGetEncryption(t *testing.T) { @@ -339,20 +339,20 @@ func TestGetEncryption(t *testing.T) { defer th.TeardownHTTP() MockEncryptionGetResponse(t) - id := "a5082c24-2a27-43a4-b48e-fcec1240e36b" - n, err := volumetypes.GetEncryption(client.ServiceClient(), id).Extract() + id := "a5082c24-2a27-43a4-b48e-fcec1240e36b" + n, err := volumetypes.GetEncryption(client.ServiceClient(), id).Extract() th.AssertNoErr(t, err) - th.AssertEquals(t, "a5082c24-2a27-43a4-b48e-fcec1240e36b", n.VolumeTypeID) + th.AssertEquals(t, "a5082c24-2a27-43a4-b48e-fcec1240e36b", n.VolumeTypeID) th.AssertEquals(t, "front-end", n.ControlLocation) th.AssertEquals(t, false, n.Deleted) - th.AssertEquals(t, "2016-12-28T02:32:25.000000", n.CreatedAt) - th.AssertEquals(t, "", n.UpdatedAt) - th.AssertEquals(t, "81e069c6-7394-4856-8df7-3b237ca61f74", n.EncryptionID) + th.AssertEquals(t, "2016-12-28T02:32:25.000000", n.CreatedAt) + th.AssertEquals(t, "", n.UpdatedAt) + th.AssertEquals(t, "81e069c6-7394-4856-8df7-3b237ca61f74", n.EncryptionID) th.AssertEquals(t, 256, n.KeySize) th.AssertEquals(t, "luks", n.Provider) - th.AssertEquals(t, "", n.DeletedAt) - th.AssertEquals(t, "aes-xts-plain64", n.Cipher) + th.AssertEquals(t, "", n.DeletedAt) + th.AssertEquals(t, "aes-xts-plain64", n.Cipher) } func TestGetEncryptionSpec(t *testing.T) { @@ -360,15 +360,15 @@ func TestGetEncryptionSpec(t *testing.T) { defer th.TeardownHTTP() MockEncryptionGetSpecResponse(t) - id := "a5082c24-2a27-43a4-b48e-fcec1240e36b" - n, err := volumetypes.GetEncryptionSpec(client.ServiceClient(), id, "cipher").Extract() + id := "a5082c24-2a27-43a4-b48e-fcec1240e36b" + n, err := volumetypes.GetEncryptionSpec(client.ServiceClient(), id, "cipher").Extract() th.AssertNoErr(t, err) - key := "cipher" - testVar, exists := n[key] - if exists { - th.AssertEquals(t, "aes-xts-plain64", testVar) - } else { - t.Fatalf("Key %s does not exist in map.", key) - } + key := "cipher" + testVar, exists := n[key] + if exists { + th.AssertEquals(t, "aes-xts-plain64", testVar) + } else { + t.Fatalf("Key %s does not exist in map.", key) + } } diff --git a/openstack/blockstorage/v3/volumetypes/urls.go b/openstack/blockstorage/v3/volumetypes/urls.go index 9ba503d314..c65478e684 100644 --- a/openstack/blockstorage/v3/volumetypes/urls.go +++ b/openstack/blockstorage/v3/volumetypes/urls.go @@ -55,17 +55,17 @@ func createEncryptionURL(client *gophercloud.ServiceClient, id string) string { } func deleteEncryptionURL(client *gophercloud.ServiceClient, id, encryptionID string) string { - return client.ServiceURL("types", id, "encryption", encryptionID) + return client.ServiceURL("types", id, "encryption", encryptionID) } func getEncryptionURL(client *gophercloud.ServiceClient, id string) string { - return client.ServiceURL("types", id, "encryption") + return client.ServiceURL("types", id, "encryption") } func getEncryptionSpecURL(client *gophercloud.ServiceClient, id, key string) string { - return client.ServiceURL("types", id, "encryption", key) + return client.ServiceURL("types", id, "encryption", key) } func updateEncryptionURL(client *gophercloud.ServiceClient, id, encryptionID string) string { - return client.ServiceURL("types", id, "encryption", encryptionID) + return client.ServiceURL("types", id, "encryption", encryptionID) } From 90064d7c1679a896482d86f5dead95149a97e55b Mon Sep 17 00:00:00 2001 From: nikParasyr Date: Thu, 29 Jun 2023 23:12:45 +0200 Subject: [PATCH 010/118] Add projectID to fwaas_v2 policy CreateOpts and ListOpts --- .../v2/extensions/fwaas_v2/policies/requests.go | 2 ++ .../v2/extensions/fwaas_v2/policies/results.go | 1 + .../fwaas_v2/policies/testing/requests_test.go | 12 +++++++++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/openstack/networking/v2/extensions/fwaas_v2/policies/requests.go b/openstack/networking/v2/extensions/fwaas_v2/policies/requests.go index d5a701aa13..8f036ca93c 100644 --- a/openstack/networking/v2/extensions/fwaas_v2/policies/requests.go +++ b/openstack/networking/v2/extensions/fwaas_v2/policies/requests.go @@ -18,6 +18,7 @@ type ListOptsBuilder interface { // and is either `asc' or `desc'. Marker and Limit are used for pagination. type ListOpts struct { TenantID string `q:"tenant_id"` + ProjectID string `q:"project_id"` Name string `q:"name"` Description string `q:"description"` Shared *bool `q:"shared"` @@ -68,6 +69,7 @@ type CreateOpts struct { // Only required if the caller has an admin role and wants to create a firewall policy // for another tenant. TenantID string `json:"tenant_id,omitempty"` + ProjectID string `json:"project_id,omitempty"` Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` Shared *bool `json:"shared,omitempty"` diff --git a/openstack/networking/v2/extensions/fwaas_v2/policies/results.go b/openstack/networking/v2/extensions/fwaas_v2/policies/results.go index c0139aea3f..8d7411c3de 100644 --- a/openstack/networking/v2/extensions/fwaas_v2/policies/results.go +++ b/openstack/networking/v2/extensions/fwaas_v2/policies/results.go @@ -11,6 +11,7 @@ type Policy struct { Name string `json:"name"` Description string `json:"description"` TenantID string `json:"tenant_id"` + ProjectID string `json:"project_id"` Audited bool `json:"audited"` Shared bool `json:"shared"` Rules []string `json:"firewall_rules,omitempty"` diff --git a/openstack/networking/v2/extensions/fwaas_v2/policies/testing/requests_test.go b/openstack/networking/v2/extensions/fwaas_v2/policies/testing/requests_test.go index ca0e09263c..e0251c770a 100644 --- a/openstack/networking/v2/extensions/fwaas_v2/policies/testing/requests_test.go +++ b/openstack/networking/v2/extensions/fwaas_v2/policies/testing/requests_test.go @@ -33,6 +33,7 @@ func TestList(t *testing.T) { "c9e77ca0-1bc8-497d-904d-948107873dc6" ], "tenant_id": "9145d91459d248b1b02fdaca97c6a75d", + "project_id": "9145d91459d248b1b02fdaca97c6a75d", "audited": true, "shared": false, "id": "f2b08c1e-aa81-4668-8ae1-1401bcb0576c", @@ -44,6 +45,7 @@ func TestList(t *testing.T) { "03d2a6ad-633f-431a-8463-4370d06a22c8" ], "tenant_id": "9145d91459d248b1b02fdaca97c6a75d", + "project_id": "9145d91459d248b1b02fdaca97c6a75d", "audited": false, "shared": true, "id": "c854fab5-bdaf-4a86-9359-78de93e5df01", @@ -72,6 +74,7 @@ func TestList(t *testing.T) { "c9e77ca0-1bc8-497d-904d-948107873dc6", }, TenantID: "9145d91459d248b1b02fdaca97c6a75d", + ProjectID: "9145d91459d248b1b02fdaca97c6a75d", Audited: true, Shared: false, ID: "f2b08c1e-aa81-4668-8ae1-1401bcb0576c", @@ -83,6 +86,7 @@ func TestList(t *testing.T) { "03d2a6ad-633f-431a-8463-4370d06a22c8", }, TenantID: "9145d91459d248b1b02fdaca97c6a75d", + ProjectID: "9145d91459d248b1b02fdaca97c6a75d", Audited: false, Shared: true, ID: "c854fab5-bdaf-4a86-9359-78de93e5df01", @@ -119,6 +123,7 @@ func TestCreate(t *testing.T) { ], "description": "Firewall policy", "tenant_id": "9145d91459d248b1b02fdaca97c6a75d", + "project_id": "9145d91459d248b1b02fdaca97c6a75d", "audited": true, "shared": false } @@ -137,6 +142,7 @@ func TestCreate(t *testing.T) { "11a58c87-76be-ae7c-a74e-b77fffb88a32" ], "tenant_id": "9145d91459d248b1b02fdaca97c6a75d", + "project_id": "9145d91459d248b1b02fdaca97c6a75d", "audited": false, "id": "f2b08c1e-aa81-4668-8ae1-1401bcb0576c", "description": "Firewall policy" @@ -147,6 +153,7 @@ func TestCreate(t *testing.T) { options := policies.CreateOpts{ TenantID: "9145d91459d248b1b02fdaca97c6a75d", + ProjectID: "9145d91459d248b1b02fdaca97c6a75d", Name: "policy", Description: "Firewall policy", Shared: gophercloud.Disabled, @@ -211,7 +218,7 @@ func TestInsertRule(t *testing.T) { th.AssertEquals(t, "e3c78ab6-e827-4297-8d68-739063865a8b", policy.ID) th.AssertEquals(t, "TESTACC-DESC-8P12aLfW", policy.Description) th.AssertEquals(t, "9f98fc0e5f944cd1b51798b668dc8778", policy.TenantID) - + th.AssertEquals(t, "9f98fc0e5f944cd1b51798b668dc8778", policy.ProjectID) } func TestInsertRuleWithInvalidParameters(t *testing.T) { @@ -253,6 +260,7 @@ func TestGet(t *testing.T) { "03d2a6ad-633f-431a-8463-4370d06a22c8" ], "tenant_id": "9145d91459d248b1b02fdaca97c6a75d", + "project_id": "9145d91459d248b1b02fdaca97c6a75d", "audited": false, "id": "f2b08c1e-aa81-4668-8ae1-1401bcb0576c", "description": "Firewall policy web" @@ -272,6 +280,7 @@ func TestGet(t *testing.T) { th.AssertEquals(t, "c9e77ca0-1bc8-497d-904d-948107873dc6", policy.Rules[1]) th.AssertEquals(t, "03d2a6ad-633f-431a-8463-4370d06a22c8", policy.Rules[2]) th.AssertEquals(t, "9145d91459d248b1b02fdaca97c6a75d", policy.TenantID) + th.AssertEquals(t, "9145d91459d248b1b02fdaca97c6a75d", policy.ProjectID) } func TestUpdate(t *testing.T) { @@ -309,6 +318,7 @@ func TestUpdate(t *testing.T) { "03d2a6ad-633f-431a-8463-4370d06a22c8" ], "tenant_id": "9145d91459d248b1b02fdaca97c6a75d", + "project_id": "9145d91459d248b1b02fdaca97c6a75d", "audited": false, "id": "f2b08c1e-aa81-4668-8ae1-1401bcb0576c", "description": "Firewall policy" From f81b74488e8a3bec3371934392b19abe0670cb74 Mon Sep 17 00:00:00 2001 From: nikParasyr Date: Thu, 29 Jun 2023 22:42:30 +0200 Subject: [PATCH 011/118] Add projectID to fwaas_v2 CreateOpts --- .../v2/extensions/fwaas_v2/rules/requests.go | 1 + .../fwaas_v2/rules/testing/requests_test.go | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/openstack/networking/v2/extensions/fwaas_v2/rules/requests.go b/openstack/networking/v2/extensions/fwaas_v2/rules/requests.go index 7ffd681d96..d80e682796 100644 --- a/openstack/networking/v2/extensions/fwaas_v2/rules/requests.go +++ b/openstack/networking/v2/extensions/fwaas_v2/rules/requests.go @@ -117,6 +117,7 @@ type CreateOpts struct { Protocol Protocol `json:"protocol" required:"true"` Action Action `json:"action" required:"true"` TenantID string `json:"tenant_id,omitempty"` + ProjectID string `json:"project_id,omitempty"` Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` IPVersion gophercloud.IPVersion `json:"ip_version,omitempty"` diff --git a/openstack/networking/v2/extensions/fwaas_v2/rules/testing/requests_test.go b/openstack/networking/v2/extensions/fwaas_v2/rules/testing/requests_test.go index 7330833654..8ca0d70e28 100644 --- a/openstack/networking/v2/extensions/fwaas_v2/rules/testing/requests_test.go +++ b/openstack/networking/v2/extensions/fwaas_v2/rules/testing/requests_test.go @@ -37,6 +37,7 @@ func TestList(t *testing.T) { "id": "f03bd950-6c56-4f5e-a307-45967078f507", "name": "ssh_form_any", "tenant_id": "80cf934d6ffb4ef5b244f1c512ad1e61", + "project_id": "80cf934d6ffb4ef5b244f1c512ad1e61", "enabled": true, "action": "allow", "ip_version": 4, @@ -53,6 +54,7 @@ func TestList(t *testing.T) { "id": "ab7bd950-6c56-4f5e-a307-45967078f890", "name": "deny_all_udp", "tenant_id": "80cf934d6ffb4ef5b244f1c512ad1e61", + "project_id": "80cf934d6ffb4ef5b244f1c512ad1e61", "enabled": true, "action": "deny", "ip_version": 4, @@ -85,6 +87,7 @@ func TestList(t *testing.T) { ID: "f03bd950-6c56-4f5e-a307-45967078f507", Name: "ssh_form_any", TenantID: "80cf934d6ffb4ef5b244f1c512ad1e61", + ProjectID: "80cf934d6ffb4ef5b244f1c512ad1e61", Enabled: true, Action: string(rules.ActionAllow), IPVersion: 4, @@ -101,6 +104,7 @@ func TestList(t *testing.T) { ID: "ab7bd950-6c56-4f5e-a307-45967078f890", Name: "deny_all_udp", TenantID: "80cf934d6ffb4ef5b244f1c512ad1e61", + ProjectID: "80cf934d6ffb4ef5b244f1c512ad1e61", Enabled: true, Action: "deny", IPVersion: 4, @@ -135,7 +139,8 @@ func TestCreate(t *testing.T) { "destination_port": "22", "name": "ssh_form_any", "action": "allow", - "tenant_id": "80cf934d6ffb4ef5b244f1c512ad1e61" + "tenant_id": "80cf934d6ffb4ef5b244f1c512ad1e61", + "project_id": "80cf934d6ffb4ef5b244f1c512ad1e61" } } `) @@ -157,6 +162,7 @@ func TestCreate(t *testing.T) { "id": "f03bd950-6c56-4f5e-a307-45967078f507", "name": "ssh_form_any", "tenant_id": "80cf934d6ffb4ef5b244f1c512ad1e61", + "project_id": "80cf934d6ffb4ef5b244f1c512ad1e61", "enabled": true, "action": "allow", "ip_version": 4, @@ -168,6 +174,7 @@ func TestCreate(t *testing.T) { options := rules.CreateOpts{ TenantID: "80cf934d6ffb4ef5b244f1c512ad1e61", + ProjectID: "80cf934d6ffb4ef5b244f1c512ad1e61", Protocol: rules.ProtocolTCP, Description: "ssh rule", DestinationIPAddress: "192.168.1.0/24", @@ -197,7 +204,8 @@ func TestCreateAnyProtocol(t *testing.T) { "destination_ip_address": "192.168.1.0/24", "name": "any_to_192.168.1.0/24", "action": "allow", - "tenant_id": "80cf934d6ffb4ef5b244f1c512ad1e61" + "tenant_id": "80cf934d6ffb4ef5b244f1c512ad1e61", + "project_id": "80cf934d6ffb4ef5b244f1c512ad1e61" } } `) @@ -219,6 +227,7 @@ func TestCreateAnyProtocol(t *testing.T) { "id": "f03bd950-6c56-4f5e-a307-45967078f507", "name": "any_to_192.168.1.0/24", "tenant_id": "80cf934d6ffb4ef5b244f1c512ad1e61", + "project_id": "80cf934d6ffb4ef5b244f1c512ad1e61", "enabled": true, "action": "allow", "ip_version": 4, @@ -230,6 +239,7 @@ func TestCreateAnyProtocol(t *testing.T) { options := rules.CreateOpts{ TenantID: "80cf934d6ffb4ef5b244f1c512ad1e61", + ProjectID: "80cf934d6ffb4ef5b244f1c512ad1e61", Protocol: rules.ProtocolAny, Description: "any to 192.168.1.0/24", DestinationIPAddress: "192.168.1.0/24", @@ -266,6 +276,7 @@ func TestGet(t *testing.T) { "id": "f03bd950-6c56-4f5e-a307-45967078f507", "name": "ssh_form_any", "tenant_id": "80cf934d6ffb4ef5b244f1c512ad1e61", + "project_id": "80cf934d6ffb4ef5b244f1c512ad1e61", "enabled": true, "action": "allow", "ip_version": 4, @@ -287,6 +298,7 @@ func TestGet(t *testing.T) { th.AssertEquals(t, "f03bd950-6c56-4f5e-a307-45967078f507", rule.ID) th.AssertEquals(t, "ssh_form_any", rule.Name) th.AssertEquals(t, "80cf934d6ffb4ef5b244f1c512ad1e61", rule.TenantID) + th.AssertEquals(t, "80cf934d6ffb4ef5b244f1c512ad1e61", rule.ProjectID) th.AssertEquals(t, true, rule.Enabled) th.AssertEquals(t, "allow", rule.Action) th.AssertEquals(t, 4, rule.IPVersion) @@ -331,6 +343,7 @@ func TestUpdate(t *testing.T) { "id": "f03bd950-6c56-4f5e-a307-45967078f507", "name": "ssh_form_any", "tenant_id": "80cf934d6ffb4ef5b244f1c512ad1e61", + "project_id": "80cf934d6ffb4ef5b244f1c512ad1e61", "enabled": false, "action": "allow", "ip_version": 4, From bf9a309975f7fe2846f12d29fd844a7c20d37fff Mon Sep 17 00:00:00 2001 From: kayrus Date: Wed, 12 Jul 2023 20:40:46 +0200 Subject: [PATCH 012/118] [manila]: add reset and force delete actions to a snapshot --- .../sharedfilesystems/v2/replicas_test.go | 15 ++-- .../sharedfilesystems/v2/snapshots.go | 3 + .../sharedfilesystems/v2/snapshots_test.go | 75 +++++++++++++++++++ .../v2/snapshots/requests.go | 51 +++++++++++++ .../sharedfilesystems/v2/snapshots/results.go | 10 +++ .../v2/snapshots/testing/fixtures.go | 36 +++++++++ .../v2/snapshots/testing/request_test.go | 24 ++++++ .../sharedfilesystems/v2/snapshots/urls.go | 8 ++ 8 files changed, 215 insertions(+), 7 deletions(-) diff --git a/acceptance/openstack/sharedfilesystems/v2/replicas_test.go b/acceptance/openstack/sharedfilesystems/v2/replicas_test.go index d3179b199f..6fa28cada6 100644 --- a/acceptance/openstack/sharedfilesystems/v2/replicas_test.go +++ b/acceptance/openstack/sharedfilesystems/v2/replicas_test.go @@ -13,8 +13,9 @@ import ( th "github.com/gophercloud/gophercloud/testhelper" ) +// 2.56 is required for a /v2/replicas/XXX URL support // otherwise we need to set "X-OpenStack-Manila-API-Experimental: true" -const replicasMicroversion = "2.60" +const replicasPathMicroversion = "2.56" func TestReplicaCreate(t *testing.T) { clients.RequireManilaReplicas(t) @@ -23,7 +24,7 @@ func TestReplicaCreate(t *testing.T) { if err != nil { t.Fatalf("Unable to create a shared file system client: %v", err) } - client.Microversion = replicasMicroversion + client.Microversion = replicasPathMicroversion share, err := CreateShare(t, client) if err != nil { @@ -60,7 +61,7 @@ func TestReplicaPromote(t *testing.T) { if err != nil { t.Fatalf("Unable to create a shared file system client: %v", err) } - client.Microversion = replicasMicroversion + client.Microversion = replicasPathMicroversion share, err := CreateShare(t, client) if err != nil { @@ -136,7 +137,7 @@ func TestReplicaExportLocations(t *testing.T) { if err != nil { t.Fatalf("Unable to create a shared file system client: %v", err) } - client.Microversion = replicasMicroversion + client.Microversion = replicasPathMicroversion share, err := CreateShare(t, client) if err != nil { @@ -203,7 +204,7 @@ func TestReplicaListDetail(t *testing.T) { if err != nil { t.Fatalf("Unable to create a shared file system client: %v", err) } - client.Microversion = replicasMicroversion + client.Microversion = replicasPathMicroversion share, err := CreateShare(t, client) if err != nil { @@ -236,7 +237,7 @@ func TestReplicaResetStatus(t *testing.T) { if err != nil { t.Fatalf("Unable to create a shared file system client: %v", err) } - client.Microversion = replicasMicroversion + client.Microversion = replicasPathMicroversion share, err := CreateShare(t, client) if err != nil { @@ -278,7 +279,7 @@ func TestReplicaForceDelete(t *testing.T) { if err != nil { t.Fatalf("Unable to create a shared file system client: %v", err) } - client.Microversion = replicasMicroversion + client.Microversion = replicasPathMicroversion share, err := CreateShare(t, client) if err != nil { diff --git a/acceptance/openstack/sharedfilesystems/v2/snapshots.go b/acceptance/openstack/sharedfilesystems/v2/snapshots.go index 62e607d229..e96d02b9b9 100644 --- a/acceptance/openstack/sharedfilesystems/v2/snapshots.go +++ b/acceptance/openstack/sharedfilesystems/v2/snapshots.go @@ -54,6 +54,9 @@ func ListSnapshots(t *testing.T, client *gophercloud.ServiceClient) ([]snapshots func DeleteSnapshot(t *testing.T, client *gophercloud.ServiceClient, snapshot *snapshots.Snapshot) { err := snapshots.Delete(client, snapshot.ID).ExtractErr() if err != nil { + if _, ok := err.(gophercloud.ErrDefault404); ok { + return + } t.Errorf("Unable to delete snapshot %s: %v", snapshot.ID, err) } diff --git a/acceptance/openstack/sharedfilesystems/v2/snapshots_test.go b/acceptance/openstack/sharedfilesystems/v2/snapshots_test.go index a30bad98bb..de83e41cd1 100644 --- a/acceptance/openstack/sharedfilesystems/v2/snapshots_test.go +++ b/acceptance/openstack/sharedfilesystems/v2/snapshots_test.go @@ -12,6 +12,10 @@ import ( th "github.com/gophercloud/gophercloud/testhelper" ) +// 2.7 is required for a /v2/snapshots/XXX/action URL support +// otherwise we need to set "X-OpenStack-Manila-API-Experimental: true" +const snapshotsPathMicroversion = "2.7" + func TestSnapshotCreate(t *testing.T) { client, err := clients.NewSharedFileSystemV2Client() if err != nil { @@ -119,3 +123,74 @@ func TestSnapshotListDetail(t *testing.T) { tools.PrintResource(t, &ss[i]) } } + +func TestSnapshotResetStatus(t *testing.T) { + client, err := clients.NewSharedFileSystemV2Client() + if err != nil { + t.Fatalf("Unable to create a shared file system client: %v", err) + } + client.Microversion = snapshotsPathMicroversion + + share, err := CreateShare(t, client) + if err != nil { + t.Fatalf("Unable to create a share: %v", err) + } + + defer DeleteShare(t, client, share) + + snapshot, err := CreateSnapshot(t, client, share.ID) + if err != nil { + t.Fatalf("Unable to create a snapshot: %v", err) + } + + defer DeleteSnapshot(t, client, snapshot) + + resetStatusOpts := &snapshots.ResetStatusOpts{ + Status: "error", + } + err = snapshots.ResetStatus(client, snapshot.ID, resetStatusOpts).ExtractErr() + if err != nil { + t.Fatalf("Unable to reset a snapshot status: %v", err) + } + + err = waitForSnapshotStatus(t, client, snapshot.ID, "error") + if err != nil { + t.Fatalf("Snapshot status error: %v", err) + } + + t.Logf("Snapshot %s status successfuly reset", snapshot.ID) +} + +func TestSnapshotForceDelete(t *testing.T) { + client, err := clients.NewSharedFileSystemV2Client() + if err != nil { + t.Fatalf("Unable to create a shared file system client: %v", err) + } + client.Microversion = snapshotsPathMicroversion + + share, err := CreateShare(t, client) + if err != nil { + t.Fatalf("Unable to create a share: %v", err) + } + + defer DeleteShare(t, client, share) + + snapshot, err := CreateSnapshot(t, client, share.ID) + if err != nil { + t.Fatalf("Unable to create a snapshot: %v", err) + } + + defer DeleteSnapshot(t, client, snapshot) + + err = snapshots.ForceDelete(client, snapshot.ID).ExtractErr() + if err != nil { + t.Fatalf("Unable to force delete a snapshot: %v", err) + } + + err = waitForSnapshotStatus(t, client, snapshot.ID, "deleted") + if err != nil { + t.Fatalf("Snapshot status error: %v", err) + } + + t.Logf("Snapshot %s was successfuly deleted", snapshot.ID) +} diff --git a/openstack/sharedfilesystems/v2/snapshots/requests.go b/openstack/sharedfilesystems/v2/snapshots/requests.go index 1ed6e8aef2..bbdde5eac1 100644 --- a/openstack/sharedfilesystems/v2/snapshots/requests.go +++ b/openstack/sharedfilesystems/v2/snapshots/requests.go @@ -163,3 +163,54 @@ func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } + +// ResetStatusOptsBuilder allows extensions to add additional parameters to the +// ResetStatus request. +type ResetStatusOptsBuilder interface { + ToSnapshotResetStatusMap() (map[string]interface{}, error) +} + +// ResetStatusOpts contains options for resetting a Snapshot status. +// For more information about these parameters, please, refer to the shared file systems API v2, +// Snapshot Actions, ResetStatus share documentation. +type ResetStatusOpts struct { + // Status is a snapshot status to reset to. Can be "available", "error", + // "creating", "deleting", "manage_starting", "manage_error", + // "unmanage_starting", "unmanage_error" or "error_deleting". + Status string `json:"status"` +} + +// ToSnapshotResetStatusMap assembles a request body based on the contents of a +// ResetStatusOpts. +func (opts ResetStatusOpts) ToSnapshotResetStatusMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "reset_status") +} + +// ResetStatus will reset the existing snapshot status. ResetStatusResult contains only the error. +// To extract it, call the ExtractErr method on the ResetStatusResult. +func ResetStatus(client *gophercloud.ServiceClient, id string, opts ResetStatusOptsBuilder) (r ResetStatusResult) { + b, err := opts.ToSnapshotResetStatusMap() + if err != nil { + r.Err = err + return + } + + resp, err := client.Post(resetStatusURL(client, id), b, nil, &gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// ForceDelete will delete the existing snapshot in any state. ForceDeleteResult contains only the error. +// To extract it, call the ExtractErr method on the ForceDeleteResult. +func ForceDelete(client *gophercloud.ServiceClient, id string) (r ForceDeleteResult) { + b := map[string]interface{}{ + "force_delete": nil, + } + resp, err := client.Post(forceDeleteURL(client, id), b, nil, &gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} diff --git a/openstack/sharedfilesystems/v2/snapshots/results.go b/openstack/sharedfilesystems/v2/snapshots/results.go index a3d45aaa94..44337b17a7 100644 --- a/openstack/sharedfilesystems/v2/snapshots/results.go +++ b/openstack/sharedfilesystems/v2/snapshots/results.go @@ -173,3 +173,13 @@ type GetResult struct { type UpdateResult struct { commonResult } + +// ResetStatusResult contains the response error from an ResetStatus request. +type ResetStatusResult struct { + gophercloud.ErrResult +} + +// ForceDeleteResult contains the response error from an ForceDelete request. +type ForceDeleteResult struct { + gophercloud.ErrResult +} diff --git a/openstack/sharedfilesystems/v2/snapshots/testing/fixtures.go b/openstack/sharedfilesystems/v2/snapshots/testing/fixtures.go index c02ef10c71..fb677918dd 100644 --- a/openstack/sharedfilesystems/v2/snapshots/testing/fixtures.go +++ b/openstack/sharedfilesystems/v2/snapshots/testing/fixtures.go @@ -204,3 +204,39 @@ func MockListDetailResponse(t *testing.T) { } }) } + +var resetStatusRequest = `{ + "reset_status": { + "status": "error" + } + }` + +// MockResetStatusResponse creates a mock reset status snapshot response +func MockResetStatusResponse(t *testing.T) { + th.Mux.HandleFunc(snapshotEndpoint+"/"+snapshotID+"/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, resetStatusRequest) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + }) +} + +var forceDeleteRequest = `{ + "force_delete": null + }` + +// MockForceDeleteResponse creates a mock force delete snapshot response +func MockForceDeleteResponse(t *testing.T) { + th.Mux.HandleFunc(snapshotEndpoint+"/"+snapshotID+"/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, forceDeleteRequest) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/openstack/sharedfilesystems/v2/snapshots/testing/request_test.go b/openstack/sharedfilesystems/v2/snapshots/testing/request_test.go index e210b4adc9..52f9c33a23 100644 --- a/openstack/sharedfilesystems/v2/snapshots/testing/request_test.go +++ b/openstack/sharedfilesystems/v2/snapshots/testing/request_test.go @@ -125,3 +125,27 @@ func TestListDetail(t *testing.T) { }, }) } + +func TestResetStatusSuccess(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + MockResetStatusResponse(t) + + c := client.ServiceClient() + + err := snapshots.ResetStatus(c, snapshotID, &snapshots.ResetStatusOpts{Status: "error"}).ExtractErr() + th.AssertNoErr(t, err) +} + +func TestForceDeleteSuccess(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + MockForceDeleteResponse(t) + + c := client.ServiceClient() + + err := snapshots.ForceDelete(c, snapshotID).ExtractErr() + th.AssertNoErr(t, err) +} diff --git a/openstack/sharedfilesystems/v2/snapshots/urls.go b/openstack/sharedfilesystems/v2/snapshots/urls.go index a07e3ec873..138d97f350 100644 --- a/openstack/sharedfilesystems/v2/snapshots/urls.go +++ b/openstack/sharedfilesystems/v2/snapshots/urls.go @@ -21,3 +21,11 @@ func getURL(c *gophercloud.ServiceClient, id string) string { func updateURL(c *gophercloud.ServiceClient, id string) string { return c.ServiceURL("snapshots", id) } + +func resetStatusURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("snapshots", id, "action") +} + +func forceDeleteURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("snapshots", id, "action") +} From b42636b9ced08f3651a36a33f1786fe517adb9e4 Mon Sep 17 00:00:00 2001 From: kayrus Date: Mon, 17 Jul 2023 18:03:00 +0200 Subject: [PATCH 013/118] [cinder]: add reset and force delete actions to volumes and snapshots --- .../blockstorage/extensions/extensions.go | 19 +++ .../extensions/volumeactions_test.go | 17 +++ .../openstack/blockstorage/v3/blockstorage.go | 21 +++ .../blockstorage/v3/quotaset_test.go | 2 +- .../blockstorage/v3/snapshots_test.go | 124 ++++++++++++++++++ .../extensions/volumeactions/requests.go | 40 ++++++ .../extensions/volumeactions/results.go | 5 + .../volumeactions/testing/fixtures.go | 21 +++ .../volumeactions/testing/requests_test.go | 16 +++ .../blockstorage/v3/snapshots/requests.go | 87 ++++++++++++ .../blockstorage/v3/snapshots/results.go | 15 +++ .../v3/snapshots/testing/fixtures.go | 62 ++++++++- .../v3/snapshots/testing/requests_test.go | 37 ++++++ openstack/blockstorage/v3/snapshots/urls.go | 12 ++ .../remoteconsoles/testing/fixtures.go | 2 +- 15 files changed, 472 insertions(+), 8 deletions(-) diff --git a/acceptance/openstack/blockstorage/extensions/extensions.go b/acceptance/openstack/blockstorage/extensions/extensions.go index d15e4b652d..dfa357fdd3 100644 --- a/acceptance/openstack/blockstorage/extensions/extensions.go +++ b/acceptance/openstack/blockstorage/extensions/extensions.go @@ -314,6 +314,25 @@ func ChangeVolumeType(t *testing.T, client *gophercloud.ServiceClient, volume *v return nil } +// ResetVolumeStatus will reset the status of a volume. +func ResetVolumeStatus(t *testing.T, client *gophercloud.ServiceClient, volume *v3.Volume, status string) error { + t.Logf("Attempting to reset the status of volume %s from %s to %s", volume.ID, volume.Status, status) + + resetOpts := volumeactions.ResetStatusOpts{ + Status: status, + } + err := volumeactions.ResetStatus(client, volume.ID, resetOpts).ExtractErr() + if err != nil { + return err + } + + if err := volumes.WaitForStatus(client, volume.ID, status, 60); err != nil { + return err + } + + return nil +} + // ReImage will re-image a volume func ReImage(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume, imageID string) error { t.Logf("Attempting to re-image volume %s", volume.ID) diff --git a/acceptance/openstack/blockstorage/extensions/volumeactions_test.go b/acceptance/openstack/blockstorage/extensions/volumeactions_test.go index 3c69d17a46..98541419df 100644 --- a/acceptance/openstack/blockstorage/extensions/volumeactions_test.go +++ b/acceptance/openstack/blockstorage/extensions/volumeactions_test.go @@ -145,6 +145,23 @@ func TestVolumeActionsChangeType(t *testing.T) { tools.PrintResource(t, newVolume) } +func TestVolumeActionsResetStatus(t *testing.T) { + client, err := clients.NewBlockStorageV3Client() + th.AssertNoErr(t, err) + + volume, err := blockstorageV3.CreateVolume(t, client) + th.AssertNoErr(t, err) + defer blockstorageV3.DeleteVolume(t, client, volume) + + tools.PrintResource(t, volume) + + err = ResetVolumeStatus(t, client, volume, "error") + th.AssertNoErr(t, err) + + err = ResetVolumeStatus(t, client, volume, "available") + th.AssertNoErr(t, err) +} + func TestVolumeActionsReImage(t *testing.T) { clients.SkipReleasesBelow(t, "stable/yoga") diff --git a/acceptance/openstack/blockstorage/v3/blockstorage.go b/acceptance/openstack/blockstorage/v3/blockstorage.go index 1645f327b6..ad6518b7de 100644 --- a/acceptance/openstack/blockstorage/v3/blockstorage.go +++ b/acceptance/openstack/blockstorage/v3/blockstorage.go @@ -38,6 +38,11 @@ func CreateSnapshot(t *testing.T, client *gophercloud.ServiceClient, volume *vol return snapshot, err } + snapshot, err = snapshots.Get(client, snapshot.ID).Extract() + if err != nil { + return snapshot, err + } + tools.PrintResource(t, snapshot) th.AssertEquals(t, snapshot.Name, snapshotName) th.AssertEquals(t, snapshot.VolumeID, volume.ID) @@ -70,6 +75,11 @@ func CreateVolume(t *testing.T, client *gophercloud.ServiceClient) (*volumes.Vol return volume, err } + volume, err = volumes.Get(client, volume.ID).Extract() + if err != nil { + return volume, err + } + tools.PrintResource(t, volume) th.AssertEquals(t, volume.Name, volumeName) th.AssertEquals(t, volume.Description, volumeDescription) @@ -105,6 +115,11 @@ func CreateVolumeWithType(t *testing.T, client *gophercloud.ServiceClient, vt *v return volume, err } + volume, err = volumes.Get(client, volume.ID).Extract() + if err != nil { + return volume, err + } + tools.PrintResource(t, volume) th.AssertEquals(t, volume.Name, volumeName) th.AssertEquals(t, volume.Description, volumeDescription) @@ -243,6 +258,9 @@ func CreatePrivateVolumeType(t *testing.T, client *gophercloud.ServiceClient) (* func DeleteSnapshot(t *testing.T, client *gophercloud.ServiceClient, snapshot *snapshots.Snapshot) { err := snapshots.Delete(client, snapshot.ID).ExtractErr() if err != nil { + if _, ok := err.(gophercloud.ErrDefault404); ok { + return + } t.Fatalf("Unable to delete snapshot %s: %+v", snapshot.ID, err) } @@ -270,6 +288,9 @@ func DeleteVolume(t *testing.T, client *gophercloud.ServiceClient, volume *volum err := volumes.Delete(client, volume.ID, volumes.DeleteOpts{}).ExtractErr() if err != nil { + if _, ok := err.(gophercloud.ErrDefault404); ok { + return + } t.Fatalf("Unable to delete volume %s: %v", volume.ID, err) } diff --git a/acceptance/openstack/blockstorage/v3/quotaset_test.go b/acceptance/openstack/blockstorage/v3/quotaset_test.go index bffe0793d1..5a9d702954 100644 --- a/acceptance/openstack/blockstorage/v3/quotaset_test.go +++ b/acceptance/openstack/blockstorage/v3/quotaset_test.go @@ -118,7 +118,7 @@ func TestQuotasetUpdate(t *testing.T) { // test that resultQuotas.Extra is populated with the 3 new quota types // for the new volumeType foo, don't take into account other volume types count := 0 - for k, _ := range resultQuotas.Extra { + for k := range resultQuotas.Extra { tools.PrintResource(t, k) switch k { case diff --git a/acceptance/openstack/blockstorage/v3/snapshots_test.go b/acceptance/openstack/blockstorage/v3/snapshots_test.go index 06ad8e8ba0..3c3d08ef4c 100644 --- a/acceptance/openstack/blockstorage/v3/snapshots_test.go +++ b/acceptance/openstack/blockstorage/v3/snapshots_test.go @@ -4,8 +4,10 @@ package v3 import ( + "fmt" "testing" + "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/acceptance/clients" "github.com/gophercloud/gophercloud/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots" @@ -73,3 +75,125 @@ func TestSnapshots(t *testing.T) { th.AssertNoErr(t, err) } + +func TestSnapshotsResetStatus(t *testing.T) { + clients.RequireLong(t) + + client, err := clients.NewBlockStorageV3Client() + th.AssertNoErr(t, err) + + volume1, err := CreateVolume(t, client) + th.AssertNoErr(t, err) + defer DeleteVolume(t, client, volume1) + + snapshot1, err := CreateSnapshot(t, client, volume1) + th.AssertNoErr(t, err) + defer DeleteSnapshot(t, client, snapshot1) + + // Reset snapshot status to error + resetOpts := snapshots.ResetStatusOpts{ + Status: "error", + } + t.Logf("Attempting to reset snapshot status to %s", resetOpts.Status) + err = snapshots.ResetStatus(client, snapshot1.ID, resetOpts).ExtractErr() + th.AssertNoErr(t, err) + + snapshot, err := snapshots.Get(client, snapshot1.ID).Extract() + th.AssertNoErr(t, err) + + if snapshot.Status != resetOpts.Status { + th.AssertNoErr(t, fmt.Errorf("unexpected %q snapshot status", snapshot.Status)) + } + + // Reset snapshot status to available + resetOpts = snapshots.ResetStatusOpts{ + Status: "available", + } + t.Logf("Attempting to reset snapshot status to %s", resetOpts.Status) + err = snapshots.ResetStatus(client, snapshot1.ID, resetOpts).ExtractErr() + th.AssertNoErr(t, err) + + snapshot, err = snapshots.Get(client, snapshot1.ID).Extract() + th.AssertNoErr(t, err) + + if snapshot.Status != resetOpts.Status { + th.AssertNoErr(t, fmt.Errorf("unexpected %q snapshot status", snapshot.Status)) + } +} + +func TestSnapshotsUpdateStatus(t *testing.T) { + clients.RequireLong(t) + + client, err := clients.NewBlockStorageV3Client() + th.AssertNoErr(t, err) + + volume1, err := CreateVolume(t, client) + th.AssertNoErr(t, err) + defer DeleteVolume(t, client, volume1) + + snapshot1, err := CreateSnapshot(t, client, volume1) + th.AssertNoErr(t, err) + defer DeleteSnapshot(t, client, snapshot1) + + // Update snapshot status to error + resetOpts := snapshots.ResetStatusOpts{ + Status: "creating", + } + t.Logf("Attempting to update snapshot status to %s", resetOpts.Status) + err = snapshots.ResetStatus(client, snapshot1.ID, resetOpts).ExtractErr() + th.AssertNoErr(t, err) + + snapshot, err := snapshots.Get(client, snapshot1.ID).Extract() + th.AssertNoErr(t, err) + + if snapshot.Status != resetOpts.Status { + th.AssertNoErr(t, fmt.Errorf("unexpected %q snapshot status", snapshot.Status)) + } + + // Update snapshot status to available + updateOpts := snapshots.UpdateStatusOpts{ + Status: "available", + } + t.Logf("Attempting to update snapshot status to %s", updateOpts.Status) + err = snapshots.UpdateStatus(client, snapshot1.ID, updateOpts).ExtractErr() + th.AssertNoErr(t, err) + + snapshot, err = snapshots.Get(client, snapshot1.ID).Extract() + th.AssertNoErr(t, err) + + if snapshot.Status != updateOpts.Status { + th.AssertNoErr(t, fmt.Errorf("unexpected %q snapshot status", snapshot.Status)) + } +} + +func TestSnapshotsForceDelete(t *testing.T) { + clients.RequireLong(t) + + client, err := clients.NewBlockStorageV3Client() + th.AssertNoErr(t, err) + + volume, err := CreateVolume(t, client) + th.AssertNoErr(t, err) + defer DeleteVolume(t, client, volume) + + snapshot, err := CreateSnapshot(t, client, volume) + th.AssertNoErr(t, err) + defer DeleteSnapshot(t, client, snapshot) + + // Force delete snapshot + t.Logf("Attempting to force delete %s snapshot", snapshot.ID) + err = snapshots.ForceDelete(client, snapshot.ID).ExtractErr() + th.AssertNoErr(t, err) + + err = tools.WaitFor(func() (bool, error) { + _, err := snapshots.Get(client, snapshot.ID).Extract() + if err != nil { + if _, ok := err.(gophercloud.ErrDefault404); ok { + return true, nil + } + } + + return false, nil + }) + th.AssertNoErr(t, err) +} diff --git a/openstack/blockstorage/extensions/volumeactions/requests.go b/openstack/blockstorage/extensions/volumeactions/requests.go index 09dfb9ed2f..03fb724a9f 100644 --- a/openstack/blockstorage/extensions/volumeactions/requests.go +++ b/openstack/blockstorage/extensions/volumeactions/requests.go @@ -418,3 +418,43 @@ func ReImage(client *gophercloud.ServiceClient, id string, opts ReImageOpts) (r _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } + +// ResetStatusOptsBuilder allows extensions to add additional parameters to the +// ResetStatus request. +type ResetStatusOptsBuilder interface { + ToResetStatusMap() (map[string]interface{}, error) +} + +// ResetStatusOpts contains options for resetting a Volume status. +// For more information about these parameters, please, refer to the Block Storage API V3, +// Volume Actions, ResetStatus volume documentation. +type ResetStatusOpts struct { + // Status is a volume status to reset to. + Status string `json:"status"` + // MigrationStatus is a volume migration status to reset to. + MigrationStatus string `json:"migration_status,omitempty"` + // AttachStatus is a volume attach status to reset to. + AttachStatus string `json:"attach_status,omitempty"` +} + +// ToResetStatusMap assembles a request body based on the contents of a +// ResetStatusOpts. +func (opts ResetStatusOpts) ToResetStatusMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "os-reset_status") +} + +// ResetStatus will reset the existing volume status. ResetStatusResult contains only the error. +// To extract it, call the ExtractErr method on the ResetStatusResult. +func ResetStatus(client *gophercloud.ServiceClient, id string, opts ResetStatusOptsBuilder) (r ResetStatusResult) { + b, err := opts.ToResetStatusMap() + if err != nil { + r.Err = err + return + } + + resp, err := client.Post(actionURL(client, id), b, nil, &gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} diff --git a/openstack/blockstorage/extensions/volumeactions/results.go b/openstack/blockstorage/extensions/volumeactions/results.go index 95b5bac1cb..34f64e18e8 100644 --- a/openstack/blockstorage/extensions/volumeactions/results.go +++ b/openstack/blockstorage/extensions/volumeactions/results.go @@ -219,3 +219,8 @@ type ChangeTypeResult struct { type ReImageResult struct { gophercloud.ErrResult } + +// ResetStatusResult contains the response error from a ResetStatus request. +type ResetStatusResult struct { + gophercloud.ErrResult +} diff --git a/openstack/blockstorage/extensions/volumeactions/testing/fixtures.go b/openstack/blockstorage/extensions/volumeactions/testing/fixtures.go index 378a120bc6..eef61d477a 100644 --- a/openstack/blockstorage/extensions/volumeactions/testing/fixtures.go +++ b/openstack/blockstorage/extensions/volumeactions/testing/fixtures.go @@ -370,3 +370,24 @@ func MockChangeTypeResponse(t *testing.T) { fmt.Fprintf(w, `{}`) }) } + +func MockResetStatusResponse(t *testing.T) { + th.Mux.HandleFunc("/volumes/cd281d77-8217-4830-be95-9528227c105c/action", + func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestJSONRequest(t, r, ` +{ + "os-reset_status": + { + "status": "error", + "attach_status": "detached", + "migration_status": "migrating" + } +} + `) + + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/openstack/blockstorage/extensions/volumeactions/testing/requests_test.go b/openstack/blockstorage/extensions/volumeactions/testing/requests_test.go index 2191a8a788..bb5d02e926 100644 --- a/openstack/blockstorage/extensions/volumeactions/testing/requests_test.go +++ b/openstack/blockstorage/extensions/volumeactions/testing/requests_test.go @@ -224,3 +224,19 @@ func TestChangeType(t *testing.T) { err := volumeactions.ChangeType(client.ServiceClient(), "cd281d77-8217-4830-be95-9528227c105c", options).ExtractErr() th.AssertNoErr(t, err) } + +func TestResetStatus(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + MockResetStatusResponse(t) + + options := &volumeactions.ResetStatusOpts{ + Status: "error", + AttachStatus: "detached", + MigrationStatus: "migrating", + } + + err := volumeactions.ResetStatus(client.ServiceClient(), "cd281d77-8217-4830-be95-9528227c105c", options).ExtractErr() + th.AssertNoErr(t, err) +} diff --git a/openstack/blockstorage/v3/snapshots/requests.go b/openstack/blockstorage/v3/snapshots/requests.go index 7dcfed7946..9bbec339ec 100644 --- a/openstack/blockstorage/v3/snapshots/requests.go +++ b/openstack/blockstorage/v3/snapshots/requests.go @@ -189,3 +189,90 @@ func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMet _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } + +// ResetStatusOptsBuilder allows extensions to add additional parameters to the +// ResetStatus request. +type ResetStatusOptsBuilder interface { + ToSnapshotResetStatusMap() (map[string]interface{}, error) +} + +// ResetStatusOpts contains options for resetting a Snapshot status. +// For more information about these parameters, please, refer to the Block Storage API V3, +// Snapshot Actions, ResetStatus snapshot documentation. +type ResetStatusOpts struct { + // Status is a snapshot status to reset to. + Status string `json:"status"` +} + +// ToSnapshotResetStatusMap assembles a request body based on the contents of a +// ResetStatusOpts. +func (opts ResetStatusOpts) ToSnapshotResetStatusMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "os-reset_status") +} + +// ResetStatus will reset the existing snapshot status. ResetStatusResult contains only the error. +// To extract it, call the ExtractErr method on the ResetStatusResult. +func ResetStatus(client *gophercloud.ServiceClient, id string, opts ResetStatusOptsBuilder) (r ResetStatusResult) { + b, err := opts.ToSnapshotResetStatusMap() + if err != nil { + r.Err = err + return + } + + resp, err := client.Post(resetStatusURL(client, id), b, nil, &gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// UpdateStatusOptsBuilder allows extensions to add additional parameters to the +// UpdateStatus request. +type UpdateStatusOptsBuilder interface { + ToSnapshotUpdateStatusMap() (map[string]interface{}, error) +} + +// UpdateStatusOpts contains options for resetting a Snapshot status. +// For more information about these parameters, please, refer to the Block Storage API V3, +// Snapshot Actions, UpdateStatus snapshot documentation. +type UpdateStatusOpts struct { + // Status is a snapshot status to update to. + Status string `json:"status"` + // A progress percentage value for snapshot build progress. + Progress string `json:"progress,omitempty"` +} + +// ToSnapshotUpdateStatusMap assembles a request body based on the contents of a +// UpdateStatusOpts. +func (opts UpdateStatusOpts) ToSnapshotUpdateStatusMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "os-update_snapshot_status") +} + +// UpdateStatus will reset the existing snapshot status. UpdateStatusResult contains only the error. +// To extract it, call the ExtractErr method on the UpdateStatusResult. +func UpdateStatus(client *gophercloud.ServiceClient, id string, opts UpdateStatusOptsBuilder) (r UpdateStatusResult) { + b, err := opts.ToSnapshotUpdateStatusMap() + if err != nil { + r.Err = err + return + } + + resp, err := client.Post(resetStatusURL(client, id), b, nil, &gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// ForceDelete will delete the existing snapshot in any state. ForceDeleteResult contains only the error. +// To extract it, call the ExtractErr method on the ForceDeleteResult. +func ForceDelete(client *gophercloud.ServiceClient, id string) (r ForceDeleteResult) { + b := map[string]interface{}{ + "os-force_delete": struct{}{}, + } + resp, err := client.Post(forceDeleteURL(client, id), b, nil, &gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} diff --git a/openstack/blockstorage/v3/snapshots/results.go b/openstack/blockstorage/v3/snapshots/results.go index d058b22172..23c7a506d8 100644 --- a/openstack/blockstorage/v3/snapshots/results.go +++ b/openstack/blockstorage/v3/snapshots/results.go @@ -141,3 +141,18 @@ func (r commonResult) Extract() (*Snapshot, error) { err := r.ExtractInto(&s) return s.Snapshot, err } + +// ResetStatusResult contains the response error from a ResetStatus request. +type ResetStatusResult struct { + gophercloud.ErrResult +} + +// UpdateStatusResult contains the response error from an UpdateStatus request. +type UpdateStatusResult struct { + gophercloud.ErrResult +} + +// ForceDeleteResult contains the response error from a ForceDelete request. +type ForceDeleteResult struct { + gophercloud.ErrResult +} diff --git a/openstack/blockstorage/v3/snapshots/testing/fixtures.go b/openstack/blockstorage/v3/snapshots/testing/fixtures.go index 3ae3bb86d2..be48c50048 100644 --- a/openstack/blockstorage/v3/snapshots/testing/fixtures.go +++ b/openstack/blockstorage/v3/snapshots/testing/fixtures.go @@ -9,7 +9,7 @@ import ( fake "github.com/gophercloud/gophercloud/testhelper/client" ) -// MockListResponse provides mock responce for list snapshot API call +// MockListResponse provides mock response for list snapshot API call func MockListResponse(t *testing.T) { th.Mux.HandleFunc("/snapshots", func(w http.ResponseWriter, r *http.Request) { th.TestMethod(t, r, "GET") @@ -59,7 +59,7 @@ func MockListResponse(t *testing.T) { }) } -// MockGetResponse provides mock responce for get snapshot API call +// MockGetResponse provides mock response for get snapshot API call func MockGetResponse(t *testing.T) { th.Mux.HandleFunc("/snapshots/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { th.TestMethod(t, r, "GET") @@ -83,7 +83,7 @@ func MockGetResponse(t *testing.T) { }) } -// MockCreateResponse provides mock responce for create snapshot API call +// MockCreateResponse provides mock response for create snapshot API call func MockCreateResponse(t *testing.T) { th.Mux.HandleFunc("/snapshots", func(w http.ResponseWriter, r *http.Request) { th.TestMethod(t, r, "POST") @@ -119,7 +119,7 @@ func MockCreateResponse(t *testing.T) { }) } -// MockUpdateMetadataResponse provides mock responce for update metadata snapshot API call +// MockUpdateMetadataResponse provides mock response for update metadata snapshot API call func MockUpdateMetadataResponse(t *testing.T) { th.Mux.HandleFunc("/snapshots/123/metadata", func(w http.ResponseWriter, r *http.Request) { th.TestMethod(t, r, "PUT") @@ -143,7 +143,7 @@ func MockUpdateMetadataResponse(t *testing.T) { }) } -// MockDeleteResponse provides mock responce for delete snapshot API call +// MockDeleteResponse provides mock response for delete snapshot API call func MockDeleteResponse(t *testing.T) { th.Mux.HandleFunc("/snapshots/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { th.TestMethod(t, r, "DELETE") @@ -152,7 +152,7 @@ func MockDeleteResponse(t *testing.T) { }) } -// MockUpdateResponse provides mock responce for update snapshot API call +// MockUpdateResponse provides mock response for update snapshot API call func MockUpdateResponse(t *testing.T) { th.Mux.HandleFunc("/snapshots/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { th.TestMethod(t, r, "PUT") @@ -176,3 +176,53 @@ func MockUpdateResponse(t *testing.T) { `) }) } + +// MockResetStatusResponse provides mock response for reset snapshot status API call +func MockResetStatusResponse(t *testing.T) { + th.Mux.HandleFunc("/snapshots/d32019d3-bc6e-4319-9c1d-6722fc136a22/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestJSONRequest(t, r, ` +{ + "os-reset_status": { + "status": "error" + } +} + `) + w.WriteHeader(http.StatusAccepted) + }) +} + +// MockUpdateStatusResponse provides mock response for update snapshot status API call +func MockUpdateStatusResponse(t *testing.T) { + th.Mux.HandleFunc("/snapshots/d32019d3-bc6e-4319-9c1d-6722fc136a22/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestJSONRequest(t, r, ` +{ + "os-update_snapshot_status": { + "status": "error", + "progress": "80%" + } +} + `) + w.WriteHeader(http.StatusAccepted) + }) +} + +// MockForceDeleteResponse provides mock response for force delete snapshot API call +func MockForceDeleteResponse(t *testing.T) { + th.Mux.HandleFunc("/snapshots/d32019d3-bc6e-4319-9c1d-6722fc136a22/action", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestJSONRequest(t, r, ` +{ + "os-force_delete": {} +} + `) + w.WriteHeader(http.StatusAccepted) + }) +} diff --git a/openstack/blockstorage/v3/snapshots/testing/requests_test.go b/openstack/blockstorage/v3/snapshots/testing/requests_test.go index a787928ba9..862b25e010 100644 --- a/openstack/blockstorage/v3/snapshots/testing/requests_test.go +++ b/openstack/blockstorage/v3/snapshots/testing/requests_test.go @@ -129,3 +129,40 @@ func TestUpdate(t *testing.T) { th.CheckEquals(t, "snapshot-002", v.Name) th.CheckEquals(t, "Daily backup 002", v.Description) } + +func TestResetStatus(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + MockResetStatusResponse(t) + + opts := &snapshots.ResetStatusOpts{ + Status: "error", + } + res := snapshots.ResetStatus(client.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22", opts) + th.AssertNoErr(t, res.Err) +} + +func TestUpdateStatus(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + MockUpdateStatusResponse(t) + + opts := &snapshots.UpdateStatusOpts{ + Status: "error", + Progress: "80%", + } + res := snapshots.UpdateStatus(client.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22", opts) + th.AssertNoErr(t, res.Err) +} + +func TestForceDelete(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + MockForceDeleteResponse(t) + + res := snapshots.ForceDelete(client.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22") + th.AssertNoErr(t, res.Err) +} diff --git a/openstack/blockstorage/v3/snapshots/urls.go b/openstack/blockstorage/v3/snapshots/urls.go index d0bcbfb98c..605b3cf5ec 100644 --- a/openstack/blockstorage/v3/snapshots/urls.go +++ b/openstack/blockstorage/v3/snapshots/urls.go @@ -29,3 +29,15 @@ func metadataURL(c *gophercloud.ServiceClient, id string) string { func updateMetadataURL(c *gophercloud.ServiceClient, id string) string { return metadataURL(c, id) } + +func resetStatusURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("snapshots", id, "action") +} + +func updateStatusURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("snapshots", id, "action") +} + +func forceDeleteURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("snapshots", id, "action") +} diff --git a/openstack/compute/v2/extensions/remoteconsoles/testing/fixtures.go b/openstack/compute/v2/extensions/remoteconsoles/testing/fixtures.go index 9644a4895e..53b9f5b88b 100644 --- a/openstack/compute/v2/extensions/remoteconsoles/testing/fixtures.go +++ b/openstack/compute/v2/extensions/remoteconsoles/testing/fixtures.go @@ -10,7 +10,7 @@ const RemoteConsoleCreateRequest = ` } ` -// RemoteConsoleCreateResult represents a raw server responce to the RemoteConsoleCreateRequest. +// RemoteConsoleCreateResult represents a raw server response to the RemoteConsoleCreateRequest. const RemoteConsoleCreateResult = ` { "remote_console": { From 705c6489ebb6244ac33bdda1be45254d32244c43 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Fri, 2 Dec 2022 12:41:12 +0100 Subject: [PATCH 014/118] orchestration: Explicit error in optionsmap creation Add verbosity to the error signaling a failure in the creation of the optionsmap. --- openstack/orchestration/v1/stacks/requests.go | 3 ++- openstack/orchestration/v1/stacks/testing/requests_test.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openstack/orchestration/v1/stacks/requests.go b/openstack/orchestration/v1/stacks/requests.go index 620e7576dc..0bd16543b9 100644 --- a/openstack/orchestration/v1/stacks/requests.go +++ b/openstack/orchestration/v1/stacks/requests.go @@ -1,6 +1,7 @@ package stacks import ( + "fmt" "strings" "github.com/gophercloud/gophercloud" @@ -89,7 +90,7 @@ func (opts CreateOpts) ToStackCreateMap() (map[string]interface{}, error) { func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { b, err := opts.ToStackCreateMap() if err != nil { - r.Err = err + r.Err = fmt.Errorf("error creating the options map: %w", err) return } resp, err := c.Post(createURL(c), b, &r.Body, nil) diff --git a/openstack/orchestration/v1/stacks/testing/requests_test.go b/openstack/orchestration/v1/stacks/testing/requests_test.go index 6f0eb3a8e9..9f0932a4d2 100644 --- a/openstack/orchestration/v1/stacks/testing/requests_test.go +++ b/openstack/orchestration/v1/stacks/testing/requests_test.go @@ -59,7 +59,7 @@ func TestCreateStackMissingRequiredInOpts(t *testing.T) { DisableRollback: gophercloud.Disabled, } r := stacks.Create(fake.ServiceClient(), createOpts) - th.AssertEquals(t, "Missing input for argument [Name]", r.Err.Error()) + th.AssertEquals(t, "error creating the options map: Missing input for argument [Name]", r.Err.Error()) } func TestAdoptStack(t *testing.T) { From 1f3de5382281c6b852a5b41167108c35c91fa8e6 Mon Sep 17 00:00:00 2001 From: Duc Truong Date: Mon, 7 Aug 2023 14:01:40 -0700 Subject: [PATCH 015/118] Add conductor API to Baremetal V1 --- .../openstack/baremetal/v1/conductors_test.go | 32 ++++ openstack/baremetal/v1/conductors/doc.go | 46 +++++ openstack/baremetal/v1/conductors/requests.go | 72 +++++++ openstack/baremetal/v1/conductors/results.go | 93 +++++++++ .../baremetal/v1/conductors/testing/doc.go | 2 + .../v1/conductors/testing/fixtures.go | 181 ++++++++++++++++++ .../v1/conductors/testing/requests_test.go | 106 ++++++++++ openstack/baremetal/v1/conductors/urls.go | 11 ++ 8 files changed, 543 insertions(+) create mode 100644 acceptance/openstack/baremetal/v1/conductors_test.go create mode 100644 openstack/baremetal/v1/conductors/doc.go create mode 100644 openstack/baremetal/v1/conductors/requests.go create mode 100644 openstack/baremetal/v1/conductors/results.go create mode 100644 openstack/baremetal/v1/conductors/testing/doc.go create mode 100644 openstack/baremetal/v1/conductors/testing/fixtures.go create mode 100644 openstack/baremetal/v1/conductors/testing/requests_test.go create mode 100644 openstack/baremetal/v1/conductors/urls.go diff --git a/acceptance/openstack/baremetal/v1/conductors_test.go b/acceptance/openstack/baremetal/v1/conductors_test.go new file mode 100644 index 0000000000..f587d6fc3f --- /dev/null +++ b/acceptance/openstack/baremetal/v1/conductors_test.go @@ -0,0 +1,32 @@ +//go:build acceptance || baremetal || ports +// +build acceptance baremetal ports + +package v1 + +import ( + "testing" + + "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/openstack/baremetal/v1/conductors" + "github.com/gophercloud/gophercloud/pagination" + + th "github.com/gophercloud/gophercloud/testhelper" +) + +func TestConductorsList(t *testing.T) { + clients.RequireLong(t) + + client, err := clients.NewBareMetalV1Client() + th.AssertNoErr(t, err) + client.Microversion = "1.53" + + err = conductors.List(client, conductors.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { + _, err := conductors.ExtractConductors(page) + if err != nil { + return false, err + } + + return false, nil + }) + th.AssertNoErr(t, err) +} diff --git a/openstack/baremetal/v1/conductors/doc.go b/openstack/baremetal/v1/conductors/doc.go new file mode 100644 index 0000000000..904910044c --- /dev/null +++ b/openstack/baremetal/v1/conductors/doc.go @@ -0,0 +1,46 @@ +/* +Package conductors provides information and interaction with the conductors API +resource in the OpenStack Bare Metal service. + +Example to List Conductors with Detail + + conductors.List(client, conductors.ListOpts{Detail: true}).EachPage(func(page pagination.Page) (bool, error) { + conductorList, err := conductors.ExtractConductors(page) + if err != nil { + return false, err + } + + for _, n := range conductorList { + // Do something + } + + return true, nil + }) + +Example to List Conductors + + listOpts := conductors.ListOpts{ + Fields: []string{"hostname"}, + } + + conductors.List(client, listOpts).EachPage(func(page pagination.Page) (bool, error) { + conductorList, err := conductors.ExtractConductors(page) + if err != nil { + return false, err + } + + for _, n := range conductorList { + // Do something + } + + return true, nil + }) + +Example to Get Conductor + + showConductor, err := conductors.Get(client, "compute2.localdomain").Extract() + if err != nil { + panic(err) + } +*/ +package conductors diff --git a/openstack/baremetal/v1/conductors/requests.go b/openstack/baremetal/v1/conductors/requests.go new file mode 100644 index 0000000000..f5bc63d63e --- /dev/null +++ b/openstack/baremetal/v1/conductors/requests.go @@ -0,0 +1,72 @@ +package conductors + +import ( + "fmt" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToConductorListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. Filtering is achieved by passing in struct field values that map to +// the conductor attributes you want to see returned. Marker and Limit are used +// for pagination. +type ListOpts struct { + // One or more fields to be returned in the response. + Fields []string `q:"fields"` + + // Requests a page size of items. + Limit int `q:"limit"` + + // The ID of the last-seen item. + Marker string `q:"marker"` + + // Sorts the response by the requested sort direction. + SortDir string `q:"sort_dir"` + + // Sorts the response by the this attribute value. + SortKey string `q:"sort_key"` + + // Provide additional information for the BIOS Settings + Detail bool `q:"detail"` +} + +// ToConductorListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToConductorListQuery() (string, error) { + if opts.Detail == true && len(opts.Fields) > 0 { + return "", fmt.Errorf("cannot have both fields and detail options for conductors") + } + + q, err := gophercloud.BuildQueryString(opts) + return q.String(), err +} + +// List makes a request against the API to list conductors accessible to you. +func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listURL(client) + if opts != nil { + query, err := opts.ToConductorListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { + return ConductorPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// Get requests details on a single conductor by hostname +func Get(client *gophercloud.ServiceClient, name string) (r GetResult) { + resp, err := client.Get(getURL(client, name), &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} diff --git a/openstack/baremetal/v1/conductors/results.go b/openstack/baremetal/v1/conductors/results.go new file mode 100644 index 0000000000..9dd4e963c3 --- /dev/null +++ b/openstack/baremetal/v1/conductors/results.go @@ -0,0 +1,93 @@ +package conductors + +import ( + "time" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +type conductorResult struct { + gophercloud.Result +} + +// Extract interprets any conductorResult as a Conductor, if possible. +func (r conductorResult) Extract() (*Conductor, error) { + var s Conductor + err := r.ExtractInto(&s) + return &s, err +} + +func (r conductorResult) ExtractInto(v interface{}) error { + return r.Result.ExtractIntoStructPtr(v, "") +} + +func ExtractConductorInto(r pagination.Page, v interface{}) error { + return r.(ConductorPage).Result.ExtractIntoSlicePtr(v, "conductors") +} + +// Conductor represents a conductor in the OpenStack Bare Metal API. +type Conductor struct { + // Whether or not this Conductor is alive or not + Alive bool `json:"alive"` + + // Hostname of this conductor + Hostname string `json:"hostname"` + + // Array of drivers for this conductor. + Drivers []string `json:"drivers"` + + // Conductor group for a conductor. Case-insensitive string up to 255 characters, containing a-z, 0-9, _, -, and .. + ConductorGroup string `json:"conductor_group"` + + // The UTC date and time when the resource was created, ISO 8601 format. + CreatedAt time.Time `json:"created_at"` + + // The UTC date and time when the resource was updated, ISO 8601 format. May be “null”. + UpdatedAt time.Time `json:"updated_at"` +} + +// ConductorPage abstracts the raw results of making a List() request against +// the API. As OpenStack extensions may freely alter the response bodies of +// structures returned to the client, you may only safely access the data +// provided through the ExtractConductor call. +type ConductorPage struct { + pagination.LinkedPageBase +} + +// IsEmpty returns true if a page contains no conductor results. +func (r ConductorPage) IsEmpty() (bool, error) { + if r.StatusCode == 204 { + return true, nil + } + + s, err := ExtractConductors(r) + return len(s) == 0, err +} + +// NextPageURL uses the response's embedded link reference to navigate to the +// next page of results. +func (r ConductorPage) NextPageURL() (string, error) { + var s struct { + Links []gophercloud.Link `json:"conductor_links"` + } + err := r.ExtractInto(&s) + if err != nil { + return "", err + } + return gophercloud.ExtractNextURL(s.Links) +} + +// ExtractConductors interprets the results of a single page from a List() call, +// producing a slice of Conductor entities. +func ExtractConductors(r pagination.Page) ([]Conductor, error) { + var s []Conductor + err := ExtractConductorInto(r, &s) + return s, err +} + +// GetResult is the response from a Get operation. Call its Extract +// method to interpret it as a Conductor. +type GetResult struct { + conductorResult +} diff --git a/openstack/baremetal/v1/conductors/testing/doc.go b/openstack/baremetal/v1/conductors/testing/doc.go new file mode 100644 index 0000000000..9cc2466b89 --- /dev/null +++ b/openstack/baremetal/v1/conductors/testing/doc.go @@ -0,0 +1,2 @@ +// conductors unit tests +package testing diff --git a/openstack/baremetal/v1/conductors/testing/fixtures.go b/openstack/baremetal/v1/conductors/testing/fixtures.go new file mode 100644 index 0000000000..02e671aa28 --- /dev/null +++ b/openstack/baremetal/v1/conductors/testing/fixtures.go @@ -0,0 +1,181 @@ +package testing + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/gophercloud/gophercloud/openstack/baremetal/v1/conductors" + th "github.com/gophercloud/gophercloud/testhelper" + "github.com/gophercloud/gophercloud/testhelper/client" +) + +// ConductorListBody contains the canned body of a conductor.List response, without detail. +const ConductorListBody = ` + { + "conductors": [ + { + "hostname": "compute1.localdomain", + "conductor_group": "", + "links": [ + { + "href": "http://127.0.0.1:6385/v1/conductors/compute1.localdomain", + "rel": "self" + }, + { + "href": "http://127.0.0.1:6385/conductors/compute1.localdomain", + "rel": "bookmark" + } + ], + "alive": false + }, + { + "hostname": "compute2.localdomain", + "conductor_group": "", + "links": [ + { + "href": "http://127.0.0.1:6385/v1/conductors/compute2.localdomain", + "rel": "self" + }, + { + "href": "http://127.0.0.1:6385/conductors/compute2.localdomain", + "rel": "bookmark" + } + ], + "alive": true + } + ] + } +` + +// ConductorListDetailBody contains the canned body of a conductor.ListDetail response. +const ConductorListDetailBody = ` +{ + "conductors": [ + { + "links": [ + { + "href": "http://127.0.0.1:6385/v1/conductors/compute1.localdomain", + "rel": "self" + }, + { + "href": "http://127.0.0.1:6385/conductors/compute1.localdomain", + "rel": "bookmark" + } + ], + "created_at": "2018-08-07T08:39:21+00:00", + "hostname": "compute1.localdomain", + "conductor_group": "", + "updated_at": "2018-11-30T07:07:23+00:00", + "alive": false, + "drivers": [ + "ipmi" + ] + }, + { + "links": [ + { + "href": "http://127.0.0.1:6385/v1/conductors/compute2.localdomain", + "rel": "self" + }, + { + "href": "http://127.0.0.1:6385/conductors/compute2.localdomain", + "rel": "bookmark" + } + ], + "created_at": "2018-12-05T07:03:19+00:00", + "hostname": "compute2.localdomain", + "conductor_group": "", + "updated_at": "2018-12-05T07:03:21+00:00", + "alive": true, + "drivers": [ + "ipmi" + ] + } + ] +} +` + +// SingleConductorBody is the canned body of a Get request on an existing conductor. +const SingleConductorBody = ` +{ + "links": [ + { + "href": "http://127.0.0.1:6385/v1/conductors/compute2.localdomain", + "rel": "self" + }, + { + "href": "http://127.0.0.1:6385/conductors/compute2.localdomain", + "rel": "bookmark" + } + ], + "created_at": "2018-12-05T07:03:19+00:00", + "hostname": "compute2.localdomain", + "conductor_group": "", + "updated_at": "2018-12-05T07:03:21+00:00", + "alive": true, + "drivers": [ + "ipmi" + ] +} +` + +var ( + createdAtFoo, _ = time.Parse(time.RFC3339, "2018-12-05T07:03:19+00:00") + updatedAt, _ = time.Parse(time.RFC3339, "2018-12-05T07:03:21+00:00") + + ConductorFoo = conductors.Conductor{ + CreatedAt: createdAtFoo, + UpdatedAt: updatedAt, + Hostname: "compute2.localdomain", + ConductorGroup: "", + Alive: true, + Drivers: []string{ + "ipmi", + }, + } +) + +// HandleConductorListSuccessfully sets up the test server to respond to a server List request. +func HandleConductorListSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/conductors", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + w.Header().Add("Content-Type", "application/json") + r.ParseForm() + + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, ConductorListBody) + + case "9e5476bd-a4ec-4653-93d6-72c93aa682ba": + fmt.Fprintf(w, `{ "servers": [] }`) + default: + t.Fatalf("/conductors invoked with unexpected marker=[%s]", marker) + } + }) +} + +// HandleConductorListDetailSuccessfully sets up the test server to respond to a server List request. +func HandleConductorListDetailSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/conductors", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + w.Header().Add("Content-Type", "application/json") + r.ParseForm() + + fmt.Fprintf(w, ConductorListDetailBody) + }) +} + +func HandleConductorGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/conductors/1234asdf", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + fmt.Fprintf(w, SingleConductorBody) + }) +} diff --git a/openstack/baremetal/v1/conductors/testing/requests_test.go b/openstack/baremetal/v1/conductors/testing/requests_test.go new file mode 100644 index 0000000000..b05495a5fd --- /dev/null +++ b/openstack/baremetal/v1/conductors/testing/requests_test.go @@ -0,0 +1,106 @@ +package testing + +import ( + "testing" + + "github.com/gophercloud/gophercloud/openstack/baremetal/v1/conductors" + "github.com/gophercloud/gophercloud/pagination" + th "github.com/gophercloud/gophercloud/testhelper" + "github.com/gophercloud/gophercloud/testhelper/client" +) + +func TestListConductors(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleConductorListSuccessfully(t) + + pages := 0 + err := conductors.List(client.ServiceClient(), conductors.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { + pages++ + + actual, err := conductors.ExtractConductors(page) + if err != nil { + return false, err + } + + if len(actual) != 2 { + t.Fatalf("Expected 2 conductors, got %d", len(actual)) + } + th.AssertEquals(t, "compute1.localdomain", actual[0].Hostname) + th.AssertEquals(t, "compute2.localdomain", actual[1].Hostname) + + return true, nil + }) + + th.AssertNoErr(t, err) + + if pages != 1 { + t.Errorf("Expected 1 page, saw %d", pages) + } +} + +func TestListDetailConductors(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleConductorListDetailSuccessfully(t) + + pages := 0 + err := conductors.List(client.ServiceClient(), conductors.ListOpts{Detail: true}).EachPage(func(page pagination.Page) (bool, error) { + pages++ + + actual, err := conductors.ExtractConductors(page) + if err != nil { + return false, err + } + + if len(actual) != 2 { + t.Fatalf("Expected 2 conductors, got %d", len(actual)) + } + th.AssertEquals(t, "compute1.localdomain", actual[0].Hostname) + th.AssertEquals(t, false, actual[0].Alive) + th.AssertEquals(t, "compute2.localdomain", actual[1].Hostname) + th.AssertEquals(t, true, actual[1].Alive) + + return true, nil + }) + + th.AssertNoErr(t, err) + + if pages != 1 { + t.Errorf("Expected 1 page, saw %d", pages) + } +} + +func TestListOpts(t *testing.T) { + // Detail cannot take Fields + optsDetail := conductors.ListOpts{ + Fields: []string{"hostname", "alive"}, + Detail: true, + } + + opts := conductors.ListOpts{ + Fields: []string{"hostname", "alive"}, + } + + _, err := optsDetail.ToConductorListQuery() + th.AssertEquals(t, err.Error(), "cannot have both fields and detail options for conductors") + + // Regular ListOpts can + query, err := opts.ToConductorListQuery() + th.AssertEquals(t, query, "?fields=hostname&fields=alive") + th.AssertNoErr(t, err) +} + +func TestGetConductor(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleConductorGetSuccessfully(t) + + c := client.ServiceClient() + actual, err := conductors.Get(c, "1234asdf").Extract() + if err != nil { + t.Fatalf("Unexpected Get error: %v", err) + } + + th.CheckDeepEquals(t, ConductorFoo, *actual) +} diff --git a/openstack/baremetal/v1/conductors/urls.go b/openstack/baremetal/v1/conductors/urls.go new file mode 100644 index 0000000000..a52e1e5ca5 --- /dev/null +++ b/openstack/baremetal/v1/conductors/urls.go @@ -0,0 +1,11 @@ +package conductors + +import "github.com/gophercloud/gophercloud" + +func listURL(client *gophercloud.ServiceClient) string { + return client.ServiceURL("conductors") +} + +func getURL(client *gophercloud.ServiceClient, id string) string { + return client.ServiceURL("conductors", id) +} From 0fe4b1bd9c2ed2e424b076dc9c02c834db62a361 Mon Sep 17 00:00:00 2001 From: Duc Truong Date: Mon, 7 Aug 2023 14:01:40 -0700 Subject: [PATCH 016/118] Add conductor API to Baremetal V1 --- .../openstack/baremetal/v1/conductors_test.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/acceptance/openstack/baremetal/v1/conductors_test.go b/acceptance/openstack/baremetal/v1/conductors_test.go index f587d6fc3f..861fa31f6b 100644 --- a/acceptance/openstack/baremetal/v1/conductors_test.go +++ b/acceptance/openstack/baremetal/v1/conductors_test.go @@ -1,5 +1,5 @@ -//go:build acceptance || baremetal || ports -// +build acceptance baremetal ports +//go:build acceptance || baremetal || conductors +// +build acceptance baremetal conductors package v1 @@ -7,6 +7,7 @@ import ( "testing" "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/conductors" "github.com/gophercloud/gophercloud/pagination" @@ -18,15 +19,17 @@ func TestConductorsList(t *testing.T) { client, err := clients.NewBareMetalV1Client() th.AssertNoErr(t, err) - client.Microversion = "1.53" + client.Microversion = "1.49" err = conductors.List(client, conductors.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { - _, err := conductors.ExtractConductors(page) + conductorList, err := conductors.ExtractConductors(page) if err != nil { return false, err } - return false, nil + tools.PrintResource(t, conductorList) + + return true, nil }) th.AssertNoErr(t, err) } From 9697b21450f275d1e5e676128a08687f6fea2d10 Mon Sep 17 00:00:00 2001 From: Duc Truong Date: Tue, 8 Aug 2023 12:04:08 -0700 Subject: [PATCH 017/118] Add get conductor acceptance test --- acceptance/openstack/baremetal/v1/conductors_test.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/acceptance/openstack/baremetal/v1/conductors_test.go b/acceptance/openstack/baremetal/v1/conductors_test.go index 861fa31f6b..5324a7aa1c 100644 --- a/acceptance/openstack/baremetal/v1/conductors_test.go +++ b/acceptance/openstack/baremetal/v1/conductors_test.go @@ -14,7 +14,7 @@ import ( th "github.com/gophercloud/gophercloud/testhelper" ) -func TestConductorsList(t *testing.T) { +func TestConductorsListAndGet(t *testing.T) { clients.RequireLong(t) client, err := clients.NewBareMetalV1Client() @@ -29,6 +29,13 @@ func TestConductorsList(t *testing.T) { tools.PrintResource(t, conductorList) + if len(conductorList) > 0 { + conductor, err := conductors.Get(client, conductorList[0].Hostname).Extract() + th.AssertNoErr(t, err) + + tools.PrintResource(t, conductor) + } + return true, nil }) th.AssertNoErr(t, err) From 45e856e8784ef02757c332cb32231063b7afaf17 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Mon, 21 Aug 2023 13:16:21 -0400 Subject: [PATCH 018/118] networking/v2/ports: allow list filter by security group neutron v2 ports APIs allow to list ports by security group already: https://docs.openstack.org/api-ref/network/v2/#show-port-details This patch adds the `SecurityGroups` field to `ListOpts`. One way to filter the ports by security group can be done with the following code: ``` listOpts := ports.ListOpts{ SecurityGroups: []string{"2183457b-70cc-4fd0-a2dc-95323fa19e45"} } allPages, err := ports.List(networkClient, listOpts).AllPages() if err != nil { panic(err) } allPorts, err := ports.ExtractPorts(allPages) if err != nil { panic(err) } for _, port := range allPorts { fmt.Printf("%+v\n", port) } ``` --- openstack/networking/v2/ports/requests.go | 41 ++++++++++++----------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/openstack/networking/v2/ports/requests.go b/openstack/networking/v2/ports/requests.go index 48f9985643..805f0e5b99 100644 --- a/openstack/networking/v2/ports/requests.go +++ b/openstack/networking/v2/ports/requests.go @@ -21,26 +21,27 @@ type ListOptsBuilder interface { // by a particular port attribute. SortDir sets the direction, and is either // `asc' or `desc'. Marker and Limit are used for pagination. type ListOpts struct { - Status string `q:"status"` - Name string `q:"name"` - Description string `q:"description"` - AdminStateUp *bool `q:"admin_state_up"` - NetworkID string `q:"network_id"` - TenantID string `q:"tenant_id"` - ProjectID string `q:"project_id"` - DeviceOwner string `q:"device_owner"` - MACAddress string `q:"mac_address"` - ID string `q:"id"` - DeviceID string `q:"device_id"` - Limit int `q:"limit"` - Marker string `q:"marker"` - SortKey string `q:"sort_key"` - SortDir string `q:"sort_dir"` - Tags string `q:"tags"` - TagsAny string `q:"tags-any"` - NotTags string `q:"not-tags"` - NotTagsAny string `q:"not-tags-any"` - FixedIPs []FixedIPOpts + Status string `q:"status"` + Name string `q:"name"` + Description string `q:"description"` + AdminStateUp *bool `q:"admin_state_up"` + NetworkID string `q:"network_id"` + TenantID string `q:"tenant_id"` + ProjectID string `q:"project_id"` + DeviceOwner string `q:"device_owner"` + MACAddress string `q:"mac_address"` + ID string `q:"id"` + DeviceID string `q:"device_id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` + Tags string `q:"tags"` + TagsAny string `q:"tags-any"` + NotTags string `q:"not-tags"` + NotTagsAny string `q:"not-tags-any"` + SecurityGroups []string `q:"security_groups"` + FixedIPs []FixedIPOpts } type FixedIPOpts struct { From 853953105f2d9179024f03880a065a6489df1a1b Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 30 Aug 2023 15:06:55 +0200 Subject: [PATCH 019/118] Prepare release v1.6.0 --- CHANGELOG.md | 21 +++++++++++++++++++++ provider_client.go | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e19d5af517..fb9d4172a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +## v1.6.0 (2023-08-30) + +New features and improvements: + +* [GH-2712](https://github.com/gophercloud/gophercloud/pull/2712) [v1] README: minor change to test backport workflow +* [GH-2713](https://github.com/gophercloud/gophercloud/pull/2713) [v1] tests: run MultiAttach with a capable Cinder Type +* [GH-2714](https://github.com/gophercloud/gophercloud/pull/2714) [v1] Add CRUD support for encryption in volume v3 types +* [GH-2715](https://github.com/gophercloud/gophercloud/pull/2715) [v1] Add projectID to fwaas_v2 policy CreateOpts and ListOpts +* [GH-2716](https://github.com/gophercloud/gophercloud/pull/2716) [v1] Add projectID to fwaas_v2 CreateOpts +* [GH-2717](https://github.com/gophercloud/gophercloud/pull/2717) [v1] [manila]: add reset and force delete actions to a snapshot +* [GH-2718](https://github.com/gophercloud/gophercloud/pull/2718) [v1] [cinder]: add reset and force delete actions to volumes and snapshots +* [GH-2721](https://github.com/gophercloud/gophercloud/pull/2721) [v1] orchestration: Explicit error in optionsmap creation +* [GH-2723](https://github.com/gophercloud/gophercloud/pull/2723) [v1] Add conductor API to Baremetal V1 +* [GH-2729](https://github.com/gophercloud/gophercloud/pull/2729) [v1] networking/v2/ports: allow list filter by security group + +CI changes: + +* [GH-2675](https://github.com/gophercloud/gophercloud/pull/2675) [v1][CI] Drop periodic jobs from stable branch +* [GH-2683](https://github.com/gophercloud/gophercloud/pull/2683) [v1] CI tweaks + + ## v1.5.0 (2023-06-21) New features and improvements: diff --git a/provider_client.go b/provider_client.go index 6cfb14fd7e..d1955b65ab 100644 --- a/provider_client.go +++ b/provider_client.go @@ -14,7 +14,7 @@ import ( // DefaultUserAgent is the default User-Agent string set in the request header. const ( - DefaultUserAgent = "gophercloud/v1.5.0" + DefaultUserAgent = "gophercloud/v1.6.0" DefaultMaxBackoffRetries = 60 ) From 224322e323b6029379113fc1c0bc97d13ccc7f10 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Tue, 29 Aug 2023 10:23:31 -0400 Subject: [PATCH 020/118] workflow: remove semver-require Now that semver label is always set but the bot, we don't need to ensure that a label was set. --- .github/workflows/semver-require.yaml | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 .github/workflows/semver-require.yaml diff --git a/.github/workflows/semver-require.yaml b/.github/workflows/semver-require.yaml deleted file mode 100644 index d584899306..0000000000 --- a/.github/workflows/semver-require.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: Verify PR Labels -on: - pull_request: - types: - - opened - - labeled - - unlabeled - - synchronize -jobs: - semver: - runs-on: ubuntu-latest - steps: - - uses: mheap/github-action-required-labels@v5 - with: - mode: exactly - count: 1 - labels: "semver:patch, semver:minor, semver:major" From f826aede41ae83a7127bcff96bbb272d04e0156f Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Fri, 18 Nov 2022 09:50:53 -0500 Subject: [PATCH 021/118] Add Github Workflow for checking Go API compatibility on PRs It'll automatically set the semver label for a given PR. Limitation: files under `/acceptance` or named `doc.go`, `fixtures.go` and `fixture.go` which don't count as semver, will count in this new job. This is because we would need to add a commit that exclude these files, then rebase the PR on top of that and run `go-apidiff`. This is too complex for now and might be addressed later. (cherry picked from commit 00da6f70afacb50378ce7cc0d6413359aa98899a) --- .github/workflows/semver-auto.yaml | 51 +++++++++++++++++++++++++++ .github/workflows/semver-unlabel.yaml | 21 ----------- 2 files changed, 51 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/semver-auto.yaml delete mode 100644 .github/workflows/semver-unlabel.yaml diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml new file mode 100644 index 0000000000..a5fbf1cee6 --- /dev/null +++ b/.github/workflows/semver-auto.yaml @@ -0,0 +1,51 @@ +name: Add PR semver labels +on: + pull_request_target: + types: [opened, synchronize, reopened] +jobs: + go-apidiff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + token: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/setup-go@v2 + with: + go-version: '1' + + - name: Remove the semver label + uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 + with: + labels: | + semver:patch + semver:minor + semver:major + github_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Checking Go API Compatibility + id: go-apidiff + uses: joelanford/go-apidiff@v0.7.0 + + - name: Add semver:patch label + if: always() && steps.go-apidiff.outputs.semver-type == 'patch' + uses: actions-ecosystem/action-add-labels@bd52874380e3909a1ac983768df6976535ece7f8 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + labels: semver:patch + + - name: Add semver:minor label + if: always() && steps.go-apidiff.outputs.semver-type == 'minor' + uses: actions-ecosystem/action-add-labels@bd52874380e3909a1ac983768df6976535ece7f8 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + labels: semver:minor + + - name: Add semver:major label + if: always() && steps.go-apidiff.outputs.semver-type == 'major' + uses: actions-ecosystem/action-add-labels@bd52874380e3909a1ac983768df6976535ece7f8 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + labels: semver:major diff --git a/.github/workflows/semver-unlabel.yaml b/.github/workflows/semver-unlabel.yaml deleted file mode 100644 index 9fdf5558e4..0000000000 --- a/.github/workflows/semver-unlabel.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: Reset PR labels on push - -# **What it does**: When the content of a PR changes, this workflow removes the semver label -# **Why we have it**: To make sure semver labels are up-to-date. -# **Who does it impact**: Pull requests. - -on: - pull_request_target: - types: - - synchronize - -jobs: - semver: - runs-on: ubuntu-latest - steps: - - name: Remove the semver label - uses: andymckay/labeler@1.0.4 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - remove-labels: "semver:patch, semver:minor, semver:major" From 8fe63e9602cd0e80c04fdfed81a6800a8211bcf1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Aug 2023 09:06:27 +0000 Subject: [PATCH 022/118] Bump actions/setup-go from 2 to 4 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 2 to 4. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] (cherry picked from commit 86e726d1a1072a2ebd10ce692578efac3bdb2643) --- .github/workflows/semver-auto.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index a5fbf1cee6..ecb3be0f05 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -12,7 +12,7 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} token: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v4 with: go-version: '1' From 8bc2f1abdb504d809bb83f1620d53e140618a862 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Aug 2023 09:06:29 +0000 Subject: [PATCH 023/118] Bump actions-ecosystem/action-add-labels from 1.1.0 to 1.1.3 Bumps [actions-ecosystem/action-add-labels](https://github.com/actions-ecosystem/action-add-labels) from 1.1.0 to 1.1.3. - [Release notes](https://github.com/actions-ecosystem/action-add-labels/releases) - [Commits](https://github.com/actions-ecosystem/action-add-labels/compare/bd52874380e3909a1ac983768df6976535ece7f8...18f1af5e3544586314bbe15c0273249c770b2daf) --- updated-dependencies: - dependency-name: actions-ecosystem/action-add-labels dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] (cherry picked from commit 8a032b26f39817e01dd42d1e3b3de49685872bd2) --- .github/workflows/semver-auto.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index ecb3be0f05..bc5322b7e4 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -31,21 +31,21 @@ jobs: - name: Add semver:patch label if: always() && steps.go-apidiff.outputs.semver-type == 'patch' - uses: actions-ecosystem/action-add-labels@bd52874380e3909a1ac983768df6976535ece7f8 + uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf with: github_token: ${{ secrets.GITHUB_TOKEN }} labels: semver:patch - name: Add semver:minor label if: always() && steps.go-apidiff.outputs.semver-type == 'minor' - uses: actions-ecosystem/action-add-labels@bd52874380e3909a1ac983768df6976535ece7f8 + uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf with: github_token: ${{ secrets.GITHUB_TOKEN }} labels: semver:minor - name: Add semver:major label if: always() && steps.go-apidiff.outputs.semver-type == 'major' - uses: actions-ecosystem/action-add-labels@bd52874380e3909a1ac983768df6976535ece7f8 + uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf with: github_token: ${{ secrets.GITHUB_TOKEN }} labels: semver:major From d8ced84de067c1b1d0d6e354d20c2667c9797c77 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Wed, 30 Aug 2023 09:13:38 -0400 Subject: [PATCH 024/118] workflow/semver-auto: rebase PR When testing if a PR is API backward compatible or not, we need to test against the base branch, not the head against the PR branched is based on. Otherwise it can lead to the case where a breaking change was merged after that a PR was proposed, go-apidiff will fail because it'll test the repo against base_ref. The PR needs to be rebased on base_ref so the actual compatibility can be verified. If the PR can't be rebase for any reason, we'll return a failure and add the label `semver:unknown`. (cherry picked from commit 3e0071fcd67b3fb055c7634e1191a704dae8a56e) --- .github/workflows/semver-auto.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index bc5322b7e4..2f8436f0e8 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -12,6 +12,17 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} token: ${{ secrets.GITHUB_TOKEN }} + - uses: peter-evans/rebase@56c359b35ff7ba8426d0fdb842958b35b1db827 + with: + base: ${{ github.base_ref }} + + - name: Add semver:unknown label + if: failure() + uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + labels: semver:unknown + - uses: actions/setup-go@v4 with: go-version: '1' @@ -23,6 +34,7 @@ jobs: semver:patch semver:minor semver:major + semver:unknown github_token: ${{ secrets.GITHUB_TOKEN }} - name: Checking Go API Compatibility From c3db85a60e9acdb28aeab5bcd8d79bad62af8a18 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Fri, 1 Sep 2023 10:31:11 -0400 Subject: [PATCH 025/118] CI: Fix a typo in semver-auto A caracter is missing for the rebase action in git ref. (cherry picked from commit 9e9f560bd9c8534412f1ac6f0585f172a7f6a3f9) --- .github/workflows/semver-auto.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index 2f8436f0e8..e1c770189c 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -12,7 +12,7 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} token: ${{ secrets.GITHUB_TOKEN }} - - uses: peter-evans/rebase@56c359b35ff7ba8426d0fdb842958b35b1db827 + - uses: peter-evans/rebase@56c359b35ff7ba8426d0fdb842958b35b1db8277 with: base: ${{ github.base_ref }} From 0df624b7018020a1af2c87b54dfc5e338eb5efbe Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Fri, 1 Sep 2023 11:08:36 -0400 Subject: [PATCH 026/118] semver-auto: remove labels first Change the tasks order, so we clean semver labels first. This avoids the case when the rebase failed, and we still have the old label, and also the `semver:unknown`, which is confusing. (cherry picked from commit 8534afd5fbdd37c6822f582fc89737caeaa1aad9) --- .github/workflows/semver-auto.yaml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index e1c770189c..4ca90227c0 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -6,6 +6,16 @@ jobs: go-apidiff: runs-on: ubuntu-latest steps: + - name: Remove the semver labels + uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 + with: + labels: | + semver:patch + semver:minor + semver:major + semver:unknown + github_token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v3 with: fetch-depth: 0 @@ -27,16 +37,6 @@ jobs: with: go-version: '1' - - name: Remove the semver label - uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 - with: - labels: | - semver:patch - semver:minor - semver:major - semver:unknown - github_token: ${{ secrets.GITHUB_TOKEN }} - - name: Checking Go API Compatibility id: go-apidiff uses: joelanford/go-apidiff@v0.7.0 From 9841cac733d4566e2792b704058ffd6548cc003f Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Fri, 1 Sep 2023 11:18:31 -0400 Subject: [PATCH 027/118] semver-auto: manual rebase instead of external action I haven't found an action that just runs a rebase without pushing it into the repo. Let's just run `git rebase -i` for now. (cherry picked from commit 510ded837d5ce25911d57dc5a68cdf302e127c6a) --- .github/workflows/semver-auto.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index 4ca90227c0..0cd6080bc5 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -22,9 +22,11 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} token: ${{ secrets.GITHUB_TOKEN }} - - uses: peter-evans/rebase@56c359b35ff7ba8426d0fdb842958b35b1db8277 - with: - base: ${{ github.base_ref }} + - name: Rebase the PR against origin/github.base_ref to ensure actual API compatibility + run: | + git rebase -i origin/${{ github.base_ref }} + env: + GIT_SEQUENCE_EDITOR: '/usr/bin/true' - name: Add semver:unknown label if: failure() From a0dde2411d273a7be321839a932d9b528375f57c Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Tue, 5 Sep 2023 10:53:02 -0400 Subject: [PATCH 028/118] semver-auto: tell who we are during rebase To avoid the `*** Please tell me who you are` error when a PR is locally rebased to find out which semver label to apply, let's just set fake user.email and user.name, which aren't used anyway since the PR isn't actually rebased, but just for the workflow so we can run `go-apidiff` which itself requires code to be committed. (cherry picked from commit 13358932e257c194233e0e4865b3860b985203f9) --- .github/workflows/semver-auto.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index 0cd6080bc5..2aa66b83fd 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -24,6 +24,8 @@ jobs: - name: Rebase the PR against origin/github.base_ref to ensure actual API compatibility run: | + git config --global user.email "localrebase@gophercloud.io" + git config --global user.name "Local rebase" git rebase -i origin/${{ github.base_ref }} env: GIT_SEQUENCE_EDITOR: '/usr/bin/true' From 0297174d63057fa26c13077b648c077f38402b44 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Fri, 8 Sep 2023 12:26:13 +0200 Subject: [PATCH 029/118] Fix typos in comments --- openstack/imageservice/v2/images/results.go | 2 +- openstack/keymanager/v1/secrets/results.go | 22 +++++++++---------- .../v2/extensions/qos/ruletypes/doc.go | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/openstack/imageservice/v2/images/results.go b/openstack/imageservice/v2/images/results.go index 1b27a15495..96fd91a2ca 100644 --- a/openstack/imageservice/v2/images/results.go +++ b/openstack/imageservice/v2/images/results.go @@ -76,7 +76,7 @@ type Image struct { CreatedAt time.Time `json:"created_at"` // UpdatedAt is the date when the last change has been made to the image or - // it's properties. + // its properties. UpdatedAt time.Time `json:"updated_at"` // File is the trailing path after the glance endpoint that represent the diff --git a/openstack/keymanager/v1/secrets/results.go b/openstack/keymanager/v1/secrets/results.go index f76b977520..46e6860098 100644 --- a/openstack/keymanager/v1/secrets/results.go +++ b/openstack/keymanager/v1/secrets/results.go @@ -93,14 +93,14 @@ type CreateResult struct { commonResult } -// UpdateResult is the response from an Update operation. Call its ExtractErr to -// determine if the request succeeded or failed. +// UpdateResult is the response from an Update operation. Call its ExtractErr +// method to determine if the request succeeded or failed. type UpdateResult struct { gophercloud.ErrResult } -// DeleteResult is the response from a Delete operation. Call its ExtractErr to -// determine if the request succeeded or failed. +// DeleteResult is the response from a Delete operation. Call its ExtractErr +// method to determine if the request succeeded or failed. type DeleteResult struct { gophercloud.ErrResult } @@ -112,11 +112,11 @@ type PayloadResult struct { Body io.ReadCloser } -// Extract is a function that takes a PayloadResult's io.Reader body -// and reads all available data into a slice of bytes. Please be aware that due -// to the nature of io.Reader is forward-only - meaning that it can only be read -// once and not rewound. You can recreate a reader from the output of this -// function by using bytes.NewReader(downloadBytes) +// Extract is a method that takes a PayloadResult's io.Reader body and reads +// all available data into a slice of bytes. Please be aware that its io.Reader +// is forward-only - meaning that it can only be read once and not rewound. You +// can recreate a reader from the output of this function by using +// bytes.NewReader(downloadBytes) func (r PayloadResult) Extract() ([]byte, error) { if r.Err != nil { return nil, r.Err @@ -215,7 +215,7 @@ func (r MetadatumResult) Extract() (*Metadatum, error) { } // MetadatumCreateResult is the response from a metadata Create operation. Call -// it's ExtractErr to determine if the request succeeded or failed. +// its ExtractErr method to determine if the request succeeded or failed. // // NOTE: This could be a MetadatumResponse but, at the time of testing, it looks // like Barbican was returning errneous JSON in the response. @@ -224,7 +224,7 @@ type MetadatumCreateResult struct { } // MetadatumDeleteResult is the response from a metadatum Delete operation. Call -// its ExtractErr to determine if the request succeeded or failed. +// its ExtractErr method to determine if the request succeeded or failed. type MetadatumDeleteResult struct { gophercloud.ErrResult } diff --git a/openstack/networking/v2/extensions/qos/ruletypes/doc.go b/openstack/networking/v2/extensions/qos/ruletypes/doc.go index c36081b485..e87efd96bd 100644 --- a/openstack/networking/v2/extensions/qos/ruletypes/doc.go +++ b/openstack/networking/v2/extensions/qos/ruletypes/doc.go @@ -15,7 +15,7 @@ Example of Listing QoS rule types fmt.Printf("%v <- Rule Types\n", rules) -Example of Getting a single QoS rule type by it's name +Example of Getting a single QoS rule type by name ruleTypeName := "bandwidth_limit" From b47ab2f753052aa4a1dbf58260a6f35fdf6444b4 Mon Sep 17 00:00:00 2001 From: Matt Pryor Date: Thu, 14 Sep 2023 13:59:06 +0100 Subject: [PATCH 030/118] Add tag field to compute block_device_v2 (cherry picked from commit 0e644e48ef6d1c4ce759755884073147e15a1957) --- openstack/compute/v2/extensions/bootfromvolume/requests.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openstack/compute/v2/extensions/bootfromvolume/requests.go b/openstack/compute/v2/extensions/bootfromvolume/requests.go index 096d8be7ef..17f11b3849 100644 --- a/openstack/compute/v2/extensions/bootfromvolume/requests.go +++ b/openstack/compute/v2/extensions/bootfromvolume/requests.go @@ -79,6 +79,12 @@ type BlockDevice struct { // VolumeType is the volume type of the block device. // This requires Compute API microversion 2.67 or later. VolumeType string `json:"volume_type,omitempty"` + + // Tag is an arbitrary string that can be applied to a block device. + // Information about the device tags can be obtained from the metadata API + // and the config drive, allowing devices to be easily identified. + // This requires Compute API microversion 2.42 or later. + Tag string `json:"tag,omitempty"` } // CreateOptsExt is a structure that extends the server `CreateOpts` structure From 18940e4f5669af377b35258f871b06e437849254 Mon Sep 17 00:00:00 2001 From: Matt Pryor Date: Thu, 14 Sep 2023 15:19:35 +0100 Subject: [PATCH 031/118] Add requests test for new field (cherry picked from commit f218ca0823da721823870bb0c8cdb26302924326) --- .../bootfromvolume/testing/fixtures.go | 50 +++++++++++++++++++ .../bootfromvolume/testing/requests_test.go | 6 +++ 2 files changed, 56 insertions(+) diff --git a/openstack/compute/v2/extensions/bootfromvolume/testing/fixtures.go b/openstack/compute/v2/extensions/bootfromvolume/testing/fixtures.go index cb89173aaa..39b09c7fe7 100644 --- a/openstack/compute/v2/extensions/bootfromvolume/testing/fixtures.go +++ b/openstack/compute/v2/extensions/bootfromvolume/testing/fixtures.go @@ -308,3 +308,53 @@ var NewVolumeTypeRequest = bootfromvolume.CreateOptsExt{ }, }, } + +const ExpectedImageAndExistingVolumeWithTagRequest = ` +{ + "server": { + "name": "createdserver", + "imageRef": "asdfasdfasdf", + "flavorRef": "performance1-1", + "block_device_mapping_v2":[ + { + "boot_index": 0, + "delete_on_termination": true, + "destination_type":"local", + "source_type":"image", + "uuid":"asdfasdfasdf" + }, + { + "boot_index": -1, + "delete_on_termination": true, + "destination_type":"volume", + "source_type":"volume", + "tag": "volume-tag", + "uuid":"123456", + "volume_size": 1 + } + ] + } +} +` + +var ImageAndExistingVolumeWithTagRequest = bootfromvolume.CreateOptsExt{ + CreateOptsBuilder: BaseCreateOptsWithImageRef, + BlockDevice: []bootfromvolume.BlockDevice{ + { + BootIndex: 0, + DeleteOnTermination: true, + DestinationType: bootfromvolume.DestinationLocal, + SourceType: bootfromvolume.SourceImage, + UUID: "asdfasdfasdf", + }, + { + BootIndex: -1, + DeleteOnTermination: true, + DestinationType: bootfromvolume.DestinationVolume, + SourceType: bootfromvolume.SourceVolume, + Tag: "volume-tag", + UUID: "123456", + VolumeSize: 1, + }, + }, +} diff --git a/openstack/compute/v2/extensions/bootfromvolume/testing/requests_test.go b/openstack/compute/v2/extensions/bootfromvolume/testing/requests_test.go index 69afc865c9..22d11cc823 100644 --- a/openstack/compute/v2/extensions/bootfromvolume/testing/requests_test.go +++ b/openstack/compute/v2/extensions/bootfromvolume/testing/requests_test.go @@ -47,3 +47,9 @@ func TestBootFromNewVolumeType(t *testing.T) { th.AssertNoErr(t, err) th.CheckJSONEquals(t, ExpectedNewVolumeTypeRequest, actual) } + +func TestAttachExistingVolumeWithTag(t *testing.T) { + actual, err := ImageAndExistingVolumeWithTagRequest.ToServerCreateMap() + th.AssertNoErr(t, err) + th.CheckJSONEquals(t, ExpectedImageAndExistingVolumeWithTagRequest, actual) +} From 9fc151e76705ed899895f4297f8ddf25dd30b237 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Wed, 20 Sep 2023 13:37:15 -0400 Subject: [PATCH 032/118] acceptance/compute: remove flavor ID check If the client uses a microversion > 2.46, the flavor ID doesn't exist. See https://docs.openstack.org/api-ref/compute/#id30 To avoid complexity when checking the flavor, let's just remove that test. (cherry picked from commit 93e5d0fec756becea90038b5fd3b9354528690e5) --- acceptance/openstack/compute/v2/compute.go | 1 - 1 file changed, 1 deletion(-) diff --git a/acceptance/openstack/compute/v2/compute.go b/acceptance/openstack/compute/v2/compute.go index c34a5f5774..7a5c696e68 100644 --- a/acceptance/openstack/compute/v2/compute.go +++ b/acceptance/openstack/compute/v2/compute.go @@ -178,7 +178,6 @@ func CreateBootableVolumeServer(t *testing.T, client *gophercloud.ServiceClient, } th.AssertEquals(t, newServer.Name, name) - th.AssertEquals(t, newServer.Flavor["id"], choices.FlavorID) return newServer, nil } From 4ecebfb2c350809da019765c3dc0caf4a5ccd9ec Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Wed, 20 Sep 2023 11:06:50 -0400 Subject: [PATCH 033/118] Add acceptance tests for tag field to compute block_device_v2 (cherry picked from commit 4fd4c99bff16eca3cdbeae1ec01af260e77aac3f) --- acceptance/openstack/compute/v2/bootfromvolume_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/acceptance/openstack/compute/v2/bootfromvolume_test.go b/acceptance/openstack/compute/v2/bootfromvolume_test.go index 9980660463..3296c84627 100644 --- a/acceptance/openstack/compute/v2/bootfromvolume_test.go +++ b/acceptance/openstack/compute/v2/bootfromvolume_test.go @@ -51,6 +51,11 @@ func TestBootFromNewVolume(t *testing.T) { choices, err := clients.AcceptanceTestChoicesFromEnv() th.AssertNoErr(t, err) + // minimum required microversion for getting volume tags is 2.70 + // https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id64 + client.Microversion = "2.70" + + tagName := "tag1" blockDevices := []bootfromvolume.BlockDevice{ { DeleteOnTermination: true, @@ -58,6 +63,7 @@ func TestBootFromNewVolume(t *testing.T) { SourceType: bootfromvolume.SourceImage, UUID: choices.ImageID, VolumeSize: 2, + Tag: tagName, }, } @@ -73,6 +79,8 @@ func TestBootFromNewVolume(t *testing.T) { tools.PrintResource(t, server) tools.PrintResource(t, attachments) + attachmentTag := *attachments[0].Tag + th.AssertEquals(t, attachmentTag, tagName) if server.Image != nil { t.Fatalf("server image should be nil") From 7eb68c102c4b392c0e58cdf48cf8699a3a80c265 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Thu, 7 Sep 2023 15:23:01 -0400 Subject: [PATCH 034/118] acceptance/volumeattachment: don't specify Connector With `lioadm` being the recommended iscsi helper, we need a real IQN; not a fake one. Let's just not specify the connector. Related #2768 (cherry picked from commit 440873f734970a2a19669f19af999977df1e91ae) --- .../blockstorage/v3/volumeattachments.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/acceptance/openstack/blockstorage/v3/volumeattachments.go b/acceptance/openstack/blockstorage/v3/volumeattachments.go index 510b6841ca..87eb0d92bd 100644 --- a/acceptance/openstack/blockstorage/v3/volumeattachments.go +++ b/acceptance/openstack/blockstorage/v3/volumeattachments.go @@ -20,10 +20,6 @@ func CreateVolumeAttachment(t *testing.T, client *gophercloud.ServiceClient, vol attachOpts := &attachments.CreateOpts{ VolumeUUID: volume.ID, InstanceUUID: server.ID, - Connector: map[string]interface{}{ - "mode": "rw", - "initiator": "fake", - }, } t.Logf("Attempting to attach volume %s to server %s", volume.ID, server.ID) @@ -56,20 +52,6 @@ func CreateVolumeAttachment(t *testing.T, client *gophercloud.ServiceClient, vol return err } - /* - // Not clear how perform a proper update, OpenStack returns "Unable to update the attachment." - updateOpts := &attachments.UpdateOpts{ - Connector: map[string]interface{}{ - "mode": "ro", - "initiator": "fake", - }, - } - attachment, err = attachments.Update(client, attachment.ID, updateOpts).Extract() - if err != nil { - return err - } - */ - listOpts := &attachments.ListOpts{ VolumeID: volume.ID, InstanceID: server.ID, From dafbcd8d30c77e31f43570821e5ff2abca75b365 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Thu, 7 Sep 2023 09:17:33 -0400 Subject: [PATCH 035/118] ci/functional: switch LIO target instead of tgt tgt has been broken for some time in the upstream CI and we were told by Cinder devs to use lioadm for the helper. Let's switch to it for more stable jobs. (cherry picked from commit f4ed08af2924655f97c7f4eeca5269ea5fa1a0fc) --- .github/workflows/functional-blockstorage.yaml | 2 +- .github/workflows/functional-compute.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index 4dfd04de59..e3cd9adf9b 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -37,7 +37,7 @@ jobs: with: branch: ${{ matrix.openstack_version }} conf_overrides: | - CINDER_ISCSI_HELPER=tgtadm + CINDER_ISCSI_HELPER=lioadm enabled_services: 's-account,s-container,s-object,s-proxy,c-bak' - name: Checkout go uses: actions/setup-go@v4 diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index 99448f7e48..d12512ec0d 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -37,7 +37,7 @@ jobs: with: branch: ${{ matrix.openstack_version }} conf_overrides: | - CINDER_ISCSI_HELPER=tgtadm + CINDER_ISCSI_HELPER=lioadm - name: Checkout go uses: actions/setup-go@v4 with: From a96ae3df2f10151162246b5f8873735bce5d7f8b Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Tue, 5 Sep 2023 22:06:24 -0400 Subject: [PATCH 036/118] ci/functional: add `antelope` release in the matrix (cherry picked from commit 4abe682d402735186fed3f084d7289655f59824b) --- .github/workflows/functional-baremetal.yaml | 3 +++ .github/workflows/functional-basic.yaml | 3 +++ .github/workflows/functional-blockstorage.yaml | 3 +++ .github/workflows/functional-clustering.yaml | 3 +++ .github/workflows/functional-compute.yaml | 3 +++ .github/workflows/functional-containerinfra.yaml | 3 +++ .github/workflows/functional-dns.yaml | 3 +++ .github/workflows/functional-identity.yaml | 3 +++ .github/workflows/functional-imageservice.yaml | 3 +++ .github/workflows/functional-keymanager.yaml | 3 +++ .github/workflows/functional-loadbalancer.yaml | 3 +++ .github/workflows/functional-messaging.yaml | 3 +++ .github/workflows/functional-networking.yaml | 3 +++ .github/workflows/functional-objectstorage.yaml | 3 +++ .github/workflows/functional-orchestration.yaml | 3 +++ .github/workflows/functional-placement.yaml | 3 +++ .github/workflows/functional-sharedfilesystems.yaml | 3 +++ 17 files changed, 51 insertions(+) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index 277245d1c6..e3a55ad4f6 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["20.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index 982e006151..93f412f346 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -15,6 +15,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["20.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index e3cd9adf9b..ed6fb9187f 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["20.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-clustering.yaml b/.github/workflows/functional-clustering.yaml index fa9a8a5a46..3a08f8b1d6 100644 --- a/.github/workflows/functional-clustering.yaml +++ b/.github/workflows/functional-clustering.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index d12512ec0d..15ab332bd2 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["20.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index 9dbd8dc5da..6332af01ec 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -14,6 +14,9 @@ jobs: ubuntu_version: "20.04" devstack_conf_overrides: | enable_plugin magnum https://github.com/openstack/magnum master + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index a14e0fbf02..dcca8b4c54 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -15,6 +15,9 @@ jobs: ubuntu_version: "20.04" devstack_conf_overrides: | enable_plugin designate https://github.com/openstack/designate master + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml index df0764beb0..ee510977ae 100644 --- a/.github/workflows/functional-identity.yaml +++ b/.github/workflows/functional-identity.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["20.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-imageservice.yaml b/.github/workflows/functional-imageservice.yaml index 77ee23bad4..18bb18ae63 100644 --- a/.github/workflows/functional-imageservice.yaml +++ b/.github/workflows/functional-imageservice.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["20.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml index 42f097c655..9865935091 100644 --- a/.github/workflows/functional-keymanager.yaml +++ b/.github/workflows/functional-keymanager.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["20.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml index 0b8cc40f6b..142f8f10a4 100644 --- a/.github/workflows/functional-loadbalancer.yaml +++ b/.github/workflows/functional-loadbalancer.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["20.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml index 8314a1b496..0fcf3c0c35 100644 --- a/.github/workflows/functional-messaging.yaml +++ b/.github/workflows/functional-messaging.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index feca87453b..f8cb132a16 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -15,6 +15,9 @@ jobs: devstack_conf_overrides: | enable_plugin neutron-dynamic-routing https://github.com/openstack/neutron-dynamic-routing master enable_plugin neutron-vpnaas https://github.com/openstack/neutron-vpnaas master + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml index 125a7add35..1625993a34 100644 --- a/.github/workflows/functional-objectstorage.yaml +++ b/.github/workflows/functional-objectstorage.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["20.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml index 90391c4520..730c40f79b 100644 --- a/.github/workflows/functional-orchestration.yaml +++ b/.github/workflows/functional-orchestration.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["20.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml index 71b24efcce..02422329e7 100644 --- a/.github/workflows/functional-placement.yaml +++ b/.github/workflows/functional-placement.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["20.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml index 7d552435ef..5bf6f0b633 100644 --- a/.github/workflows/functional-sharedfilesystems.yaml +++ b/.github/workflows/functional-sharedfilesystems.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["20.04"] include: + - name: "antelope" + openstack_version: "stable/2023.1" + ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" From 8126d0a86c7abf14c0db94d51775da62f967c47d Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Tue, 5 Sep 2023 22:12:47 -0400 Subject: [PATCH 037/118] ci/functional: reduce LOC (cherry picked from commit e2a497e0624bf79d844ea5e3c6717fbb2982891c) --- .../workflows/functional-containerinfra.yaml | 14 +------------ .github/workflows/functional-dns.yaml | 14 +------------ .github/workflows/functional-networking.yaml | 21 ++----------------- 3 files changed, 4 insertions(+), 45 deletions(-) diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index 6332af01ec..a9d7f078dd 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -12,36 +12,24 @@ jobs: - name: "master" openstack_version: "master" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin magnum https://github.com/openstack/magnum master - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin magnum https://github.com/openstack/magnum stable/zed - name: "yoga" openstack_version: "stable/yoga" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin magnum https://github.com/openstack/magnum stable/yoga - name: "xena" openstack_version: "stable/xena" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin magnum https://github.com/openstack/magnum stable/xena - name: "wallaby" openstack_version: "stable/wallaby" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin magnum https://github.com/openstack/magnum stable/wallaby - name: "victoria" openstack_version: "stable/victoria" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin magnum https://github.com/openstack/magnum stable/victoria runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Magnum and run containerinfra acceptance tests steps: @@ -52,13 +40,13 @@ jobs: with: branch: ${{ matrix.openstack_version }} conf_overrides: | + enable_plugin magnum https://github.com/openstack/magnum ${{ matrix.openstack_version }} enable_plugin barbican https://github.com/openstack/barbican ${{ matrix.openstack_version }} enable_plugin heat https://github.com/openstack/heat ${{ matrix.openstack_version }} GLANCE_LIMIT_IMAGE_SIZE_TOTAL=5000 SWIFT_MAX_FILE_SIZE=5368709122 KEYSTONE_ADMIN_ENDPOINT=true MAGNUMCLIENT_BRANCH=${{ matrix.openstack_version }} - ${{ matrix.devstack_conf_overrides }} enabled_services: 'h-eng,h-api,h-api-cfn,h-api-cw' - name: Checkout go uses: actions/setup-go@v4 diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index dcca8b4c54..ae9bac3cd1 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -13,36 +13,24 @@ jobs: - name: "master" openstack_version: "master" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin designate https://github.com/openstack/designate master - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin designate https://github.com/openstack/designate stable/zed - name: "yoga" openstack_version: "stable/yoga" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin designate https://github.com/openstack/designate stable/yoga - name: "xena" openstack_version: "stable/xena" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin designate https://github.com/openstack/designate stable/xena - name: "wallaby" openstack_version: "stable/wallaby" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin designate https://github.com/openstack/designate stable/wallaby - name: "victoria" openstack_version: "stable/victoria" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin designate https://github.com/openstack/designate stable/victoria runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Designate and run dns acceptance tests steps: @@ -53,7 +41,7 @@ jobs: with: branch: ${{ matrix.openstack_version }} conf_overrides: | - ${{ matrix.devstack_conf_overrides }} + enable_plugin designate https://github.com/openstack/designate ${{ matrix.openstack_version }} enabled_services: 'designate,designate-central,designate-api,designate-worker,designate-producer,designate-mdns' - name: Checkout go uses: actions/setup-go@v4 diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index f8cb132a16..5531ee926c 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -12,42 +12,24 @@ jobs: - name: "master" openstack_version: "master" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin neutron-dynamic-routing https://github.com/openstack/neutron-dynamic-routing master - enable_plugin neutron-vpnaas https://github.com/openstack/neutron-vpnaas master - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin neutron-dynamic-routing https://github.com/openstack/neutron-dynamic-routing stable/zed - enable_plugin neutron-vpnaas https://github.com/openstack/neutron-vpnaas stable/zed - name: "yoga" openstack_version: "stable/yoga" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin neutron-dynamic-routing https://github.com/openstack/neutron-dynamic-routing stable/yoga - enable_plugin neutron-vpnaas https://github.com/openstack/neutron-vpnaas stable/yoga - name: "xena" openstack_version: "stable/xena" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin neutron-dynamic-routing https://github.com/openstack/neutron-dynamic-routing stable/xena - enable_plugin neutron-vpnaas https://github.com/openstack/neutron-vpnaas stable/xena - name: "wallaby" openstack_version: "stable/wallaby" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin neutron-dynamic-routing https://github.com/openstack/neutron-dynamic-routing stable/wallaby - enable_plugin neutron-vpnaas https://github.com/openstack/neutron-vpnaas stable/wallaby - name: "victoria" openstack_version: "stable/victoria" ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin neutron-dynamic-routing https://github.com/openstack/neutron-dynamic-routing stable/victoria - enable_plugin neutron-vpnaas https://github.com/openstack/neutron-vpnaas stable/victoria runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Neutron and run networking acceptance tests steps: @@ -58,8 +40,9 @@ jobs: with: branch: ${{ matrix.openstack_version }} conf_overrides: | + enable_plugin neutron-dynamic-routing https://github.com/openstack/neutron-dynamic-routing ${{ matrix.openstack_version }} + enable_plugin neutron-vpnaas https://github.com/openstack/neutron-vpnaas ${{ matrix.openstack_version }} Q_ML2_PLUGIN_EXT_DRIVERS=qos,port_security,dns_domain_keywords - ${{ matrix.devstack_conf_overrides }} enabled_services: 'neutron-dns,neutron-qos,neutron-segments,neutron-trunk,neutron-uplink-status-propagation,neutron-network-segment-range,neutron-port-forwarding' - name: Checkout go uses: actions/setup-go@v4 From 5ac547f223590bac9a490027c3b8d110a4f9e91b Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Tue, 5 Sep 2023 16:11:35 -0400 Subject: [PATCH 038/118] ci/functional: switch master jobs to run on ubuntu 22.04 Since https://github.com/openstack/devstack/commit/427a4e1a9b7f20a8be0ad5091f2229945ce711a8 We don't support focal anymore in devstack-master. We need to run 22.04 from now. Note: some workflows already had it right but it wasn't consistent across all services. (cherry picked from commit 9a8b0de0519b455afaf88ee38ee66f5babf8e3cf) --- .github/workflows/functional-baremetal.yaml | 2 +- .github/workflows/functional-basic.yaml | 2 +- .github/workflows/functional-blockstorage.yaml | 2 +- .github/workflows/functional-compute.yaml | 2 +- .github/workflows/functional-containerinfra.yaml | 2 +- .github/workflows/functional-dns.yaml | 2 +- .github/workflows/functional-identity.yaml | 2 +- .github/workflows/functional-imageservice.yaml | 2 +- .github/workflows/functional-keymanager.yaml | 2 +- .github/workflows/functional-loadbalancer.yaml | 2 +- .github/workflows/functional-networking.yaml | 2 +- .github/workflows/functional-objectstorage.yaml | 2 +- .github/workflows/functional-orchestration.yaml | 2 +- .github/workflows/functional-placement.yaml | 2 +- .github/workflows/functional-sharedfilesystems.yaml | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index e3a55ad4f6..5002c08be0 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -10,7 +10,7 @@ jobs: matrix: name: ["master"] openstack_version: ["master"] - ubuntu_version: ["20.04"] + ubuntu_version: ["22.04"] include: - name: "antelope" openstack_version: "stable/2023.1" diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index 93f412f346..17225e1e5f 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -13,7 +13,7 @@ jobs: matrix: name: ["master"] openstack_version: ["master"] - ubuntu_version: ["20.04"] + ubuntu_version: ["22.04"] include: - name: "antelope" openstack_version: "stable/2023.1" diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index ed6fb9187f..4b8f69133e 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -10,7 +10,7 @@ jobs: matrix: name: ["master"] openstack_version: ["master"] - ubuntu_version: ["20.04"] + ubuntu_version: ["22.04"] include: - name: "antelope" openstack_version: "stable/2023.1" diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index 15ab332bd2..65311bce6e 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -10,7 +10,7 @@ jobs: matrix: name: ["master"] openstack_version: ["master"] - ubuntu_version: ["20.04"] + ubuntu_version: ["22.04"] include: - name: "antelope" openstack_version: "stable/2023.1" diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index a9d7f078dd..cbdbb5cce1 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -11,7 +11,7 @@ jobs: include: - name: "master" openstack_version: "master" - ubuntu_version: "20.04" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index ae9bac3cd1..e332d273ae 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -12,7 +12,7 @@ jobs: include: - name: "master" openstack_version: "master" - ubuntu_version: "20.04" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml index ee510977ae..3170e41e06 100644 --- a/.github/workflows/functional-identity.yaml +++ b/.github/workflows/functional-identity.yaml @@ -10,7 +10,7 @@ jobs: matrix: name: ["master"] openstack_version: ["master"] - ubuntu_version: ["20.04"] + ubuntu_version: ["22.04"] include: - name: "antelope" openstack_version: "stable/2023.1" diff --git a/.github/workflows/functional-imageservice.yaml b/.github/workflows/functional-imageservice.yaml index 18bb18ae63..744ee93a05 100644 --- a/.github/workflows/functional-imageservice.yaml +++ b/.github/workflows/functional-imageservice.yaml @@ -10,7 +10,7 @@ jobs: matrix: name: ["master"] openstack_version: ["master"] - ubuntu_version: ["20.04"] + ubuntu_version: ["22.04"] include: - name: "antelope" openstack_version: "stable/2023.1" diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml index 9865935091..8d72e06a60 100644 --- a/.github/workflows/functional-keymanager.yaml +++ b/.github/workflows/functional-keymanager.yaml @@ -10,7 +10,7 @@ jobs: matrix: name: ["master"] openstack_version: ["master"] - ubuntu_version: ["20.04"] + ubuntu_version: ["22.04"] include: - name: "antelope" openstack_version: "stable/2023.1" diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml index 142f8f10a4..9af476b3a5 100644 --- a/.github/workflows/functional-loadbalancer.yaml +++ b/.github/workflows/functional-loadbalancer.yaml @@ -10,7 +10,7 @@ jobs: matrix: name: ["master"] openstack_version: ["master"] - ubuntu_version: ["20.04"] + ubuntu_version: ["22.04"] include: - name: "antelope" openstack_version: "stable/2023.1" diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index 5531ee926c..0a33e5787c 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -11,7 +11,7 @@ jobs: include: - name: "master" openstack_version: "master" - ubuntu_version: "20.04" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml index 1625993a34..bf7e4f5b6f 100644 --- a/.github/workflows/functional-objectstorage.yaml +++ b/.github/workflows/functional-objectstorage.yaml @@ -10,7 +10,7 @@ jobs: matrix: name: ["master"] openstack_version: ["master"] - ubuntu_version: ["20.04"] + ubuntu_version: ["22.04"] include: - name: "antelope" openstack_version: "stable/2023.1" diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml index 730c40f79b..5f81b3e733 100644 --- a/.github/workflows/functional-orchestration.yaml +++ b/.github/workflows/functional-orchestration.yaml @@ -10,7 +10,7 @@ jobs: matrix: name: ["master"] openstack_version: ["master"] - ubuntu_version: ["20.04"] + ubuntu_version: ["22.04"] include: - name: "antelope" openstack_version: "stable/2023.1" diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml index 02422329e7..a7efecdd24 100644 --- a/.github/workflows/functional-placement.yaml +++ b/.github/workflows/functional-placement.yaml @@ -10,7 +10,7 @@ jobs: matrix: name: ["master"] openstack_version: ["master"] - ubuntu_version: ["20.04"] + ubuntu_version: ["22.04"] include: - name: "antelope" openstack_version: "stable/2023.1" diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml index 5bf6f0b633..48acec333e 100644 --- a/.github/workflows/functional-sharedfilesystems.yaml +++ b/.github/workflows/functional-sharedfilesystems.yaml @@ -10,7 +10,7 @@ jobs: matrix: name: ["master"] openstack_version: ["master"] - ubuntu_version: ["20.04"] + ubuntu_version: ["22.04"] include: - name: "antelope" openstack_version: "stable/2023.1" From 2aab79dd3a0fd19082f9f211f126ee86c17652fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Thu, 7 Sep 2023 15:06:57 +0200 Subject: [PATCH 039/118] Acceptance: Rename IsReleasesBelow() and IsReleasesAbove() Rename to IsCurrentBelow() and IsCurrentAbove() respectively. --- acceptance/clients/conditions.go | 12 ++++++------ acceptance/openstack/loadbalancer/v2/loadbalancer.go | 2 +- acceptance/openstack/loadbalancer/v2/quotas_test.go | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/acceptance/clients/conditions.go b/acceptance/clients/conditions.go index 44522c2308..6308eaeac6 100644 --- a/acceptance/clients/conditions.go +++ b/acceptance/clients/conditions.go @@ -111,7 +111,7 @@ func SkipRelease(t *testing.T, release string) { func SkipReleasesBelow(t *testing.T, release string) { current_branch := getReleaseFromEnv(t) - if IsReleasesBelow(t, release) { + if IsCurrentBelow(t, release) { t.Skipf("this is not supported below %s, testing in %s", release, current_branch) } } @@ -123,15 +123,15 @@ func SkipReleasesAbove(t *testing.T, release string) { current_branch := getReleaseFromEnv(t) // Assume master is always too new - if IsReleasesAbove(t, release) { + if IsCurrentAbove(t, release) { t.Skipf("this is not supported above %s, testing in %s", release, current_branch) } } -// IsReleasesAbove will return true on releases above a certain +// IsCurrentAbove will return true on releases above a certain // one. The result is always true on master release. Releases are named such // as 'stable/mitaka', master, etc. -func IsReleasesAbove(t *testing.T, release string) bool { +func IsCurrentAbove(t *testing.T, release string) bool { current_branch := getReleaseFromEnv(t) // Assume master is always too new @@ -142,9 +142,9 @@ func IsReleasesAbove(t *testing.T, release string) bool { return false } -// IsReleasesBelow will return true on releases below a certain +// IsCurrentBelow will return true on releases below a certain // one. Releases are named such as 'stable/mitaka', master, etc. -func IsReleasesBelow(t *testing.T, release string) bool { +func IsCurrentBelow(t *testing.T, release string) bool { current_branch := getReleaseFromEnv(t) if current_branch != "master" || current_branch < release { diff --git a/acceptance/openstack/loadbalancer/v2/loadbalancer.go b/acceptance/openstack/loadbalancer/v2/loadbalancer.go index 8d5efb011d..eb11d68c17 100644 --- a/acceptance/openstack/loadbalancer/v2/loadbalancer.go +++ b/acceptance/openstack/loadbalancer/v2/loadbalancer.go @@ -71,7 +71,7 @@ func CreateListenerHTTP(t *testing.T, client *gophercloud.ServiceClient, lb *loa } // tls_version is only supported in microversion v2.17 introduced in victoria - if clients.IsReleasesAbove(t, "stable/ussuri") { + if clients.IsCurrentAbove(t, "stable/ussuri") { tlsVersions = []listeners.TLSVersion{"TLSv1.2", "TLSv1.3"} tlsVersionsExp = []string{"TLSv1.2", "TLSv1.3"} } diff --git a/acceptance/openstack/loadbalancer/v2/quotas_test.go b/acceptance/openstack/loadbalancer/v2/quotas_test.go index 4e174642c4..35dcb2e54a 100644 --- a/acceptance/openstack/loadbalancer/v2/quotas_test.go +++ b/acceptance/openstack/loadbalancer/v2/quotas_test.go @@ -45,7 +45,7 @@ func TestQuotasUpdate(t *testing.T) { Healthmonitor: gophercloud.IntToPointer(5), } // L7 parameters are only supported in microversion v2.19 introduced in victoria - if clients.IsReleasesAbove(t, "stable/ussuri") { + if clients.IsCurrentAbove(t, "stable/ussuri") { quotaUpdateOpts.L7Policy = gophercloud.IntToPointer(55) quotaUpdateOpts.L7Rule = gophercloud.IntToPointer(105) } @@ -67,7 +67,7 @@ func TestQuotasUpdate(t *testing.T) { Healthmonitor: &originalQuotas.Healthmonitor, } // L7 parameters are only supported in microversion v2.19 introduced in victoria - if clients.IsReleasesAbove(t, "stable/ussuri") { + if clients.IsCurrentAbove(t, "stable/ussuri") { restoredQuotaUpdate.L7Policy = &originalQuotas.L7Policy restoredQuotaUpdate.L7Rule = &originalQuotas.L7Rule } From e5568fea158497f6b34714d2cead81d2b96ce15a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Thu, 7 Sep 2023 18:07:51 +0200 Subject: [PATCH 040/118] Acceptance: Fix IsCurrentBelow and IsCurrentAbove functions Take into account numerical release names, after zed, and ensure that comparing the same version always yields false. --- acceptance/clients/conditions.go | 73 +++++++++++++------ acceptance/clients/testing/conditions_test.go | 65 +++++++++++++++++ 2 files changed, 115 insertions(+), 23 deletions(-) create mode 100644 acceptance/clients/testing/conditions_test.go diff --git a/acceptance/clients/conditions.go b/acceptance/clients/conditions.go index 6308eaeac6..a1239a1ba7 100644 --- a/acceptance/clients/conditions.go +++ b/acceptance/clients/conditions.go @@ -2,6 +2,8 @@ package clients import ( "os" + "strconv" + "strings" "testing" ) @@ -90,18 +92,18 @@ func RequireIronicHTTPBasic(t *testing.T) { } func getReleaseFromEnv(t *testing.T) string { - current_branch := os.Getenv("OS_BRANCH") - if current_branch == "" { + current := strings.TrimPrefix(os.Getenv("OS_BRANCH"), "stable/") + if current == "" { t.Fatal("this test requires OS_BRANCH to be set but it wasn't") } - return current_branch + return current } // SkipRelease will have the test be skipped on a certain // release. Releases are named such as 'stable/mitaka', master, etc. func SkipRelease(t *testing.T, release string) { - current_branch := getReleaseFromEnv(t) - if current_branch == release { + current := getReleaseFromEnv(t) + if current == release { t.Skipf("this is not supported in %s", release) } } @@ -109,10 +111,10 @@ func SkipRelease(t *testing.T, release string) { // SkipReleasesBelow will have the test be skipped on releases below a certain // one. Releases are named such as 'stable/mitaka', master, etc. func SkipReleasesBelow(t *testing.T, release string) { - current_branch := getReleaseFromEnv(t) + current := getReleaseFromEnv(t) if IsCurrentBelow(t, release) { - t.Skipf("this is not supported below %s, testing in %s", release, current_branch) + t.Skipf("this is not supported below %s, testing in %s", release, current) } } @@ -120,36 +122,61 @@ func SkipReleasesBelow(t *testing.T, release string) { // one. The test is always skipped on master release. Releases are named such // as 'stable/mitaka', master, etc. func SkipReleasesAbove(t *testing.T, release string) { - current_branch := getReleaseFromEnv(t) + current := getReleaseFromEnv(t) - // Assume master is always too new if IsCurrentAbove(t, release) { - t.Skipf("this is not supported above %s, testing in %s", release, current_branch) + t.Skipf("this is not supported above %s, testing in %s", release, current) } } +func isReleaseNumeral(release string) bool { + _, err := strconv.Atoi(release[0:1]) + return err == nil +} + // IsCurrentAbove will return true on releases above a certain // one. The result is always true on master release. Releases are named such // as 'stable/mitaka', master, etc. func IsCurrentAbove(t *testing.T, release string) bool { - current_branch := getReleaseFromEnv(t) - - // Assume master is always too new - if current_branch == "master" || current_branch > release { - return true - } - t.Logf("Target release %s is below the current branch %s", release, current_branch) + current := getReleaseFromEnv(t) + release = strings.TrimPrefix(release, "stable/") + + if release != "master" { + // Assume master is always too new + if current == "master" { + return true + } + // Numeral releases are always newer than non-numeral ones + if isReleaseNumeral(current) && !isReleaseNumeral(release) { + return true + } + if current > release && !(!isReleaseNumeral(current) && isReleaseNumeral(release)) { + return true + } + } + t.Logf("Target release %s is below the current branch %s", release, current) return false } // IsCurrentBelow will return true on releases below a certain // one. Releases are named such as 'stable/mitaka', master, etc. func IsCurrentBelow(t *testing.T, release string) bool { - current_branch := getReleaseFromEnv(t) - - if current_branch != "master" || current_branch < release { - return true - } - t.Logf("Target release %s is above the current branch %s", release, current_branch) + current := getReleaseFromEnv(t) + release = strings.TrimPrefix(release, "stable/") + + if current != "master" { + // Assume master is always too new + if release == "master" { + return true + } + // Numeral releases are always newer than non-numeral ones + if isReleaseNumeral(release) && !isReleaseNumeral(current) { + return true + } + if release > current && !(!isReleaseNumeral(release) && isReleaseNumeral(current)) { + return true + } + } + t.Logf("Target release %s is above the current branch %s", release, current) return false } diff --git a/acceptance/clients/testing/conditions_test.go b/acceptance/clients/testing/conditions_test.go new file mode 100644 index 0000000000..a9825ea293 --- /dev/null +++ b/acceptance/clients/testing/conditions_test.go @@ -0,0 +1,65 @@ +package testing + +import ( + "fmt" + "os" + "testing" + + "github.com/gophercloud/gophercloud/acceptance/clients" +) + +func TestIsCurrentAbove(t *testing.T) { + cases := []struct { + Current string + Release string + Result bool + }{ + {Current: "master", Release: "zed", Result: true}, + {Current: "master", Release: "2023.1", Result: true}, + {Current: "master", Release: "master", Result: false}, + {Current: "zed", Release: "master", Result: false}, + {Current: "zed", Release: "yoga", Result: true}, + {Current: "zed", Release: "2023.1", Result: false}, + {Current: "2023.1", Release: "2023.1", Result: false}, + {Current: "2023.2", Release: "stable/2023.1", Result: true}, + } + + for _, tt := range cases { + t.Run(fmt.Sprintf("%s above %s", tt.Current, tt.Release), func(t *testing.T) { + os.Setenv("OS_BRANCH", tt.Current) + got := clients.IsCurrentAbove(t, tt.Release) + if got != tt.Result { + t.Errorf("got %v want %v", got, tt.Result) + } + }) + + } +} + +func TestIsCurrentBelow(t *testing.T) { + cases := []struct { + Current string + Release string + Result bool + }{ + {Current: "master", Release: "zed", Result: false}, + {Current: "master", Release: "2023.1", Result: false}, + {Current: "master", Release: "master", Result: false}, + {Current: "zed", Release: "master", Result: true}, + {Current: "zed", Release: "yoga", Result: false}, + {Current: "zed", Release: "2023.1", Result: true}, + {Current: "2023.1", Release: "2023.1", Result: false}, + {Current: "2023.2", Release: "stable/2023.1", Result: false}, + } + + for _, tt := range cases { + t.Run(fmt.Sprintf("%s below %s", tt.Current, tt.Release), func(t *testing.T) { + os.Setenv("OS_BRANCH", tt.Current) + got := clients.IsCurrentBelow(t, tt.Release) + if got != tt.Result { + t.Errorf("got %v want %v", got, tt.Result) + } + }) + + } +} From d7d4aac9a96aec29c746dc80a0a4292c9da3967c Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Thu, 7 Sep 2023 14:22:28 -0400 Subject: [PATCH 041/118] ci/semver-auto: return a failure only when needed When go-apidiff returns semver=major, it returns RC=1 which causes the workflow to return an error while we don't want that, we just want the label to be applied. Instead, let's ignore that error so the label can be set later and add a step to check if an error occured and semver is not major, then it's an actual problem that we should check in the logs (e.g. an issue when running go-apidiff). (cherry picked from commit 12ff5ebd8f619dfb58968234568fb0ff8d14ea71) --- .github/workflows/semver-auto.yaml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index 2aa66b83fd..edc3c6dcf2 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -43,24 +43,33 @@ jobs: - name: Checking Go API Compatibility id: go-apidiff + # if semver=major, this will return RC=1, so let's ignore the failure so label + # can be set later. We check for actual errors in the next step. + continue-on-error: true uses: joelanford/go-apidiff@v0.7.0 + # go-apidiff returns RC=1 when semver=major, which makes the workflow to return + # a failure. Instead let's just return a failure if go-apidiff failed to run. + - name: Return an error if Go API Compatibility couldn't be verified + if: steps.go-apidiff.outcome != 'success' && steps.go-apidiff.semver-type != 'major' + run: exit 1 + - name: Add semver:patch label - if: always() && steps.go-apidiff.outputs.semver-type == 'patch' + if: steps.go-apidiff.outputs.semver-type == 'patch' uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf with: github_token: ${{ secrets.GITHUB_TOKEN }} labels: semver:patch - name: Add semver:minor label - if: always() && steps.go-apidiff.outputs.semver-type == 'minor' + if: steps.go-apidiff.outputs.semver-type == 'minor' uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf with: github_token: ${{ secrets.GITHUB_TOKEN }} labels: semver:minor - name: Add semver:major label - if: always() && steps.go-apidiff.outputs.semver-type == 'major' + if: steps.go-apidiff.outputs.semver-type == 'major' uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf with: github_token: ${{ secrets.GITHUB_TOKEN }} From 27c2a3f1408b6e33e29adea09323a9da5724aeda Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Fri, 8 Sep 2023 09:15:40 -0400 Subject: [PATCH 042/118] Fix semver-auto In my previous commit, I didn't read the output, fixing now. (cherry picked from commit 2999b21e92d1033d01ccc10e5f9b06458dacb450) --- .github/workflows/semver-auto.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index edc3c6dcf2..88a6ca9dc2 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -51,7 +51,7 @@ jobs: # go-apidiff returns RC=1 when semver=major, which makes the workflow to return # a failure. Instead let's just return a failure if go-apidiff failed to run. - name: Return an error if Go API Compatibility couldn't be verified - if: steps.go-apidiff.outcome != 'success' && steps.go-apidiff.semver-type != 'major' + if: steps.go-apidiff.outcome != 'success' && steps.go-apidiff.outputs.semver-type != 'major' run: exit 1 - name: Add semver:patch label From 5871a113d777c53dc5cbe8d98e5fea8fd6eaf8b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Fri, 22 Sep 2023 15:46:35 +0200 Subject: [PATCH 043/118] Make acceptance tests internal Do not expose acceptance tests packages externally. This has the added benefit of go-apidiff no longer reporting false positive when analyzing for backward incompatible changes. --- .github/workflows/functional-basic.yaml | 2 +- {acceptance => internal/acceptance}/README.md | 2 +- {acceptance => internal/acceptance}/clients/clients.go | 0 .../acceptance}/clients/conditions.go | 0 {acceptance => internal/acceptance}/clients/http.go | 0 .../acceptance}/clients/testing/conditions_test.go | 2 +- .../openstack/baremetal/httpbasic/allocations_test.go | 4 ++-- .../acceptance}/openstack/baremetal/httpbasic/doc.go | 0 .../openstack/baremetal/httpbasic/nodes_test.go | 4 ++-- .../openstack/baremetal/httpbasic/ports_test.go | 4 ++-- .../openstack/baremetal/noauth/allocations_test.go | 4 ++-- .../acceptance}/openstack/baremetal/noauth/doc.go | 0 .../openstack/baremetal/noauth/nodes_test.go | 4 ++-- .../openstack/baremetal/noauth/ports_test.go | 4 ++-- .../openstack/baremetal/v1/allocations_test.go | 2 +- .../acceptance}/openstack/baremetal/v1/baremetal.go | 2 +- .../openstack/baremetal/v1/conductors_test.go | 4 ++-- .../acceptance}/openstack/baremetal/v1/nodes_test.go | 2 +- .../acceptance}/openstack/baremetal/v1/ports_test.go | 2 +- .../openstack/blockstorage/apiversions_test.go | 4 ++-- .../openstack/blockstorage/extensions/backups_test.go | 4 ++-- .../openstack/blockstorage/extensions/extensions.go | 2 +- .../openstack/blockstorage/extensions/limits_test.go | 4 ++-- .../openstack/blockstorage/extensions/pkg.go | 0 .../blockstorage/extensions/schedulerhints_test.go | 4 ++-- .../blockstorage/extensions/schedulerstats_test.go | 4 ++-- .../openstack/blockstorage/extensions/services_test.go | 4 ++-- .../blockstorage/extensions/volumeactions_test.go | 10 +++++----- .../blockstorage/extensions/volumetenants_test.go | 4 ++-- .../openstack/blockstorage/noauth/blockstorage.go | 4 ++-- .../openstack/blockstorage/noauth/snapshots_test.go | 4 ++-- .../openstack/blockstorage/noauth/volumes_test.go | 4 ++-- .../openstack/blockstorage/v1/blockstorage.go | 2 +- .../acceptance}/openstack/blockstorage/v1/pkg.go | 0 .../openstack/blockstorage/v1/snapshots_test.go | 4 ++-- .../openstack/blockstorage/v1/volumes_test.go | 4 ++-- .../openstack/blockstorage/v1/volumetypes_test.go | 4 ++-- .../openstack/blockstorage/v2/blockstorage.go | 4 ++-- .../acceptance}/openstack/blockstorage/v2/pkg.go | 0 .../openstack/blockstorage/v2/snapshots_test.go | 4 ++-- .../openstack/blockstorage/v2/volumes_test.go | 4 ++-- .../openstack/blockstorage/v3/blockstorage.go | 2 +- .../acceptance}/openstack/blockstorage/v3/pkg.go | 0 .../acceptance}/openstack/blockstorage/v3/qos_test.go | 4 ++-- .../openstack/blockstorage/v3/quotaset_test.go | 4 ++-- .../openstack/blockstorage/v3/snapshots_test.go | 4 ++-- .../openstack/blockstorage/v3/volumeattachments.go | 0 .../blockstorage/v3/volumeattachments_test.go | 4 ++-- .../openstack/blockstorage/v3/volumes_test.go | 4 ++-- .../openstack/blockstorage/v3/volumetypes_test.go | 6 +++--- .../acceptance}/openstack/client_test.go | 4 ++-- .../openstack/clustering/v1/actions_test.go | 4 ++-- .../acceptance}/openstack/clustering/v1/clustering.go | 4 ++-- .../openstack/clustering/v1/clusters_test.go | 4 ++-- .../acceptance}/openstack/clustering/v1/events_test.go | 4 ++-- .../acceptance}/openstack/clustering/v1/nodes_test.go | 4 ++-- .../acceptance}/openstack/clustering/v1/pkg.go | 0 .../openstack/clustering/v1/policies_test.go | 4 ++-- .../openstack/clustering/v1/policytypes_test.go | 4 ++-- .../openstack/clustering/v1/profiles_test.go | 4 ++-- .../openstack/clustering/v1/profiletypes_test.go | 4 ++-- .../openstack/clustering/v1/receivers_test.go | 4 ++-- .../openstack/clustering/v1/webhooktrigger_test.go | 2 +- .../acceptance}/openstack/common.go | 0 .../openstack/compute/v2/aggregates_test.go | 4 ++-- .../openstack/compute/v2/attachinterfaces_test.go | 4 ++-- .../openstack/compute/v2/availabilityzones_test.go | 4 ++-- .../openstack/compute/v2/bootfromvolume_test.go | 6 +++--- .../acceptance}/openstack/compute/v2/compute.go | 4 ++-- .../openstack/compute/v2/defsecrules_test.go | 4 ++-- .../openstack/compute/v2/diagnostics_test.go | 4 ++-- .../acceptance}/openstack/compute/v2/extension_test.go | 4 ++-- .../acceptance}/openstack/compute/v2/flavors_test.go | 6 +++--- .../openstack/compute/v2/floatingip_test.go | 4 ++-- .../openstack/compute/v2/hypervisors_test.go | 4 ++-- .../acceptance}/openstack/compute/v2/images_test.go | 4 ++-- .../openstack/compute/v2/instance_actions_test.go | 4 ++-- .../acceptance}/openstack/compute/v2/keypairs_test.go | 6 +++--- .../acceptance}/openstack/compute/v2/limits_test.go | 4 ++-- .../acceptance}/openstack/compute/v2/migrate_test.go | 2 +- .../acceptance}/openstack/compute/v2/network_test.go | 4 ++-- .../acceptance}/openstack/compute/v2/pkg.go | 0 .../acceptance}/openstack/compute/v2/quotaset_test.go | 4 ++-- .../openstack/compute/v2/remoteconsoles_test.go | 4 ++-- .../openstack/compute/v2/rescueunrescue_test.go | 2 +- .../acceptance}/openstack/compute/v2/secgroup_test.go | 4 ++-- .../openstack/compute/v2/servergroup_test.go | 4 ++-- .../acceptance}/openstack/compute/v2/servers_test.go | 6 +++--- .../acceptance}/openstack/compute/v2/services_test.go | 4 ++-- .../openstack/compute/v2/tenantnetworks_test.go | 4 ++-- .../acceptance}/openstack/compute/v2/usage_test.go | 4 ++-- .../openstack/compute/v2/volumeattach_test.go | 6 +++--- .../acceptance}/openstack/container/v1/capsules.go | 2 +- .../openstack/container/v1/capsules_test.go | 2 +- .../acceptance}/openstack/container/v1/fixtures.go | 0 .../openstack/containerinfra/v1/certificates_test.go | 2 +- .../openstack/containerinfra/v1/clusters_test.go | 4 ++-- .../containerinfra/v1/clustertemplates_test.go | 4 ++-- .../openstack/containerinfra/v1/containerinfra.go | 6 +++--- .../openstack/containerinfra/v1/nodegroups_test.go | 4 ++-- .../acceptance}/openstack/containerinfra/v1/pkg.go | 0 .../openstack/containerinfra/v1/quotas_test.go | 4 ++-- .../acceptance}/openstack/db/v1/configurations_test.go | 4 ++-- .../acceptance}/openstack/db/v1/databases_test.go | 4 ++-- .../acceptance}/openstack/db/v1/db.go | 4 ++-- .../acceptance}/openstack/db/v1/flavors_test.go | 4 ++-- .../acceptance}/openstack/db/v1/instances_test.go | 4 ++-- .../acceptance}/openstack/db/v1/pkg.go | 0 .../acceptance}/openstack/db/v1/users_test.go | 4 ++-- .../acceptance}/openstack/dns/v2/dns.go | 2 +- .../acceptance}/openstack/dns/v2/recordsets_test.go | 4 ++-- .../acceptance}/openstack/dns/v2/transfers_test.go | 6 +++--- .../acceptance}/openstack/dns/v2/zones_test.go | 4 ++-- .../openstack/identity/v2/extension_test.go | 4 ++-- .../acceptance}/openstack/identity/v2/identity.go | 2 +- .../acceptance}/openstack/identity/v2/pkg.go | 0 .../acceptance}/openstack/identity/v2/role_test.go | 4 ++-- .../acceptance}/openstack/identity/v2/tenant_test.go | 4 ++-- .../acceptance}/openstack/identity/v2/token_test.go | 4 ++-- .../acceptance}/openstack/identity/v2/user_test.go | 4 ++-- .../identity/v3/applicationcredentials_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/catalog_test.go | 4 ++-- .../openstack/identity/v3/credentials_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/domains_test.go | 4 ++-- .../openstack/identity/v3/ec2credentials_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/endpoint_test.go | 4 ++-- .../openstack/identity/v3/federation_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/groups_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/identity.go | 2 +- .../acceptance}/openstack/identity/v3/limits_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/oauth1_test.go | 4 ++-- .../openstack/identity/v3/osinherit_test.go | 2 +- .../acceptance}/openstack/identity/v3/pkg.go | 0 .../acceptance}/openstack/identity/v3/policies_test.go | 4 ++-- .../openstack/identity/v3/projectendpoint_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/projects_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/reauth_test.go | 2 +- .../acceptance}/openstack/identity/v3/regions_test.go | 4 ++-- .../openstack/identity/v3/registeredlimits_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/roles_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/service_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/token_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/trusts_test.go | 4 ++-- .../acceptance}/openstack/identity/v3/users_test.go | 4 ++-- .../openstack/imageservice/v2/imagedata_test.go | 4 ++-- .../openstack/imageservice/v2/imageimport_test.go | 4 ++-- .../openstack/imageservice/v2/images_test.go | 4 ++-- .../openstack/imageservice/v2/imageservice.go | 2 +- .../openstack/imageservice/v2/tasks_test.go | 4 ++-- .../acceptance}/openstack/keymanager/v1/acls_test.go | 4 ++-- .../openstack/keymanager/v1/containers_test.go | 4 ++-- .../acceptance}/openstack/keymanager/v1/keymanager.go | 2 +- .../acceptance}/openstack/keymanager/v1/orders_test.go | 4 ++-- .../openstack/keymanager/v1/secrets_test.go | 4 ++-- .../openstack/loadbalancer/v2/amphorae_test.go | 4 ++-- .../openstack/loadbalancer/v2/l7policies_test.go | 4 ++-- .../openstack/loadbalancer/v2/listeners_test.go | 4 ++-- .../openstack/loadbalancer/v2/loadbalancer.go | 4 ++-- .../openstack/loadbalancer/v2/loadbalancers_test.go | 8 ++++---- .../openstack/loadbalancer/v2/monitors_test.go | 4 ++-- .../acceptance}/openstack/loadbalancer/v2/pkg.go | 0 .../openstack/loadbalancer/v2/pools_test.go | 4 ++-- .../openstack/loadbalancer/v2/providers_test.go | 4 ++-- .../openstack/loadbalancer/v2/quotas_test.go | 4 ++-- .../acceptance}/openstack/messaging/v2/claims_test.go | 4 ++-- .../acceptance}/openstack/messaging/v2/message_test.go | 4 ++-- .../acceptance}/openstack/messaging/v2/messaging.go | 2 +- .../acceptance}/openstack/messaging/v2/queue_test.go | 4 ++-- .../openstack/networking/v2/apiversion_test.go | 4 ++-- .../openstack/networking/v2/extension_test.go | 4 ++-- .../networking/v2/extensions/agents/agents_test.go | 8 ++++---- .../openstack/networking/v2/extensions/agents/doc.go | 0 .../networking/v2/extensions/attributestags_test.go | 6 +++--- .../v2/extensions/bgp/peers/bgppeers_test.go | 4 ++-- .../networking/v2/extensions/bgp/peers/doc.go | 0 .../networking/v2/extensions/bgp/peers/peers.go | 2 +- .../v2/extensions/bgp/speakers/bgpspeakers_test.go | 8 ++++---- .../networking/v2/extensions/bgp/speakers/doc.go | 0 .../networking/v2/extensions/bgp/speakers/speakers.go | 2 +- .../openstack/networking/v2/extensions/dns/dns.go | 2 +- .../openstack/networking/v2/extensions/dns/dns_test.go | 8 ++++---- .../openstack/networking/v2/extensions/extensions.go | 2 +- .../networking/v2/extensions/fwaas/firewall_test.go | 6 +++--- .../openstack/networking/v2/extensions/fwaas/fwaas.go | 2 +- .../networking/v2/extensions/fwaas/policy_test.go | 4 ++-- .../networking/v2/extensions/fwaas/rule_test.go | 4 ++-- .../networking/v2/extensions/fwaas_v2/fwaas_v2.go | 2 +- .../networking/v2/extensions/fwaas_v2/groups_test.go | 4 ++-- .../networking/v2/extensions/fwaas_v2/policy_test.go | 4 ++-- .../networking/v2/extensions/fwaas_v2/rule_test.go | 4 ++-- .../v2/extensions/layer3/addressscopes_test.go | 4 ++-- .../v2/extensions/layer3/extraroutes_test.go | 6 +++--- .../v2/extensions/layer3/floatingips_test.go | 6 +++--- .../v2/extensions/layer3/l3_scheduling_test.go | 6 +++--- .../networking/v2/extensions/layer3/layer3.go | 4 ++-- .../v2/extensions/layer3/portforwardings_test.go | 6 +++--- .../networking/v2/extensions/layer3/routers_test.go | 6 +++--- .../openstack/networking/v2/extensions/lbaas/lbaas.go | 2 +- .../networking/v2/extensions/lbaas/members_test.go | 6 +++--- .../networking/v2/extensions/lbaas/monitors_test.go | 4 ++-- .../networking/v2/extensions/lbaas/pools_test.go | 6 +++--- .../networking/v2/extensions/lbaas/vips_test.go | 6 +++--- .../v2/extensions/lbaas_v2/l7policies_test.go | 4 ++-- .../networking/v2/extensions/lbaas_v2/lbaas_v2.go | 2 +- .../v2/extensions/lbaas_v2/listeners_test.go | 4 ++-- .../v2/extensions/lbaas_v2/loadbalancers_test.go | 6 +++--- .../networking/v2/extensions/lbaas_v2/monitors_test.go | 4 ++-- .../networking/v2/extensions/lbaas_v2/pools_test.go | 4 ++-- .../openstack/networking/v2/extensions/mtu/mtu.go | 2 +- .../openstack/networking/v2/extensions/mtu/mtu_test.go | 6 +++--- .../networkipavailabilities_test.go | 4 ++-- .../v2/extensions/portsbinding/portsbinding.go | 2 +- .../v2/extensions/portsbinding/portsbinding_test.go | 6 +++--- .../networking/v2/extensions/provider_test.go | 6 +++--- .../networking/v2/extensions/qos/policies/policies.go | 2 +- .../v2/extensions/qos/policies/policies_test.go | 4 ++-- .../networking/v2/extensions/qos/rules/rules.go | 0 .../networking/v2/extensions/qos/rules/rules_test.go | 6 +++--- .../v2/extensions/qos/ruletypes/ruletypes_test.go | 4 ++-- .../networking/v2/extensions/quotas/quotas.go | 0 .../networking/v2/extensions/quotas/quotas_test.go | 4 ++-- .../v2/extensions/rbacpolicies/rbacpolicies.go | 0 .../v2/extensions/rbacpolicies/rbacpolicies_test.go | 8 ++++---- .../networking/v2/extensions/security_test.go | 6 +++--- .../v2/extensions/subnetpools/subnetpools.go | 2 +- .../v2/extensions/subnetpools/subnetpools_test.go | 4 ++-- .../v2/extensions/trunk_details/trunks_test.go | 6 +++--- .../networking/v2/extensions/trunks/trunks.go | 2 +- .../networking/v2/extensions/trunks/trunks_test.go | 6 +++--- .../v2/extensions/vlantransparent/vlantransparent.go | 2 +- .../extensions/vlantransparent/vlantransparent_test.go | 6 +++--- .../networking/v2/extensions/vpnaas/group_test.go | 4 ++-- .../networking/v2/extensions/vpnaas/ikepolicy_test.go | 4 ++-- .../v2/extensions/vpnaas/ipsecpolicy_test.go | 4 ++-- .../networking/v2/extensions/vpnaas/service_test.go | 6 +++--- .../v2/extensions/vpnaas/siteconnection_test.go | 8 ++++---- .../networking/v2/extensions/vpnaas/vpnaas.go | 2 +- .../acceptance}/openstack/networking/v2/networking.go | 2 +- .../openstack/networking/v2/networks_test.go | 4 ++-- .../acceptance}/openstack/networking/v2/ports_test.go | 6 +++--- .../openstack/networking/v2/subnets_test.go | 6 +++--- .../openstack/objectstorage/v1/accounts_test.go | 2 +- .../openstack/objectstorage/v1/containers_test.go | 4 ++-- .../openstack/objectstorage/v1/objects_test.go | 4 ++-- .../acceptance}/openstack/objectstorage/v1/pkg.go | 0 .../openstack/objectstorage/v1/versioning_test.go | 4 ++-- .../openstack/orchestration/v1/buildinfo_test.go | 2 +- .../openstack/orchestration/v1/orchestration.go | 2 +- .../openstack/orchestration/v1/stackevents_test.go | 2 +- .../openstack/orchestration/v1/stackresources_test.go | 4 ++-- .../openstack/orchestration/v1/stacks_test.go | 4 ++-- .../openstack/orchestration/v1/stacktemplates_test.go | 4 ++-- .../openstack/orchestration/v1/testdata/samplefile | 0 {acceptance => internal/acceptance}/openstack/pkg.go | 0 .../acceptance}/openstack/placement/v1/pkg.go | 0 .../acceptance}/openstack/placement/v1/placement.go | 2 +- .../openstack/placement/v1/resourceproviders_test.go | 4 ++-- .../sharedfilesystems/v2/availabilityzones_test.go | 2 +- .../sharedfilesystems/v2/messages/messages.go | 0 .../sharedfilesystems/v2/messages/messages_test.go | 4 ++-- .../openstack/sharedfilesystems/v2/messages/pkg.go | 0 .../acceptance}/openstack/sharedfilesystems/v2/pkg.go | 0 .../openstack/sharedfilesystems/v2/replicas.go | 2 +- .../openstack/sharedfilesystems/v2/replicas_test.go | 4 ++-- .../sharedfilesystems/v2/schedulerstats_test.go | 4 ++-- .../openstack/sharedfilesystems/v2/securityservices.go | 2 +- .../sharedfilesystems/v2/securityservices_test.go | 4 ++-- .../openstack/sharedfilesystems/v2/services_test.go | 4 ++-- .../openstack/sharedfilesystems/v2/shareaccessrules.go | 2 +- .../sharedfilesystems/v2/shareaccessrules_test.go | 4 ++-- .../openstack/sharedfilesystems/v2/sharenetworks.go | 4 ++-- .../sharedfilesystems/v2/sharenetworks_test.go | 4 ++-- .../openstack/sharedfilesystems/v2/shares.go | 2 +- .../openstack/sharedfilesystems/v2/shares_test.go | 4 ++-- .../openstack/sharedfilesystems/v2/sharetransfers.go | 0 .../sharedfilesystems/v2/sharetransfers_test.go | 4 ++-- .../openstack/sharedfilesystems/v2/sharetypes.go | 2 +- .../openstack/sharedfilesystems/v2/sharetypes_test.go | 4 ++-- .../openstack/sharedfilesystems/v2/snapshots.go | 2 +- .../openstack/sharedfilesystems/v2/snapshots_test.go | 4 ++-- .../acceptance}/openstack/workflow/v2/crontrigger.go | 2 +- .../openstack/workflow/v2/crontriggers_test.go | 4 ++-- .../acceptance}/openstack/workflow/v2/execution.go | 2 +- .../openstack/workflow/v2/executions_test.go | 4 ++-- .../acceptance}/openstack/workflow/v2/workflow.go | 2 +- .../openstack/workflow/v2/workflows_test.go | 4 ++-- {acceptance => internal/acceptance}/tools/pkg.go | 0 {acceptance => internal/acceptance}/tools/tools.go | 0 .../v1/profiletypes/testing/requests_test.go | 2 +- script/acceptancetest | 2 +- 290 files changed, 498 insertions(+), 498 deletions(-) rename {acceptance => internal/acceptance}/README.md (98%) rename {acceptance => internal/acceptance}/clients/clients.go (100%) rename {acceptance => internal/acceptance}/clients/conditions.go (100%) rename {acceptance => internal/acceptance}/clients/http.go (100%) rename {acceptance => internal/acceptance}/clients/testing/conditions_test.go (96%) rename {acceptance => internal/acceptance}/openstack/baremetal/httpbasic/allocations_test.go (87%) rename {acceptance => internal/acceptance}/openstack/baremetal/httpbasic/doc.go (100%) rename {acceptance => internal/acceptance}/openstack/baremetal/httpbasic/nodes_test.go (93%) rename {acceptance => internal/acceptance}/openstack/baremetal/httpbasic/ports_test.go (92%) rename {acceptance => internal/acceptance}/openstack/baremetal/noauth/allocations_test.go (87%) rename {acceptance => internal/acceptance}/openstack/baremetal/noauth/doc.go (100%) rename {acceptance => internal/acceptance}/openstack/baremetal/noauth/nodes_test.go (93%) rename {acceptance => internal/acceptance}/openstack/baremetal/noauth/ports_test.go (91%) rename {acceptance => internal/acceptance}/openstack/baremetal/v1/allocations_test.go (94%) rename {acceptance => internal/acceptance}/openstack/baremetal/v1/baremetal.go (98%) rename {acceptance => internal/acceptance}/openstack/baremetal/v1/conductors_test.go (88%) rename {acceptance => internal/acceptance}/openstack/baremetal/v1/nodes_test.go (98%) rename {acceptance => internal/acceptance}/openstack/baremetal/v1/ports_test.go (96%) rename {acceptance => internal/acceptance}/openstack/blockstorage/apiversions_test.go (89%) rename {acceptance => internal/acceptance}/openstack/blockstorage/extensions/backups_test.go (85%) rename {acceptance => internal/acceptance}/openstack/blockstorage/extensions/extensions.go (99%) rename {acceptance => internal/acceptance}/openstack/blockstorage/extensions/limits_test.go (92%) rename {acceptance => internal/acceptance}/openstack/blockstorage/extensions/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/blockstorage/extensions/schedulerhints_test.go (91%) rename {acceptance => internal/acceptance}/openstack/blockstorage/extensions/schedulerstats_test.go (84%) rename {acceptance => internal/acceptance}/openstack/blockstorage/extensions/services_test.go (83%) rename {acceptance => internal/acceptance}/openstack/blockstorage/extensions/volumeactions_test.go (93%) rename {acceptance => internal/acceptance}/openstack/blockstorage/extensions/volumetenants_test.go (87%) rename {acceptance => internal/acceptance}/openstack/blockstorage/noauth/blockstorage.go (96%) rename {acceptance => internal/acceptance}/openstack/blockstorage/noauth/snapshots_test.go (91%) rename {acceptance => internal/acceptance}/openstack/blockstorage/noauth/volumes_test.go (90%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v1/blockstorage.go (98%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v1/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v1/snapshots_test.go (91%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v1/volumes_test.go (93%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v1/volumetypes_test.go (90%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v2/blockstorage.go (97%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v2/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v2/snapshots_test.go (89%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v2/volumes_test.go (96%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v3/blockstorage.go (99%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v3/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v3/qos_test.go (95%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v3/quotaset_test.go (97%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v3/snapshots_test.go (97%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v3/volumeattachments.go (100%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v3/volumeattachments_test.go (86%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v3/volumes_test.go (96%) rename {acceptance => internal/acceptance}/openstack/blockstorage/v3/volumetypes_test.go (96%) rename {acceptance => internal/acceptance}/openstack/client_test.go (96%) rename {acceptance => internal/acceptance}/openstack/clustering/v1/actions_test.go (83%) rename {acceptance => internal/acceptance}/openstack/clustering/v1/clustering.go (98%) rename {acceptance => internal/acceptance}/openstack/clustering/v1/clusters_test.go (99%) rename {acceptance => internal/acceptance}/openstack/clustering/v1/events_test.go (82%) rename {acceptance => internal/acceptance}/openstack/clustering/v1/nodes_test.go (98%) rename {acceptance => internal/acceptance}/openstack/clustering/v1/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/clustering/v1/policies_test.go (92%) rename {acceptance => internal/acceptance}/openstack/clustering/v1/policytypes_test.go (92%) rename {acceptance => internal/acceptance}/openstack/clustering/v1/profiles_test.go (93%) rename {acceptance => internal/acceptance}/openstack/clustering/v1/profiletypes_test.go (89%) rename {acceptance => internal/acceptance}/openstack/clustering/v1/receivers_test.go (94%) rename {acceptance => internal/acceptance}/openstack/clustering/v1/webhooktrigger_test.go (96%) rename {acceptance => internal/acceptance}/openstack/common.go (100%) rename {acceptance => internal/acceptance}/openstack/compute/v2/aggregates_test.go (96%) rename {acceptance => internal/acceptance}/openstack/compute/v2/attachinterfaces_test.go (90%) rename {acceptance => internal/acceptance}/openstack/compute/v2/availabilityzones_test.go (91%) rename {acceptance => internal/acceptance}/openstack/compute/v2/bootfromvolume_test.go (97%) rename {acceptance => internal/acceptance}/openstack/compute/v2/compute.go (99%) rename {acceptance => internal/acceptance}/openstack/compute/v2/defsecrules_test.go (91%) rename {acceptance => internal/acceptance}/openstack/compute/v2/diagnostics_test.go (83%) rename {acceptance => internal/acceptance}/openstack/compute/v2/extension_test.go (88%) rename {acceptance => internal/acceptance}/openstack/compute/v2/flavors_test.go (96%) rename {acceptance => internal/acceptance}/openstack/compute/v2/floatingip_test.go (96%) rename {acceptance => internal/acceptance}/openstack/compute/v2/hypervisors_test.go (95%) rename {acceptance => internal/acceptance}/openstack/compute/v2/images_test.go (89%) rename {acceptance => internal/acceptance}/openstack/compute/v2/instance_actions_test.go (94%) rename {acceptance => internal/acceptance}/openstack/compute/v2/keypairs_test.go (94%) rename {acceptance => internal/acceptance}/openstack/compute/v2/limits_test.go (90%) rename {acceptance => internal/acceptance}/openstack/compute/v2/migrate_test.go (95%) rename {acceptance => internal/acceptance}/openstack/compute/v2/network_test.go (90%) rename {acceptance => internal/acceptance}/openstack/compute/v2/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/compute/v2/quotaset_test.go (97%) rename {acceptance => internal/acceptance}/openstack/compute/v2/remoteconsoles_test.go (81%) rename {acceptance => internal/acceptance}/openstack/compute/v2/rescueunrescue_test.go (89%) rename {acceptance => internal/acceptance}/openstack/compute/v2/secgroup_test.go (96%) rename {acceptance => internal/acceptance}/openstack/compute/v2/servergroup_test.go (95%) rename {acceptance => internal/acceptance}/openstack/compute/v2/servers_test.go (98%) rename {acceptance => internal/acceptance}/openstack/compute/v2/services_test.go (95%) rename {acceptance => internal/acceptance}/openstack/compute/v2/tenantnetworks_test.go (90%) rename {acceptance => internal/acceptance}/openstack/compute/v2/usage_test.go (93%) rename {acceptance => internal/acceptance}/openstack/compute/v2/volumeattach_test.go (81%) rename {acceptance => internal/acceptance}/openstack/container/v1/capsules.go (94%) rename {acceptance => internal/acceptance}/openstack/container/v1/capsules_test.go (97%) rename {acceptance => internal/acceptance}/openstack/container/v1/fixtures.go (100%) rename {acceptance => internal/acceptance}/openstack/containerinfra/v1/certificates_test.go (96%) rename {acceptance => internal/acceptance}/openstack/containerinfra/v1/clusters_test.go (94%) rename {acceptance => internal/acceptance}/openstack/containerinfra/v1/clustertemplates_test.go (93%) rename {acceptance => internal/acceptance}/openstack/containerinfra/v1/containerinfra.go (97%) rename {acceptance => internal/acceptance}/openstack/containerinfra/v1/nodegroups_test.go (97%) rename {acceptance => internal/acceptance}/openstack/containerinfra/v1/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/containerinfra/v1/quotas_test.go (74%) rename {acceptance => internal/acceptance}/openstack/db/v1/configurations_test.go (94%) rename {acceptance => internal/acceptance}/openstack/db/v1/databases_test.go (90%) rename {acceptance => internal/acceptance}/openstack/db/v1/db.go (97%) rename {acceptance => internal/acceptance}/openstack/db/v1/flavors_test.go (90%) rename {acceptance => internal/acceptance}/openstack/db/v1/instances_test.go (92%) rename {acceptance => internal/acceptance}/openstack/db/v1/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/db/v1/users_test.go (89%) rename {acceptance => internal/acceptance}/openstack/dns/v2/dns.go (99%) rename {acceptance => internal/acceptance}/openstack/dns/v2/recordsets_test.go (94%) rename {acceptance => internal/acceptance}/openstack/dns/v2/transfers_test.go (92%) rename {acceptance => internal/acceptance}/openstack/dns/v2/zones_test.go (88%) rename {acceptance => internal/acceptance}/openstack/identity/v2/extension_test.go (88%) rename {acceptance => internal/acceptance}/openstack/identity/v2/identity.go (98%) rename {acceptance => internal/acceptance}/openstack/identity/v2/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/identity/v2/role_test.go (92%) rename {acceptance => internal/acceptance}/openstack/identity/v2/tenant_test.go (91%) rename {acceptance => internal/acceptance}/openstack/identity/v2/token_test.go (91%) rename {acceptance => internal/acceptance}/openstack/identity/v2/user_test.go (90%) rename {acceptance => internal/acceptance}/openstack/identity/v3/applicationcredentials_test.go (98%) rename {acceptance => internal/acceptance}/openstack/identity/v3/catalog_test.go (79%) rename {acceptance => internal/acceptance}/openstack/identity/v3/credentials_test.go (97%) rename {acceptance => internal/acceptance}/openstack/identity/v3/domains_test.go (94%) rename {acceptance => internal/acceptance}/openstack/identity/v3/ec2credentials_test.go (95%) rename {acceptance => internal/acceptance}/openstack/identity/v3/endpoint_test.go (93%) rename {acceptance => internal/acceptance}/openstack/identity/v3/federation_test.go (95%) rename {acceptance => internal/acceptance}/openstack/identity/v3/groups_test.go (95%) rename {acceptance => internal/acceptance}/openstack/identity/v3/identity.go (99%) rename {acceptance => internal/acceptance}/openstack/identity/v3/limits_test.go (97%) rename {acceptance => internal/acceptance}/openstack/identity/v3/oauth1_test.go (98%) rename {acceptance => internal/acceptance}/openstack/identity/v3/osinherit_test.go (99%) rename {acceptance => internal/acceptance}/openstack/identity/v3/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/identity/v3/policies_test.go (96%) rename {acceptance => internal/acceptance}/openstack/identity/v3/projectendpoint_test.go (91%) rename {acceptance => internal/acceptance}/openstack/identity/v3/projects_test.go (98%) rename {acceptance => internal/acceptance}/openstack/identity/v3/reauth_test.go (92%) rename {acceptance => internal/acceptance}/openstack/identity/v3/regions_test.go (94%) rename {acceptance => internal/acceptance}/openstack/identity/v3/registeredlimits_test.go (96%) rename {acceptance => internal/acceptance}/openstack/identity/v3/roles_test.go (99%) rename {acceptance => internal/acceptance}/openstack/identity/v3/service_test.go (92%) rename {acceptance => internal/acceptance}/openstack/identity/v3/token_test.go (89%) rename {acceptance => internal/acceptance}/openstack/identity/v3/trusts_test.go (96%) rename {acceptance => internal/acceptance}/openstack/identity/v3/users_test.go (98%) rename {acceptance => internal/acceptance}/openstack/imageservice/v2/imagedata_test.go (82%) rename {acceptance => internal/acceptance}/openstack/imageservice/v2/imageimport_test.go (84%) rename {acceptance => internal/acceptance}/openstack/imageservice/v2/images_test.go (97%) rename {acceptance => internal/acceptance}/openstack/imageservice/v2/imageservice.go (98%) rename {acceptance => internal/acceptance}/openstack/imageservice/v2/tasks_test.go (91%) rename {acceptance => internal/acceptance}/openstack/keymanager/v1/acls_test.go (96%) rename {acceptance => internal/acceptance}/openstack/keymanager/v1/containers_test.go (97%) rename {acceptance => internal/acceptance}/openstack/keymanager/v1/keymanager.go (99%) rename {acceptance => internal/acceptance}/openstack/keymanager/v1/orders_test.go (94%) rename {acceptance => internal/acceptance}/openstack/keymanager/v1/secrets_test.go (98%) rename {acceptance => internal/acceptance}/openstack/loadbalancer/v2/amphorae_test.go (84%) rename {acceptance => internal/acceptance}/openstack/loadbalancer/v2/l7policies_test.go (85%) rename {acceptance => internal/acceptance}/openstack/loadbalancer/v2/listeners_test.go (85%) rename {acceptance => internal/acceptance}/openstack/loadbalancer/v2/loadbalancer.go (99%) rename {acceptance => internal/acceptance}/openstack/loadbalancer/v2/loadbalancers_test.go (98%) rename {acceptance => internal/acceptance}/openstack/loadbalancer/v2/monitors_test.go (84%) rename {acceptance => internal/acceptance}/openstack/loadbalancer/v2/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/loadbalancer/v2/pools_test.go (84%) rename {acceptance => internal/acceptance}/openstack/loadbalancer/v2/providers_test.go (85%) rename {acceptance => internal/acceptance}/openstack/loadbalancer/v2/quotas_test.go (94%) rename {acceptance => internal/acceptance}/openstack/messaging/v2/claims_test.go (92%) rename {acceptance => internal/acceptance}/openstack/messaging/v2/message_test.go (98%) rename {acceptance => internal/acceptance}/openstack/messaging/v2/messaging.go (98%) rename {acceptance => internal/acceptance}/openstack/messaging/v2/queue_test.go (96%) rename {acceptance => internal/acceptance}/openstack/networking/v2/apiversion_test.go (90%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extension_test.go (88%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/agents/agents_test.go (94%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/agents/doc.go (100%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/attributestags_test.go (95%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/bgp/peers/bgppeers_test.go (92%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/bgp/peers/doc.go (100%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/bgp/peers/peers.go (93%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/bgp/speakers/bgpspeakers_test.go (92%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/bgp/speakers/doc.go (100%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/bgp/speakers/speakers.go (95%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/dns/dns.go (98%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/dns/dns_test.go (95%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/extensions.go (98%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/fwaas/firewall_test.go (95%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/fwaas/fwaas.go (99%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/fwaas/policy_test.go (91%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/fwaas/rule_test.go (90%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/fwaas_v2/fwaas_v2.go (98%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/fwaas_v2/groups_test.go (96%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/fwaas_v2/policy_test.go (94%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/fwaas_v2/rule_test.go (93%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/layer3/addressscopes_test.go (91%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/layer3/extraroutes_test.go (92%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/layer3/floatingips_test.go (96%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/layer3/l3_scheduling_test.go (92%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/layer3/layer3.go (98%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/layer3/portforwardings_test.go (91%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/layer3/routers_test.go (96%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/lbaas/lbaas.go (98%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/lbaas/members_test.go (90%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/lbaas/monitors_test.go (92%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/lbaas/pools_test.go (93%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/lbaas/vips_test.go (90%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/lbaas_v2/l7policies_test.go (86%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/lbaas_v2/lbaas_v2.go (99%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/lbaas_v2/listeners_test.go (86%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/lbaas_v2/loadbalancers_test.go (97%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/lbaas_v2/monitors_test.go (86%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/lbaas_v2/pools_test.go (86%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/mtu/mtu.go (96%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/mtu/mtu_test.go (94%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/networkipavailabilities/networkipavailabilities_test.go (87%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/portsbinding/portsbinding.go (96%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go (90%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/provider_test.go (75%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/qos/policies/policies.go (95%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/qos/policies/policies_test.go (92%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/qos/rules/rules.go (100%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/qos/rules/rules_test.go (94%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/qos/ruletypes/ruletypes_test.go (89%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/quotas/quotas.go (100%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/quotas/quotas_test.go (93%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/rbacpolicies/rbacpolicies.go (100%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/rbacpolicies/rbacpolicies_test.go (87%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/security_test.go (90%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/subnetpools/subnetpools.go (96%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/subnetpools/subnetpools_test.go (91%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/trunk_details/trunks_test.go (93%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/trunks/trunks.go (95%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/trunks/trunks_test.go (97%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/vlantransparent/vlantransparent.go (97%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/vlantransparent/vlantransparent_test.go (85%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/vpnaas/group_test.go (91%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/vpnaas/ikepolicy_test.go (91%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/vpnaas/ipsecpolicy_test.go (90%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/vpnaas/service_test.go (83%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/vpnaas/siteconnection_test.go (89%) rename {acceptance => internal/acceptance}/openstack/networking/v2/extensions/vpnaas/vpnaas.go (99%) rename {acceptance => internal/acceptance}/openstack/networking/v2/networking.go (99%) rename {acceptance => internal/acceptance}/openstack/networking/v2/networks_test.go (97%) rename {acceptance => internal/acceptance}/openstack/networking/v2/ports_test.go (98%) rename {acceptance => internal/acceptance}/openstack/networking/v2/subnets_test.go (97%) rename {acceptance => internal/acceptance}/openstack/objectstorage/v1/accounts_test.go (95%) rename {acceptance => internal/acceptance}/openstack/objectstorage/v1/containers_test.go (98%) rename {acceptance => internal/acceptance}/openstack/objectstorage/v1/objects_test.go (98%) rename {acceptance => internal/acceptance}/openstack/objectstorage/v1/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/objectstorage/v1/versioning_test.go (97%) rename {acceptance => internal/acceptance}/openstack/orchestration/v1/buildinfo_test.go (86%) rename {acceptance => internal/acceptance}/openstack/orchestration/v1/orchestration.go (98%) rename {acceptance => internal/acceptance}/openstack/orchestration/v1/stackevents_test.go (93%) rename {acceptance => internal/acceptance}/openstack/orchestration/v1/stackresources_test.go (92%) rename {acceptance => internal/acceptance}/openstack/orchestration/v1/stacks_test.go (90%) rename {acceptance => internal/acceptance}/openstack/orchestration/v1/stacktemplates_test.go (90%) rename {acceptance => internal/acceptance}/openstack/orchestration/v1/testdata/samplefile (100%) rename {acceptance => internal/acceptance}/openstack/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/placement/v1/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/placement/v1/placement.go (97%) rename {acceptance => internal/acceptance}/openstack/placement/v1/resourceproviders_test.go (96%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/availabilityzones_test.go (91%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/messages/messages.go (100%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/messages/messages_test.go (95%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/messages/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/pkg.go (100%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/replicas.go (98%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/replicas_test.go (98%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/schedulerstats_test.go (82%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/securityservices.go (96%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/securityservices_test.go (97%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/services_test.go (83%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/shareaccessrules.go (97%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/shareaccessrules_test.go (96%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/sharenetworks.go (92%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/sharenetworks_test.go (98%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/shares.go (98%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/shares_test.go (99%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/sharetransfers.go (100%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/sharetransfers_test.go (93%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/sharetypes.go (95%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/sharetypes_test.go (97%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/snapshots.go (97%) rename {acceptance => internal/acceptance}/openstack/sharedfilesystems/v2/snapshots_test.go (97%) rename {acceptance => internal/acceptance}/openstack/workflow/v2/crontrigger.go (97%) rename {acceptance => internal/acceptance}/openstack/workflow/v2/crontriggers_test.go (91%) rename {acceptance => internal/acceptance}/openstack/workflow/v2/execution.go (97%) rename {acceptance => internal/acceptance}/openstack/workflow/v2/executions_test.go (90%) rename {acceptance => internal/acceptance}/openstack/workflow/v2/workflow.go (97%) rename {acceptance => internal/acceptance}/openstack/workflow/v2/workflows_test.go (89%) rename {acceptance => internal/acceptance}/tools/pkg.go (100%) rename {acceptance => internal/acceptance}/tools/tools.go (100%) diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index 17225e1e5f..b836cfb711 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -51,7 +51,7 @@ jobs: run: ./script/acceptancetest env: DEVSTACK_PATH: ${{ github.workspace }}/devstack - ACCEPTANCE_TESTS_FILTER: '^acceptance/openstack$' + ACCEPTANCE_TESTS_FILTER: '^internal/acceptance/openstack$' OS_BRANCH: ${{ matrix.openstack_version }} - name: Generate logs on failure run: ./script/collectlogs diff --git a/acceptance/README.md b/internal/acceptance/README.md similarity index 98% rename from acceptance/README.md rename to internal/acceptance/README.md index 834cdc12ef..cbbbac7f39 100644 --- a/acceptance/README.md +++ b/internal/acceptance/README.md @@ -100,7 +100,7 @@ Alternatively, add the following to your `.bashrc`: gophercloudtest() { if [[ -n $1 ]] && [[ -n $2 ]]; then pushd $GOPATH/src/github.com/gophercloud/gophercloud - go test -v -tags "fixtures acceptance" -run "$1" github.com/gophercloud/gophercloud/acceptance/openstack/$2 | tee ~/gophercloud.log + go test -v -tags "fixtures acceptance" -run "$1" github.com/gophercloud/gophercloud/internal/acceptance/openstack/$2 | tee ~/gophercloud.log popd fi } diff --git a/acceptance/clients/clients.go b/internal/acceptance/clients/clients.go similarity index 100% rename from acceptance/clients/clients.go rename to internal/acceptance/clients/clients.go diff --git a/acceptance/clients/conditions.go b/internal/acceptance/clients/conditions.go similarity index 100% rename from acceptance/clients/conditions.go rename to internal/acceptance/clients/conditions.go diff --git a/acceptance/clients/http.go b/internal/acceptance/clients/http.go similarity index 100% rename from acceptance/clients/http.go rename to internal/acceptance/clients/http.go diff --git a/acceptance/clients/testing/conditions_test.go b/internal/acceptance/clients/testing/conditions_test.go similarity index 96% rename from acceptance/clients/testing/conditions_test.go rename to internal/acceptance/clients/testing/conditions_test.go index a9825ea293..3fbe11260e 100644 --- a/acceptance/clients/testing/conditions_test.go +++ b/internal/acceptance/clients/testing/conditions_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" ) func TestIsCurrentAbove(t *testing.T) { diff --git a/acceptance/openstack/baremetal/httpbasic/allocations_test.go b/internal/acceptance/openstack/baremetal/httpbasic/allocations_test.go similarity index 87% rename from acceptance/openstack/baremetal/httpbasic/allocations_test.go rename to internal/acceptance/openstack/baremetal/httpbasic/allocations_test.go index afe44a0cf2..89acfb6a03 100644 --- a/acceptance/openstack/baremetal/httpbasic/allocations_test.go +++ b/internal/acceptance/openstack/baremetal/httpbasic/allocations_test.go @@ -6,8 +6,8 @@ package httpbasic import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - v1 "github.com/gophercloud/gophercloud/acceptance/openstack/baremetal/v1" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + v1 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/baremetal/v1" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/allocations" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/baremetal/httpbasic/doc.go b/internal/acceptance/openstack/baremetal/httpbasic/doc.go similarity index 100% rename from acceptance/openstack/baremetal/httpbasic/doc.go rename to internal/acceptance/openstack/baremetal/httpbasic/doc.go diff --git a/acceptance/openstack/baremetal/httpbasic/nodes_test.go b/internal/acceptance/openstack/baremetal/httpbasic/nodes_test.go similarity index 93% rename from acceptance/openstack/baremetal/httpbasic/nodes_test.go rename to internal/acceptance/openstack/baremetal/httpbasic/nodes_test.go index 79995912e3..993a3ca227 100644 --- a/acceptance/openstack/baremetal/httpbasic/nodes_test.go +++ b/internal/acceptance/openstack/baremetal/httpbasic/nodes_test.go @@ -3,8 +3,8 @@ package httpbasic import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - v1 "github.com/gophercloud/gophercloud/acceptance/openstack/baremetal/v1" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + v1 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/baremetal/v1" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes" "github.com/gophercloud/gophercloud/pagination" diff --git a/acceptance/openstack/baremetal/httpbasic/ports_test.go b/internal/acceptance/openstack/baremetal/httpbasic/ports_test.go similarity index 92% rename from acceptance/openstack/baremetal/httpbasic/ports_test.go rename to internal/acceptance/openstack/baremetal/httpbasic/ports_test.go index ebed5b6785..f69ba2744a 100644 --- a/acceptance/openstack/baremetal/httpbasic/ports_test.go +++ b/internal/acceptance/openstack/baremetal/httpbasic/ports_test.go @@ -6,8 +6,8 @@ package httpbasic import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - v1 "github.com/gophercloud/gophercloud/acceptance/openstack/baremetal/v1" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + v1 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/baremetal/v1" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/ports" "github.com/gophercloud/gophercloud/pagination" diff --git a/acceptance/openstack/baremetal/noauth/allocations_test.go b/internal/acceptance/openstack/baremetal/noauth/allocations_test.go similarity index 87% rename from acceptance/openstack/baremetal/noauth/allocations_test.go rename to internal/acceptance/openstack/baremetal/noauth/allocations_test.go index 825fd4d93e..fe02a1fdb6 100644 --- a/acceptance/openstack/baremetal/noauth/allocations_test.go +++ b/internal/acceptance/openstack/baremetal/noauth/allocations_test.go @@ -6,8 +6,8 @@ package noauth import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - v1 "github.com/gophercloud/gophercloud/acceptance/openstack/baremetal/v1" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + v1 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/baremetal/v1" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/allocations" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/baremetal/noauth/doc.go b/internal/acceptance/openstack/baremetal/noauth/doc.go similarity index 100% rename from acceptance/openstack/baremetal/noauth/doc.go rename to internal/acceptance/openstack/baremetal/noauth/doc.go diff --git a/acceptance/openstack/baremetal/noauth/nodes_test.go b/internal/acceptance/openstack/baremetal/noauth/nodes_test.go similarity index 93% rename from acceptance/openstack/baremetal/noauth/nodes_test.go rename to internal/acceptance/openstack/baremetal/noauth/nodes_test.go index 09969992a3..3d2f36c6f7 100644 --- a/acceptance/openstack/baremetal/noauth/nodes_test.go +++ b/internal/acceptance/openstack/baremetal/noauth/nodes_test.go @@ -3,8 +3,8 @@ package noauth import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - v1 "github.com/gophercloud/gophercloud/acceptance/openstack/baremetal/v1" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + v1 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/baremetal/v1" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes" "github.com/gophercloud/gophercloud/pagination" diff --git a/acceptance/openstack/baremetal/noauth/ports_test.go b/internal/acceptance/openstack/baremetal/noauth/ports_test.go similarity index 91% rename from acceptance/openstack/baremetal/noauth/ports_test.go rename to internal/acceptance/openstack/baremetal/noauth/ports_test.go index a45b26d462..bb59ec6ad4 100644 --- a/acceptance/openstack/baremetal/noauth/ports_test.go +++ b/internal/acceptance/openstack/baremetal/noauth/ports_test.go @@ -6,8 +6,8 @@ package noauth import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - v1 "github.com/gophercloud/gophercloud/acceptance/openstack/baremetal/v1" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + v1 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/baremetal/v1" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/ports" "github.com/gophercloud/gophercloud/pagination" diff --git a/acceptance/openstack/baremetal/v1/allocations_test.go b/internal/acceptance/openstack/baremetal/v1/allocations_test.go similarity index 94% rename from acceptance/openstack/baremetal/v1/allocations_test.go rename to internal/acceptance/openstack/baremetal/v1/allocations_test.go index 7c6bfac52f..c902f4219d 100644 --- a/acceptance/openstack/baremetal/v1/allocations_test.go +++ b/internal/acceptance/openstack/baremetal/v1/allocations_test.go @@ -6,7 +6,7 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/allocations" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/baremetal/v1/baremetal.go b/internal/acceptance/openstack/baremetal/v1/baremetal.go similarity index 98% rename from acceptance/openstack/baremetal/v1/baremetal.go rename to internal/acceptance/openstack/baremetal/v1/baremetal.go index 1278de533a..5849957fb8 100644 --- a/acceptance/openstack/baremetal/v1/baremetal.go +++ b/internal/acceptance/openstack/baremetal/v1/baremetal.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/allocations" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/ports" diff --git a/acceptance/openstack/baremetal/v1/conductors_test.go b/internal/acceptance/openstack/baremetal/v1/conductors_test.go similarity index 88% rename from acceptance/openstack/baremetal/v1/conductors_test.go rename to internal/acceptance/openstack/baremetal/v1/conductors_test.go index 5324a7aa1c..4dc294c4b6 100644 --- a/acceptance/openstack/baremetal/v1/conductors_test.go +++ b/internal/acceptance/openstack/baremetal/v1/conductors_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/conductors" "github.com/gophercloud/gophercloud/pagination" diff --git a/acceptance/openstack/baremetal/v1/nodes_test.go b/internal/acceptance/openstack/baremetal/v1/nodes_test.go similarity index 98% rename from acceptance/openstack/baremetal/v1/nodes_test.go rename to internal/acceptance/openstack/baremetal/v1/nodes_test.go index 2c0af7c499..af79bfd5d7 100644 --- a/acceptance/openstack/baremetal/v1/nodes_test.go +++ b/internal/acceptance/openstack/baremetal/v1/nodes_test.go @@ -6,7 +6,7 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes" "github.com/gophercloud/gophercloud/pagination" diff --git a/acceptance/openstack/baremetal/v1/ports_test.go b/internal/acceptance/openstack/baremetal/v1/ports_test.go similarity index 96% rename from acceptance/openstack/baremetal/v1/ports_test.go rename to internal/acceptance/openstack/baremetal/v1/ports_test.go index e263402c29..069a31028d 100644 --- a/acceptance/openstack/baremetal/v1/ports_test.go +++ b/internal/acceptance/openstack/baremetal/v1/ports_test.go @@ -6,7 +6,7 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/baremetal/v1/ports" "github.com/gophercloud/gophercloud/pagination" diff --git a/acceptance/openstack/blockstorage/apiversions_test.go b/internal/acceptance/openstack/blockstorage/apiversions_test.go similarity index 89% rename from acceptance/openstack/blockstorage/apiversions_test.go rename to internal/acceptance/openstack/blockstorage/apiversions_test.go index 77ccda0f31..b9ff57b83f 100644 --- a/acceptance/openstack/blockstorage/apiversions_test.go +++ b/internal/acceptance/openstack/blockstorage/apiversions_test.go @@ -6,8 +6,8 @@ package blockstorage import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/apiversions" ) diff --git a/acceptance/openstack/blockstorage/extensions/backups_test.go b/internal/acceptance/openstack/blockstorage/extensions/backups_test.go similarity index 85% rename from acceptance/openstack/blockstorage/extensions/backups_test.go rename to internal/acceptance/openstack/blockstorage/extensions/backups_test.go index 67f86c8eb6..eea44b511d 100644 --- a/acceptance/openstack/blockstorage/extensions/backups_test.go +++ b/internal/acceptance/openstack/blockstorage/extensions/backups_test.go @@ -6,10 +6,10 @@ package extensions import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/backups" - blockstorage "github.com/gophercloud/gophercloud/acceptance/openstack/blockstorage/v3" + blockstorage "github.com/gophercloud/gophercloud/internal/acceptance/openstack/blockstorage/v3" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/blockstorage/extensions/extensions.go b/internal/acceptance/openstack/blockstorage/extensions/extensions.go similarity index 99% rename from acceptance/openstack/blockstorage/extensions/extensions.go rename to internal/acceptance/openstack/blockstorage/extensions/extensions.go index dfa357fdd3..dca1062035 100644 --- a/acceptance/openstack/blockstorage/extensions/extensions.go +++ b/internal/acceptance/openstack/blockstorage/extensions/extensions.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/backups" "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions" "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes" diff --git a/acceptance/openstack/blockstorage/extensions/limits_test.go b/internal/acceptance/openstack/blockstorage/extensions/limits_test.go similarity index 92% rename from acceptance/openstack/blockstorage/extensions/limits_test.go rename to internal/acceptance/openstack/blockstorage/extensions/limits_test.go index c1b3994f9c..4ea356f657 100644 --- a/acceptance/openstack/blockstorage/extensions/limits_test.go +++ b/internal/acceptance/openstack/blockstorage/extensions/limits_test.go @@ -3,8 +3,8 @@ package extensions import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/limits" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/blockstorage/extensions/pkg.go b/internal/acceptance/openstack/blockstorage/extensions/pkg.go similarity index 100% rename from acceptance/openstack/blockstorage/extensions/pkg.go rename to internal/acceptance/openstack/blockstorage/extensions/pkg.go diff --git a/acceptance/openstack/blockstorage/extensions/schedulerhints_test.go b/internal/acceptance/openstack/blockstorage/extensions/schedulerhints_test.go similarity index 91% rename from acceptance/openstack/blockstorage/extensions/schedulerhints_test.go rename to internal/acceptance/openstack/blockstorage/extensions/schedulerhints_test.go index 8ff9fbb6a1..9864428324 100644 --- a/acceptance/openstack/blockstorage/extensions/schedulerhints_test.go +++ b/internal/acceptance/openstack/blockstorage/extensions/schedulerhints_test.go @@ -6,8 +6,8 @@ package extensions import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/schedulerhints" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/blockstorage/extensions/schedulerstats_test.go b/internal/acceptance/openstack/blockstorage/extensions/schedulerstats_test.go similarity index 84% rename from acceptance/openstack/blockstorage/extensions/schedulerstats_test.go rename to internal/acceptance/openstack/blockstorage/extensions/schedulerstats_test.go index 7b5f609b1c..f30c4c6120 100644 --- a/acceptance/openstack/blockstorage/extensions/schedulerstats_test.go +++ b/internal/acceptance/openstack/blockstorage/extensions/schedulerstats_test.go @@ -6,8 +6,8 @@ package extensions import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/schedulerstats" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/blockstorage/extensions/services_test.go b/internal/acceptance/openstack/blockstorage/extensions/services_test.go similarity index 83% rename from acceptance/openstack/blockstorage/extensions/services_test.go rename to internal/acceptance/openstack/blockstorage/extensions/services_test.go index 863d38aaec..9f32132a54 100644 --- a/acceptance/openstack/blockstorage/extensions/services_test.go +++ b/internal/acceptance/openstack/blockstorage/extensions/services_test.go @@ -6,8 +6,8 @@ package extensions import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/services" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/blockstorage/extensions/volumeactions_test.go b/internal/acceptance/openstack/blockstorage/extensions/volumeactions_test.go similarity index 93% rename from acceptance/openstack/blockstorage/extensions/volumeactions_test.go rename to internal/acceptance/openstack/blockstorage/extensions/volumeactions_test.go index 98541419df..673e968297 100644 --- a/acceptance/openstack/blockstorage/extensions/volumeactions_test.go +++ b/internal/acceptance/openstack/blockstorage/extensions/volumeactions_test.go @@ -6,11 +6,11 @@ package extensions import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - blockstorage "github.com/gophercloud/gophercloud/acceptance/openstack/blockstorage/v2" - blockstorageV3 "github.com/gophercloud/gophercloud/acceptance/openstack/blockstorage/v3" - compute "github.com/gophercloud/gophercloud/acceptance/openstack/compute/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + blockstorage "github.com/gophercloud/gophercloud/internal/acceptance/openstack/blockstorage/v2" + blockstorageV3 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/blockstorage/v3" + compute "github.com/gophercloud/gophercloud/internal/acceptance/openstack/compute/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/blockstorage/extensions/volumetenants_test.go b/internal/acceptance/openstack/blockstorage/extensions/volumetenants_test.go similarity index 87% rename from acceptance/openstack/blockstorage/extensions/volumetenants_test.go rename to internal/acceptance/openstack/blockstorage/extensions/volumetenants_test.go index e684a79423..2571588537 100644 --- a/acceptance/openstack/blockstorage/extensions/volumetenants_test.go +++ b/internal/acceptance/openstack/blockstorage/extensions/volumetenants_test.go @@ -6,8 +6,8 @@ package extensions import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - blockstorage "github.com/gophercloud/gophercloud/acceptance/openstack/blockstorage/v3" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + blockstorage "github.com/gophercloud/gophercloud/internal/acceptance/openstack/blockstorage/v3" "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumetenants" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/blockstorage/noauth/blockstorage.go b/internal/acceptance/openstack/blockstorage/noauth/blockstorage.go similarity index 96% rename from acceptance/openstack/blockstorage/noauth/blockstorage.go rename to internal/acceptance/openstack/blockstorage/noauth/blockstorage.go index d057c2e604..6f5580714f 100644 --- a/acceptance/openstack/blockstorage/noauth/blockstorage.go +++ b/internal/acceptance/openstack/blockstorage/noauth/blockstorage.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes" ) diff --git a/acceptance/openstack/blockstorage/noauth/snapshots_test.go b/internal/acceptance/openstack/blockstorage/noauth/snapshots_test.go similarity index 91% rename from acceptance/openstack/blockstorage/noauth/snapshots_test.go rename to internal/acceptance/openstack/blockstorage/noauth/snapshots_test.go index 2c0cc63dec..a12d1fa66b 100644 --- a/acceptance/openstack/blockstorage/noauth/snapshots_test.go +++ b/internal/acceptance/openstack/blockstorage/noauth/snapshots_test.go @@ -6,8 +6,8 @@ package noauth import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots" ) diff --git a/acceptance/openstack/blockstorage/noauth/volumes_test.go b/internal/acceptance/openstack/blockstorage/noauth/volumes_test.go similarity index 90% rename from acceptance/openstack/blockstorage/noauth/volumes_test.go rename to internal/acceptance/openstack/blockstorage/noauth/volumes_test.go index 5f80d07cfb..5a66210a33 100644 --- a/acceptance/openstack/blockstorage/noauth/volumes_test.go +++ b/internal/acceptance/openstack/blockstorage/noauth/volumes_test.go @@ -6,8 +6,8 @@ package noauth import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes" ) diff --git a/acceptance/openstack/blockstorage/v1/blockstorage.go b/internal/acceptance/openstack/blockstorage/v1/blockstorage.go similarity index 98% rename from acceptance/openstack/blockstorage/v1/blockstorage.go rename to internal/acceptance/openstack/blockstorage/v1/blockstorage.go index 670eaad50d..e380f80caf 100644 --- a/acceptance/openstack/blockstorage/v1/blockstorage.go +++ b/internal/acceptance/openstack/blockstorage/v1/blockstorage.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/snapshots" "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes" "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumetypes" diff --git a/acceptance/openstack/blockstorage/v1/pkg.go b/internal/acceptance/openstack/blockstorage/v1/pkg.go similarity index 100% rename from acceptance/openstack/blockstorage/v1/pkg.go rename to internal/acceptance/openstack/blockstorage/v1/pkg.go diff --git a/acceptance/openstack/blockstorage/v1/snapshots_test.go b/internal/acceptance/openstack/blockstorage/v1/snapshots_test.go similarity index 91% rename from acceptance/openstack/blockstorage/v1/snapshots_test.go rename to internal/acceptance/openstack/blockstorage/v1/snapshots_test.go index 9ff2c192a4..8b02b35486 100644 --- a/acceptance/openstack/blockstorage/v1/snapshots_test.go +++ b/internal/acceptance/openstack/blockstorage/v1/snapshots_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/snapshots" ) diff --git a/acceptance/openstack/blockstorage/v1/volumes_test.go b/internal/acceptance/openstack/blockstorage/v1/volumes_test.go similarity index 93% rename from acceptance/openstack/blockstorage/v1/volumes_test.go rename to internal/acceptance/openstack/blockstorage/v1/volumes_test.go index c5aba5d539..d22701955c 100644 --- a/acceptance/openstack/blockstorage/v1/volumes_test.go +++ b/internal/acceptance/openstack/blockstorage/v1/volumes_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/blockstorage/v1/volumetypes_test.go b/internal/acceptance/openstack/blockstorage/v1/volumetypes_test.go similarity index 90% rename from acceptance/openstack/blockstorage/v1/volumetypes_test.go rename to internal/acceptance/openstack/blockstorage/v1/volumetypes_test.go index c1e76a740e..f21fe5eae1 100644 --- a/acceptance/openstack/blockstorage/v1/volumetypes_test.go +++ b/internal/acceptance/openstack/blockstorage/v1/volumetypes_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumetypes" ) diff --git a/acceptance/openstack/blockstorage/v2/blockstorage.go b/internal/acceptance/openstack/blockstorage/v2/blockstorage.go similarity index 97% rename from acceptance/openstack/blockstorage/v2/blockstorage.go rename to internal/acceptance/openstack/blockstorage/v2/blockstorage.go index 6170d555ba..e3027abce9 100644 --- a/acceptance/openstack/blockstorage/v2/blockstorage.go +++ b/internal/acceptance/openstack/blockstorage/v2/blockstorage.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/snapshots" "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/blockstorage/v2/pkg.go b/internal/acceptance/openstack/blockstorage/v2/pkg.go similarity index 100% rename from acceptance/openstack/blockstorage/v2/pkg.go rename to internal/acceptance/openstack/blockstorage/v2/pkg.go diff --git a/acceptance/openstack/blockstorage/v2/snapshots_test.go b/internal/acceptance/openstack/blockstorage/v2/snapshots_test.go similarity index 89% rename from acceptance/openstack/blockstorage/v2/snapshots_test.go rename to internal/acceptance/openstack/blockstorage/v2/snapshots_test.go index 22a8a6bd8a..ec8a2775d8 100644 --- a/acceptance/openstack/blockstorage/v2/snapshots_test.go +++ b/internal/acceptance/openstack/blockstorage/v2/snapshots_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/snapshots" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/blockstorage/v2/volumes_test.go b/internal/acceptance/openstack/blockstorage/v2/volumes_test.go similarity index 96% rename from acceptance/openstack/blockstorage/v2/volumes_test.go rename to internal/acceptance/openstack/blockstorage/v2/volumes_test.go index f2f839cc98..3ca33c1b6c 100644 --- a/acceptance/openstack/blockstorage/v2/volumes_test.go +++ b/internal/acceptance/openstack/blockstorage/v2/volumes_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions" "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/snapshots" "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes" diff --git a/acceptance/openstack/blockstorage/v3/blockstorage.go b/internal/acceptance/openstack/blockstorage/v3/blockstorage.go similarity index 99% rename from acceptance/openstack/blockstorage/v3/blockstorage.go rename to internal/acceptance/openstack/blockstorage/v3/blockstorage.go index ad6518b7de..6a4408a543 100644 --- a/acceptance/openstack/blockstorage/v3/blockstorage.go +++ b/internal/acceptance/openstack/blockstorage/v3/blockstorage.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/qos" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes" diff --git a/acceptance/openstack/blockstorage/v3/pkg.go b/internal/acceptance/openstack/blockstorage/v3/pkg.go similarity index 100% rename from acceptance/openstack/blockstorage/v3/pkg.go rename to internal/acceptance/openstack/blockstorage/v3/pkg.go diff --git a/acceptance/openstack/blockstorage/v3/qos_test.go b/internal/acceptance/openstack/blockstorage/v3/qos_test.go similarity index 95% rename from acceptance/openstack/blockstorage/v3/qos_test.go rename to internal/acceptance/openstack/blockstorage/v3/qos_test.go index 82c52a384a..85aa5b1908 100644 --- a/acceptance/openstack/blockstorage/v3/qos_test.go +++ b/internal/acceptance/openstack/blockstorage/v3/qos_test.go @@ -3,8 +3,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/qos" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/blockstorage/v3/quotaset_test.go b/internal/acceptance/openstack/blockstorage/v3/quotaset_test.go similarity index 97% rename from acceptance/openstack/blockstorage/v3/quotaset_test.go rename to internal/acceptance/openstack/blockstorage/v3/quotaset_test.go index 5a9d702954..1106f160da 100644 --- a/acceptance/openstack/blockstorage/v3/quotaset_test.go +++ b/internal/acceptance/openstack/blockstorage/v3/quotaset_test.go @@ -8,8 +8,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/quotasets" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumetypes" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/blockstorage/v3/snapshots_test.go b/internal/acceptance/openstack/blockstorage/v3/snapshots_test.go similarity index 97% rename from acceptance/openstack/blockstorage/v3/snapshots_test.go rename to internal/acceptance/openstack/blockstorage/v3/snapshots_test.go index 3c3d08ef4c..51cdd1f461 100644 --- a/acceptance/openstack/blockstorage/v3/snapshots_test.go +++ b/internal/acceptance/openstack/blockstorage/v3/snapshots_test.go @@ -8,8 +8,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/blockstorage/v3/volumeattachments.go b/internal/acceptance/openstack/blockstorage/v3/volumeattachments.go similarity index 100% rename from acceptance/openstack/blockstorage/v3/volumeattachments.go rename to internal/acceptance/openstack/blockstorage/v3/volumeattachments.go diff --git a/acceptance/openstack/blockstorage/v3/volumeattachments_test.go b/internal/acceptance/openstack/blockstorage/v3/volumeattachments_test.go similarity index 86% rename from acceptance/openstack/blockstorage/v3/volumeattachments_test.go rename to internal/acceptance/openstack/blockstorage/v3/volumeattachments_test.go index a8cd3b005e..5d2b939dc0 100644 --- a/acceptance/openstack/blockstorage/v3/volumeattachments_test.go +++ b/internal/acceptance/openstack/blockstorage/v3/volumeattachments_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - compute "github.com/gophercloud/gophercloud/acceptance/openstack/compute/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + compute "github.com/gophercloud/gophercloud/internal/acceptance/openstack/compute/v2" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/blockstorage/v3/volumes_test.go b/internal/acceptance/openstack/blockstorage/v3/volumes_test.go similarity index 96% rename from acceptance/openstack/blockstorage/v3/volumes_test.go rename to internal/acceptance/openstack/blockstorage/v3/volumes_test.go index b86f70863a..3bf405e3d5 100644 --- a/acceptance/openstack/blockstorage/v3/volumes_test.go +++ b/internal/acceptance/openstack/blockstorage/v3/volumes_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes" "github.com/gophercloud/gophercloud/pagination" diff --git a/acceptance/openstack/blockstorage/v3/volumetypes_test.go b/internal/acceptance/openstack/blockstorage/v3/volumetypes_test.go similarity index 96% rename from acceptance/openstack/blockstorage/v3/volumetypes_test.go rename to internal/acceptance/openstack/blockstorage/v3/volumetypes_test.go index 6ac7086c3a..84b5c0fd39 100644 --- a/acceptance/openstack/blockstorage/v3/volumetypes_test.go +++ b/internal/acceptance/openstack/blockstorage/v3/volumetypes_test.go @@ -6,9 +6,9 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - identity "github.com/gophercloud/gophercloud/acceptance/openstack/identity/v3" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + identity "github.com/gophercloud/gophercloud/internal/acceptance/openstack/identity/v3" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumetypes" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/client_test.go b/internal/acceptance/openstack/client_test.go similarity index 96% rename from acceptance/openstack/client_test.go rename to internal/acceptance/openstack/client_test.go index d497c969a9..366dd8b664 100644 --- a/acceptance/openstack/client_test.go +++ b/internal/acceptance/openstack/client_test.go @@ -9,8 +9,8 @@ import ( "time" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack" "github.com/gophercloud/gophercloud/openstack/identity/v3/credentials" "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/ec2tokens" diff --git a/acceptance/openstack/clustering/v1/actions_test.go b/internal/acceptance/openstack/clustering/v1/actions_test.go similarity index 83% rename from acceptance/openstack/clustering/v1/actions_test.go rename to internal/acceptance/openstack/clustering/v1/actions_test.go index f8a7843eb1..9ec67640f4 100644 --- a/acceptance/openstack/clustering/v1/actions_test.go +++ b/internal/acceptance/openstack/clustering/v1/actions_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/clustering/v1/actions" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/clustering/v1/clustering.go b/internal/acceptance/openstack/clustering/v1/clustering.go similarity index 98% rename from acceptance/openstack/clustering/v1/clustering.go rename to internal/acceptance/openstack/clustering/v1/clustering.go index 6c7a406796..d256bf2790 100644 --- a/acceptance/openstack/clustering/v1/clustering.go +++ b/internal/acceptance/openstack/clustering/v1/clustering.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/clustering/v1/actions" "github.com/gophercloud/gophercloud/openstack/clustering/v1/clusters" "github.com/gophercloud/gophercloud/openstack/clustering/v1/nodes" diff --git a/acceptance/openstack/clustering/v1/clusters_test.go b/internal/acceptance/openstack/clustering/v1/clusters_test.go similarity index 99% rename from acceptance/openstack/clustering/v1/clusters_test.go rename to internal/acceptance/openstack/clustering/v1/clusters_test.go index f5e72704c2..9d37267ae2 100644 --- a/acceptance/openstack/clustering/v1/clusters_test.go +++ b/internal/acceptance/openstack/clustering/v1/clusters_test.go @@ -8,8 +8,8 @@ import ( "strings" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/clustering/v1/actions" "github.com/gophercloud/gophercloud/openstack/clustering/v1/clusters" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/clustering/v1/events_test.go b/internal/acceptance/openstack/clustering/v1/events_test.go similarity index 82% rename from acceptance/openstack/clustering/v1/events_test.go rename to internal/acceptance/openstack/clustering/v1/events_test.go index 6e8b50a827..cb849ad880 100644 --- a/acceptance/openstack/clustering/v1/events_test.go +++ b/internal/acceptance/openstack/clustering/v1/events_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/clustering/v1/events" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/clustering/v1/nodes_test.go b/internal/acceptance/openstack/clustering/v1/nodes_test.go similarity index 98% rename from acceptance/openstack/clustering/v1/nodes_test.go rename to internal/acceptance/openstack/clustering/v1/nodes_test.go index 50d178672d..f35c3d4a46 100644 --- a/acceptance/openstack/clustering/v1/nodes_test.go +++ b/internal/acceptance/openstack/clustering/v1/nodes_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/clustering/v1/nodes" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/clustering/v1/pkg.go b/internal/acceptance/openstack/clustering/v1/pkg.go similarity index 100% rename from acceptance/openstack/clustering/v1/pkg.go rename to internal/acceptance/openstack/clustering/v1/pkg.go diff --git a/acceptance/openstack/clustering/v1/policies_test.go b/internal/acceptance/openstack/clustering/v1/policies_test.go similarity index 92% rename from acceptance/openstack/clustering/v1/policies_test.go rename to internal/acceptance/openstack/clustering/v1/policies_test.go index a1fc2be6ef..9502b9a1af 100644 --- a/acceptance/openstack/clustering/v1/policies_test.go +++ b/internal/acceptance/openstack/clustering/v1/policies_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/clustering/v1/policies" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/clustering/v1/policytypes_test.go b/internal/acceptance/openstack/clustering/v1/policytypes_test.go similarity index 92% rename from acceptance/openstack/clustering/v1/policytypes_test.go rename to internal/acceptance/openstack/clustering/v1/policytypes_test.go index 70a43f9c66..fe930b9c57 100644 --- a/acceptance/openstack/clustering/v1/policytypes_test.go +++ b/internal/acceptance/openstack/clustering/v1/policytypes_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/clustering/v1/policytypes" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/clustering/v1/profiles_test.go b/internal/acceptance/openstack/clustering/v1/profiles_test.go similarity index 93% rename from acceptance/openstack/clustering/v1/profiles_test.go rename to internal/acceptance/openstack/clustering/v1/profiles_test.go index b65b7d4565..0c6143df57 100644 --- a/acceptance/openstack/clustering/v1/profiles_test.go +++ b/internal/acceptance/openstack/clustering/v1/profiles_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/clustering/v1/profiles" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/clustering/v1/profiletypes_test.go b/internal/acceptance/openstack/clustering/v1/profiletypes_test.go similarity index 89% rename from acceptance/openstack/clustering/v1/profiletypes_test.go rename to internal/acceptance/openstack/clustering/v1/profiletypes_test.go index 9a7c700252..2fe7c0301c 100644 --- a/acceptance/openstack/clustering/v1/profiletypes_test.go +++ b/internal/acceptance/openstack/clustering/v1/profiletypes_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/clustering/v1/profiletypes" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/clustering/v1/receivers_test.go b/internal/acceptance/openstack/clustering/v1/receivers_test.go similarity index 94% rename from acceptance/openstack/clustering/v1/receivers_test.go rename to internal/acceptance/openstack/clustering/v1/receivers_test.go index 56b862abbf..6c7149a489 100644 --- a/acceptance/openstack/clustering/v1/receivers_test.go +++ b/internal/acceptance/openstack/clustering/v1/receivers_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/clustering/v1/receivers" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/clustering/v1/webhooktrigger_test.go b/internal/acceptance/openstack/clustering/v1/webhooktrigger_test.go similarity index 96% rename from acceptance/openstack/clustering/v1/webhooktrigger_test.go rename to internal/acceptance/openstack/clustering/v1/webhooktrigger_test.go index b4b4a2e37e..c481208711 100644 --- a/acceptance/openstack/clustering/v1/webhooktrigger_test.go +++ b/internal/acceptance/openstack/clustering/v1/webhooktrigger_test.go @@ -6,7 +6,7 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/clustering/v1/nodes" "github.com/gophercloud/gophercloud/openstack/clustering/v1/webhooks" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/common.go b/internal/acceptance/openstack/common.go similarity index 100% rename from acceptance/openstack/common.go rename to internal/acceptance/openstack/common.go diff --git a/acceptance/openstack/compute/v2/aggregates_test.go b/internal/acceptance/openstack/compute/v2/aggregates_test.go similarity index 96% rename from acceptance/openstack/compute/v2/aggregates_test.go rename to internal/acceptance/openstack/compute/v2/aggregates_test.go index a90a77b8dd..84e05dec52 100644 --- a/acceptance/openstack/compute/v2/aggregates_test.go +++ b/internal/acceptance/openstack/compute/v2/aggregates_test.go @@ -9,8 +9,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/aggregates" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/hypervisors" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/compute/v2/attachinterfaces_test.go b/internal/acceptance/openstack/compute/v2/attachinterfaces_test.go similarity index 90% rename from acceptance/openstack/compute/v2/attachinterfaces_test.go rename to internal/acceptance/openstack/compute/v2/attachinterfaces_test.go index 3efef0c1d5..3887634f1e 100644 --- a/acceptance/openstack/compute/v2/attachinterfaces_test.go +++ b/internal/acceptance/openstack/compute/v2/attachinterfaces_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/availabilityzones_test.go b/internal/acceptance/openstack/compute/v2/availabilityzones_test.go similarity index 91% rename from acceptance/openstack/compute/v2/availabilityzones_test.go rename to internal/acceptance/openstack/compute/v2/availabilityzones_test.go index 967d56f5ab..9d125589e6 100644 --- a/acceptance/openstack/compute/v2/availabilityzones_test.go +++ b/internal/acceptance/openstack/compute/v2/availabilityzones_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/bootfromvolume_test.go b/internal/acceptance/openstack/compute/v2/bootfromvolume_test.go similarity index 97% rename from acceptance/openstack/compute/v2/bootfromvolume_test.go rename to internal/acceptance/openstack/compute/v2/bootfromvolume_test.go index 3296c84627..2a054568ec 100644 --- a/acceptance/openstack/compute/v2/bootfromvolume_test.go +++ b/internal/acceptance/openstack/compute/v2/bootfromvolume_test.go @@ -6,9 +6,9 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - blockstorage "github.com/gophercloud/gophercloud/acceptance/openstack/blockstorage/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + blockstorage "github.com/gophercloud/gophercloud/internal/acceptance/openstack/blockstorage/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/bootfromvolume" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/compute/v2/compute.go b/internal/acceptance/openstack/compute/v2/compute.go similarity index 99% rename from acceptance/openstack/compute/v2/compute.go rename to internal/acceptance/openstack/compute/v2/compute.go index 7a5c696e68..f3d102916e 100644 --- a/acceptance/openstack/compute/v2/compute.go +++ b/internal/acceptance/openstack/compute/v2/compute.go @@ -9,8 +9,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/aggregates" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces" diff --git a/acceptance/openstack/compute/v2/defsecrules_test.go b/internal/acceptance/openstack/compute/v2/defsecrules_test.go similarity index 91% rename from acceptance/openstack/compute/v2/defsecrules_test.go rename to internal/acceptance/openstack/compute/v2/defsecrules_test.go index cb0352f80d..b2e5accad0 100644 --- a/acceptance/openstack/compute/v2/defsecrules_test.go +++ b/internal/acceptance/openstack/compute/v2/defsecrules_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" dsr "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/defsecrules" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/diagnostics_test.go b/internal/acceptance/openstack/compute/v2/diagnostics_test.go similarity index 83% rename from acceptance/openstack/compute/v2/diagnostics_test.go rename to internal/acceptance/openstack/compute/v2/diagnostics_test.go index a19d54fe66..0424bb27a3 100644 --- a/acceptance/openstack/compute/v2/diagnostics_test.go +++ b/internal/acceptance/openstack/compute/v2/diagnostics_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/diagnostics" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/extension_test.go b/internal/acceptance/openstack/compute/v2/extension_test.go similarity index 88% rename from acceptance/openstack/compute/v2/extension_test.go rename to internal/acceptance/openstack/compute/v2/extension_test.go index 8fb0f28ba1..96b321a0c7 100644 --- a/acceptance/openstack/compute/v2/extension_test.go +++ b/internal/acceptance/openstack/compute/v2/extension_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/common/extensions" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/flavors_test.go b/internal/acceptance/openstack/compute/v2/flavors_test.go similarity index 96% rename from acceptance/openstack/compute/v2/flavors_test.go rename to internal/acceptance/openstack/compute/v2/flavors_test.go index 9e3ec1db45..ec14e5ad33 100644 --- a/acceptance/openstack/compute/v2/flavors_test.go +++ b/internal/acceptance/openstack/compute/v2/flavors_test.go @@ -6,9 +6,9 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - identity "github.com/gophercloud/gophercloud/acceptance/openstack/identity/v3" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + identity "github.com/gophercloud/gophercloud/internal/acceptance/openstack/identity/v3" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/floatingip_test.go b/internal/acceptance/openstack/compute/v2/floatingip_test.go similarity index 96% rename from acceptance/openstack/compute/v2/floatingip_test.go rename to internal/acceptance/openstack/compute/v2/floatingip_test.go index dae68e7b63..6e2ecb0399 100644 --- a/acceptance/openstack/compute/v2/floatingip_test.go +++ b/internal/acceptance/openstack/compute/v2/floatingip_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips" "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/compute/v2/hypervisors_test.go b/internal/acceptance/openstack/compute/v2/hypervisors_test.go similarity index 95% rename from acceptance/openstack/compute/v2/hypervisors_test.go rename to internal/acceptance/openstack/compute/v2/hypervisors_test.go index ee4410726f..4992a62814 100644 --- a/acceptance/openstack/compute/v2/hypervisors_test.go +++ b/internal/acceptance/openstack/compute/v2/hypervisors_test.go @@ -8,8 +8,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/hypervisors" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/images_test.go b/internal/acceptance/openstack/compute/v2/images_test.go similarity index 89% rename from acceptance/openstack/compute/v2/images_test.go rename to internal/acceptance/openstack/compute/v2/images_test.go index 4d25d29416..48dae1d974 100644 --- a/acceptance/openstack/compute/v2/images_test.go +++ b/internal/acceptance/openstack/compute/v2/images_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/images" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/instance_actions_test.go b/internal/acceptance/openstack/compute/v2/instance_actions_test.go similarity index 94% rename from acceptance/openstack/compute/v2/instance_actions_test.go rename to internal/acceptance/openstack/compute/v2/instance_actions_test.go index 3b60d90067..9928c2ceb8 100644 --- a/acceptance/openstack/compute/v2/instance_actions_test.go +++ b/internal/acceptance/openstack/compute/v2/instance_actions_test.go @@ -7,8 +7,8 @@ import ( "testing" "time" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/instanceactions" "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/compute/v2/keypairs_test.go b/internal/acceptance/openstack/compute/v2/keypairs_test.go similarity index 94% rename from acceptance/openstack/compute/v2/keypairs_test.go rename to internal/acceptance/openstack/compute/v2/keypairs_test.go index dd6c577963..21e37bd802 100644 --- a/acceptance/openstack/compute/v2/keypairs_test.go +++ b/internal/acceptance/openstack/compute/v2/keypairs_test.go @@ -6,9 +6,9 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - identity "github.com/gophercloud/gophercloud/acceptance/openstack/identity/v3" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + identity "github.com/gophercloud/gophercloud/internal/acceptance/openstack/identity/v3" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs" "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/compute/v2/limits_test.go b/internal/acceptance/openstack/compute/v2/limits_test.go similarity index 90% rename from acceptance/openstack/compute/v2/limits_test.go rename to internal/acceptance/openstack/compute/v2/limits_test.go index 3aab23c3a7..c355ea0181 100644 --- a/acceptance/openstack/compute/v2/limits_test.go +++ b/internal/acceptance/openstack/compute/v2/limits_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/limits" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/migrate_test.go b/internal/acceptance/openstack/compute/v2/migrate_test.go similarity index 95% rename from acceptance/openstack/compute/v2/migrate_test.go rename to internal/acceptance/openstack/compute/v2/migrate_test.go index fcc69e7fb9..8edc44b980 100644 --- a/acceptance/openstack/compute/v2/migrate_test.go +++ b/internal/acceptance/openstack/compute/v2/migrate_test.go @@ -6,7 +6,7 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/migrate" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/network_test.go b/internal/acceptance/openstack/compute/v2/network_test.go similarity index 90% rename from acceptance/openstack/compute/v2/network_test.go rename to internal/acceptance/openstack/compute/v2/network_test.go index 345356830f..0850c040b0 100644 --- a/acceptance/openstack/compute/v2/network_test.go +++ b/internal/acceptance/openstack/compute/v2/network_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/networks" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/pkg.go b/internal/acceptance/openstack/compute/v2/pkg.go similarity index 100% rename from acceptance/openstack/compute/v2/pkg.go rename to internal/acceptance/openstack/compute/v2/pkg.go diff --git a/acceptance/openstack/compute/v2/quotaset_test.go b/internal/acceptance/openstack/compute/v2/quotaset_test.go similarity index 97% rename from acceptance/openstack/compute/v2/quotaset_test.go rename to internal/acceptance/openstack/compute/v2/quotaset_test.go index 3273b81b22..72868e1d25 100644 --- a/acceptance/openstack/compute/v2/quotaset_test.go +++ b/internal/acceptance/openstack/compute/v2/quotaset_test.go @@ -9,8 +9,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/quotasets" "github.com/gophercloud/gophercloud/openstack/identity/v3/projects" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/compute/v2/remoteconsoles_test.go b/internal/acceptance/openstack/compute/v2/remoteconsoles_test.go similarity index 81% rename from acceptance/openstack/compute/v2/remoteconsoles_test.go rename to internal/acceptance/openstack/compute/v2/remoteconsoles_test.go index 1a32de0045..f6fa7c8edb 100644 --- a/acceptance/openstack/compute/v2/remoteconsoles_test.go +++ b/internal/acceptance/openstack/compute/v2/remoteconsoles_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/rescueunrescue_test.go b/internal/acceptance/openstack/compute/v2/rescueunrescue_test.go similarity index 89% rename from acceptance/openstack/compute/v2/rescueunrescue_test.go rename to internal/acceptance/openstack/compute/v2/rescueunrescue_test.go index b4304bfdfc..2d660a0b4f 100644 --- a/acceptance/openstack/compute/v2/rescueunrescue_test.go +++ b/internal/acceptance/openstack/compute/v2/rescueunrescue_test.go @@ -6,7 +6,7 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/secgroup_test.go b/internal/acceptance/openstack/compute/v2/secgroup_test.go similarity index 96% rename from acceptance/openstack/compute/v2/secgroup_test.go rename to internal/acceptance/openstack/compute/v2/secgroup_test.go index 174c3f418f..aaa2595443 100644 --- a/acceptance/openstack/compute/v2/secgroup_test.go +++ b/internal/acceptance/openstack/compute/v2/secgroup_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups" "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/compute/v2/servergroup_test.go b/internal/acceptance/openstack/compute/v2/servergroup_test.go similarity index 95% rename from acceptance/openstack/compute/v2/servergroup_test.go rename to internal/acceptance/openstack/compute/v2/servergroup_test.go index fe11c28a3f..2ee3a1494c 100644 --- a/acceptance/openstack/compute/v2/servergroup_test.go +++ b/internal/acceptance/openstack/compute/v2/servergroup_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups" "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/compute/v2/servers_test.go b/internal/acceptance/openstack/compute/v2/servers_test.go similarity index 98% rename from acceptance/openstack/compute/v2/servers_test.go rename to internal/acceptance/openstack/compute/v2/servers_test.go index 953cb05720..0f32a4ea17 100644 --- a/acceptance/openstack/compute/v2/servers_test.go +++ b/internal/acceptance/openstack/compute/v2/servers_test.go @@ -8,9 +8,9 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - networks "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networks "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/extendedserverattributes" diff --git a/acceptance/openstack/compute/v2/services_test.go b/internal/acceptance/openstack/compute/v2/services_test.go similarity index 95% rename from acceptance/openstack/compute/v2/services_test.go rename to internal/acceptance/openstack/compute/v2/services_test.go index d7d36d7f2c..fbd8b760cf 100644 --- a/acceptance/openstack/compute/v2/services_test.go +++ b/internal/acceptance/openstack/compute/v2/services_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/services" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/tenantnetworks_test.go b/internal/acceptance/openstack/compute/v2/tenantnetworks_test.go similarity index 90% rename from acceptance/openstack/compute/v2/tenantnetworks_test.go rename to internal/acceptance/openstack/compute/v2/tenantnetworks_test.go index f404663472..3700d5f38c 100644 --- a/acceptance/openstack/compute/v2/tenantnetworks_test.go +++ b/internal/acceptance/openstack/compute/v2/tenantnetworks_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/tenantnetworks" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/compute/v2/usage_test.go b/internal/acceptance/openstack/compute/v2/usage_test.go similarity index 93% rename from acceptance/openstack/compute/v2/usage_test.go rename to internal/acceptance/openstack/compute/v2/usage_test.go index c4874a68c6..4ad35aa599 100644 --- a/acceptance/openstack/compute/v2/usage_test.go +++ b/internal/acceptance/openstack/compute/v2/usage_test.go @@ -8,8 +8,8 @@ import ( "testing" "time" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/usage" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/compute/v2/volumeattach_test.go b/internal/acceptance/openstack/compute/v2/volumeattach_test.go similarity index 81% rename from acceptance/openstack/compute/v2/volumeattach_test.go rename to internal/acceptance/openstack/compute/v2/volumeattach_test.go index 1d3dac08f8..11f5328e1f 100644 --- a/acceptance/openstack/compute/v2/volumeattach_test.go +++ b/internal/acceptance/openstack/compute/v2/volumeattach_test.go @@ -6,9 +6,9 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - bs "github.com/gophercloud/gophercloud/acceptance/openstack/blockstorage/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + bs "github.com/gophercloud/gophercloud/internal/acceptance/openstack/blockstorage/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/container/v1/capsules.go b/internal/acceptance/openstack/container/v1/capsules.go similarity index 94% rename from acceptance/openstack/container/v1/capsules.go rename to internal/acceptance/openstack/container/v1/capsules.go index 08467ce2b9..7b4cdcd095 100644 --- a/acceptance/openstack/container/v1/capsules.go +++ b/internal/acceptance/openstack/container/v1/capsules.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/container/v1/capsules" ) diff --git a/acceptance/openstack/container/v1/capsules_test.go b/internal/acceptance/openstack/container/v1/capsules_test.go similarity index 97% rename from acceptance/openstack/container/v1/capsules_test.go rename to internal/acceptance/openstack/container/v1/capsules_test.go index 451d5e2853..4ebda2bbfd 100644 --- a/acceptance/openstack/container/v1/capsules_test.go +++ b/internal/acceptance/openstack/container/v1/capsules_test.go @@ -6,7 +6,7 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/container/v1/capsules" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/container/v1/fixtures.go b/internal/acceptance/openstack/container/v1/fixtures.go similarity index 100% rename from acceptance/openstack/container/v1/fixtures.go rename to internal/acceptance/openstack/container/v1/fixtures.go diff --git a/acceptance/openstack/containerinfra/v1/certificates_test.go b/internal/acceptance/openstack/containerinfra/v1/certificates_test.go similarity index 96% rename from acceptance/openstack/containerinfra/v1/certificates_test.go rename to internal/acceptance/openstack/containerinfra/v1/certificates_test.go index b83f1ac28d..b1d1911cb6 100644 --- a/acceptance/openstack/containerinfra/v1/certificates_test.go +++ b/internal/acceptance/openstack/containerinfra/v1/certificates_test.go @@ -6,7 +6,7 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/containerinfra/v1/certificates" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/containerinfra/v1/clusters_test.go b/internal/acceptance/openstack/containerinfra/v1/clusters_test.go similarity index 94% rename from acceptance/openstack/containerinfra/v1/clusters_test.go rename to internal/acceptance/openstack/containerinfra/v1/clusters_test.go index 67eca18c53..1e2fbb6184 100644 --- a/acceptance/openstack/containerinfra/v1/clusters_test.go +++ b/internal/acceptance/openstack/containerinfra/v1/clusters_test.go @@ -7,8 +7,8 @@ import ( "testing" "time" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/containerinfra/v1/clusters" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/containerinfra/v1/clustertemplates_test.go b/internal/acceptance/openstack/containerinfra/v1/clustertemplates_test.go similarity index 93% rename from acceptance/openstack/containerinfra/v1/clustertemplates_test.go rename to internal/acceptance/openstack/containerinfra/v1/clustertemplates_test.go index 87994c5c20..67843c1c4c 100644 --- a/acceptance/openstack/containerinfra/v1/clustertemplates_test.go +++ b/internal/acceptance/openstack/containerinfra/v1/clustertemplates_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/containerinfra/v1/clustertemplates" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/containerinfra/v1/containerinfra.go b/internal/acceptance/openstack/containerinfra/v1/containerinfra.go similarity index 97% rename from acceptance/openstack/containerinfra/v1/containerinfra.go rename to internal/acceptance/openstack/containerinfra/v1/containerinfra.go index 796c0149ff..28127195f0 100644 --- a/acceptance/openstack/containerinfra/v1/containerinfra.go +++ b/internal/acceptance/openstack/containerinfra/v1/containerinfra.go @@ -8,9 +8,9 @@ import ( "time" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - idv3 "github.com/gophercloud/gophercloud/acceptance/openstack/identity/v3" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + idv3 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/identity/v3" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/containerinfra/v1/clusters" "github.com/gophercloud/gophercloud/openstack/containerinfra/v1/clustertemplates" "github.com/gophercloud/gophercloud/openstack/containerinfra/v1/quotas" diff --git a/acceptance/openstack/containerinfra/v1/nodegroups_test.go b/internal/acceptance/openstack/containerinfra/v1/nodegroups_test.go similarity index 97% rename from acceptance/openstack/containerinfra/v1/nodegroups_test.go rename to internal/acceptance/openstack/containerinfra/v1/nodegroups_test.go index 7537d1d436..acbde956a5 100644 --- a/acceptance/openstack/containerinfra/v1/nodegroups_test.go +++ b/internal/acceptance/openstack/containerinfra/v1/nodegroups_test.go @@ -9,8 +9,8 @@ import ( "time" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/containerinfra/v1/nodegroups" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/containerinfra/v1/pkg.go b/internal/acceptance/openstack/containerinfra/v1/pkg.go similarity index 100% rename from acceptance/openstack/containerinfra/v1/pkg.go rename to internal/acceptance/openstack/containerinfra/v1/pkg.go diff --git a/acceptance/openstack/containerinfra/v1/quotas_test.go b/internal/acceptance/openstack/containerinfra/v1/quotas_test.go similarity index 74% rename from acceptance/openstack/containerinfra/v1/quotas_test.go rename to internal/acceptance/openstack/containerinfra/v1/quotas_test.go index 5783d9195b..64169babca 100644 --- a/acceptance/openstack/containerinfra/v1/quotas_test.go +++ b/internal/acceptance/openstack/containerinfra/v1/quotas_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/db/v1/configurations_test.go b/internal/acceptance/openstack/db/v1/configurations_test.go similarity index 94% rename from acceptance/openstack/db/v1/configurations_test.go rename to internal/acceptance/openstack/db/v1/configurations_test.go index 02472cc8fb..ae108aace3 100644 --- a/acceptance/openstack/db/v1/configurations_test.go +++ b/internal/acceptance/openstack/db/v1/configurations_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/db/v1/configurations" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/db/v1/databases_test.go b/internal/acceptance/openstack/db/v1/databases_test.go similarity index 90% rename from acceptance/openstack/db/v1/databases_test.go rename to internal/acceptance/openstack/db/v1/databases_test.go index 854ca0bc0f..f8ca7d2250 100644 --- a/acceptance/openstack/db/v1/databases_test.go +++ b/internal/acceptance/openstack/db/v1/databases_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/db/v1/databases" ) diff --git a/acceptance/openstack/db/v1/db.go b/internal/acceptance/openstack/db/v1/db.go similarity index 97% rename from acceptance/openstack/db/v1/db.go rename to internal/acceptance/openstack/db/v1/db.go index f5e637f3d9..1a1e39758e 100644 --- a/acceptance/openstack/db/v1/db.go +++ b/internal/acceptance/openstack/db/v1/db.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/db/v1/databases" "github.com/gophercloud/gophercloud/openstack/db/v1/instances" "github.com/gophercloud/gophercloud/openstack/db/v1/users" diff --git a/acceptance/openstack/db/v1/flavors_test.go b/internal/acceptance/openstack/db/v1/flavors_test.go similarity index 90% rename from acceptance/openstack/db/v1/flavors_test.go rename to internal/acceptance/openstack/db/v1/flavors_test.go index 0c51565b60..2183e60f7a 100644 --- a/acceptance/openstack/db/v1/flavors_test.go +++ b/internal/acceptance/openstack/db/v1/flavors_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/db/v1/flavors" ) diff --git a/acceptance/openstack/db/v1/instances_test.go b/internal/acceptance/openstack/db/v1/instances_test.go similarity index 92% rename from acceptance/openstack/db/v1/instances_test.go rename to internal/acceptance/openstack/db/v1/instances_test.go index 0d9ccdf08f..16a5d2d6df 100644 --- a/acceptance/openstack/db/v1/instances_test.go +++ b/internal/acceptance/openstack/db/v1/instances_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/db/v1/instances" ) diff --git a/acceptance/openstack/db/v1/pkg.go b/internal/acceptance/openstack/db/v1/pkg.go similarity index 100% rename from acceptance/openstack/db/v1/pkg.go rename to internal/acceptance/openstack/db/v1/pkg.go diff --git a/acceptance/openstack/db/v1/users_test.go b/internal/acceptance/openstack/db/v1/users_test.go similarity index 89% rename from acceptance/openstack/db/v1/users_test.go rename to internal/acceptance/openstack/db/v1/users_test.go index 6bdc00bbad..c9417c06e8 100644 --- a/acceptance/openstack/db/v1/users_test.go +++ b/internal/acceptance/openstack/db/v1/users_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/db/v1/users" ) diff --git a/acceptance/openstack/dns/v2/dns.go b/internal/acceptance/openstack/dns/v2/dns.go similarity index 99% rename from acceptance/openstack/dns/v2/dns.go rename to internal/acceptance/openstack/dns/v2/dns.go index 7fc34b70e0..d61588895f 100644 --- a/acceptance/openstack/dns/v2/dns.go +++ b/internal/acceptance/openstack/dns/v2/dns.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets" transferAccepts "github.com/gophercloud/gophercloud/openstack/dns/v2/transfer/accept" transferRequests "github.com/gophercloud/gophercloud/openstack/dns/v2/transfer/request" diff --git a/acceptance/openstack/dns/v2/recordsets_test.go b/internal/acceptance/openstack/dns/v2/recordsets_test.go similarity index 94% rename from acceptance/openstack/dns/v2/recordsets_test.go rename to internal/acceptance/openstack/dns/v2/recordsets_test.go index 67b1f706ce..38aadcd6e8 100644 --- a/acceptance/openstack/dns/v2/recordsets_test.go +++ b/internal/acceptance/openstack/dns/v2/recordsets_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/dns/v2/transfers_test.go b/internal/acceptance/openstack/dns/v2/transfers_test.go similarity index 92% rename from acceptance/openstack/dns/v2/transfers_test.go rename to internal/acceptance/openstack/dns/v2/transfers_test.go index 341aec6415..7cbcf4aa72 100644 --- a/acceptance/openstack/dns/v2/transfers_test.go +++ b/internal/acceptance/openstack/dns/v2/transfers_test.go @@ -6,9 +6,9 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - identity "github.com/gophercloud/gophercloud/acceptance/openstack/identity/v3" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + identity "github.com/gophercloud/gophercloud/internal/acceptance/openstack/identity/v3" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" transferAccepts "github.com/gophercloud/gophercloud/openstack/dns/v2/transfer/accept" transferRequests "github.com/gophercloud/gophercloud/openstack/dns/v2/transfer/request" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/dns/v2/zones_test.go b/internal/acceptance/openstack/dns/v2/zones_test.go similarity index 88% rename from acceptance/openstack/dns/v2/zones_test.go rename to internal/acceptance/openstack/dns/v2/zones_test.go index e21b96d27c..b8edc55b10 100644 --- a/acceptance/openstack/dns/v2/zones_test.go +++ b/internal/acceptance/openstack/dns/v2/zones_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/dns/v2/zones" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/identity/v2/extension_test.go b/internal/acceptance/openstack/identity/v2/extension_test.go similarity index 88% rename from acceptance/openstack/identity/v2/extension_test.go rename to internal/acceptance/openstack/identity/v2/extension_test.go index 7077c08a84..ed4202c372 100644 --- a/acceptance/openstack/identity/v2/extension_test.go +++ b/internal/acceptance/openstack/identity/v2/extension_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v2/extensions" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/identity/v2/identity.go b/internal/acceptance/openstack/identity/v2/identity.go similarity index 98% rename from acceptance/openstack/identity/v2/identity.go rename to internal/acceptance/openstack/identity/v2/identity.go index f74812193b..6666e2e950 100644 --- a/acceptance/openstack/identity/v2/identity.go +++ b/internal/acceptance/openstack/identity/v2/identity.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v2/extensions/admin/roles" "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants" "github.com/gophercloud/gophercloud/openstack/identity/v2/users" diff --git a/acceptance/openstack/identity/v2/pkg.go b/internal/acceptance/openstack/identity/v2/pkg.go similarity index 100% rename from acceptance/openstack/identity/v2/pkg.go rename to internal/acceptance/openstack/identity/v2/pkg.go diff --git a/acceptance/openstack/identity/v2/role_test.go b/internal/acceptance/openstack/identity/v2/role_test.go similarity index 92% rename from acceptance/openstack/identity/v2/role_test.go rename to internal/acceptance/openstack/identity/v2/role_test.go index 4c40e70162..573209f4b8 100644 --- a/acceptance/openstack/identity/v2/role_test.go +++ b/internal/acceptance/openstack/identity/v2/role_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v2/extensions/admin/roles" "github.com/gophercloud/gophercloud/openstack/identity/v2/users" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/identity/v2/tenant_test.go b/internal/acceptance/openstack/identity/v2/tenant_test.go similarity index 91% rename from acceptance/openstack/identity/v2/tenant_test.go rename to internal/acceptance/openstack/identity/v2/tenant_test.go index df2dcb7eb0..0b108f6733 100644 --- a/acceptance/openstack/identity/v2/tenant_test.go +++ b/internal/acceptance/openstack/identity/v2/tenant_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/identity/v2/token_test.go b/internal/acceptance/openstack/identity/v2/token_test.go similarity index 91% rename from acceptance/openstack/identity/v2/token_test.go rename to internal/acceptance/openstack/identity/v2/token_test.go index cf758c60e2..085a3a5066 100644 --- a/acceptance/openstack/identity/v2/token_test.go +++ b/internal/acceptance/openstack/identity/v2/token_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack" "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/identity/v2/user_test.go b/internal/acceptance/openstack/identity/v2/user_test.go similarity index 90% rename from acceptance/openstack/identity/v2/user_test.go rename to internal/acceptance/openstack/identity/v2/user_test.go index e700cdd3ec..d014fc9698 100644 --- a/acceptance/openstack/identity/v2/user_test.go +++ b/internal/acceptance/openstack/identity/v2/user_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v2/users" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/identity/v3/applicationcredentials_test.go b/internal/acceptance/openstack/identity/v3/applicationcredentials_test.go similarity index 98% rename from acceptance/openstack/identity/v3/applicationcredentials_test.go rename to internal/acceptance/openstack/identity/v3/applicationcredentials_test.go index e1758c5b2f..e2c5d6580d 100644 --- a/acceptance/openstack/identity/v3/applicationcredentials_test.go +++ b/internal/acceptance/openstack/identity/v3/applicationcredentials_test.go @@ -7,8 +7,8 @@ import ( "testing" "time" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack" "github.com/gophercloud/gophercloud/openstack/identity/v3/applicationcredentials" "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens" diff --git a/acceptance/openstack/identity/v3/catalog_test.go b/internal/acceptance/openstack/identity/v3/catalog_test.go similarity index 79% rename from acceptance/openstack/identity/v3/catalog_test.go rename to internal/acceptance/openstack/identity/v3/catalog_test.go index 11542c58e6..c366b40793 100644 --- a/acceptance/openstack/identity/v3/catalog_test.go +++ b/internal/acceptance/openstack/identity/v3/catalog_test.go @@ -3,8 +3,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/catalog" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/identity/v3/credentials_test.go b/internal/acceptance/openstack/identity/v3/credentials_test.go similarity index 97% rename from acceptance/openstack/identity/v3/credentials_test.go rename to internal/acceptance/openstack/identity/v3/credentials_test.go index acb5cd94f1..a0a6d675e6 100644 --- a/acceptance/openstack/identity/v3/credentials_test.go +++ b/internal/acceptance/openstack/identity/v3/credentials_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack" "github.com/gophercloud/gophercloud/openstack/identity/v3/credentials" "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/ec2tokens" diff --git a/acceptance/openstack/identity/v3/domains_test.go b/internal/acceptance/openstack/identity/v3/domains_test.go similarity index 94% rename from acceptance/openstack/identity/v3/domains_test.go rename to internal/acceptance/openstack/identity/v3/domains_test.go index 5e9d06b266..0a096ea7d9 100644 --- a/acceptance/openstack/identity/v3/domains_test.go +++ b/internal/acceptance/openstack/identity/v3/domains_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/domains" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/identity/v3/ec2credentials_test.go b/internal/acceptance/openstack/identity/v3/ec2credentials_test.go similarity index 95% rename from acceptance/openstack/identity/v3/ec2credentials_test.go rename to internal/acceptance/openstack/identity/v3/ec2credentials_test.go index 5c19459f9f..36977de3e7 100644 --- a/acceptance/openstack/identity/v3/ec2credentials_test.go +++ b/internal/acceptance/openstack/identity/v3/ec2credentials_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack" "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/ec2credentials" "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens" diff --git a/acceptance/openstack/identity/v3/endpoint_test.go b/internal/acceptance/openstack/identity/v3/endpoint_test.go similarity index 93% rename from acceptance/openstack/identity/v3/endpoint_test.go rename to internal/acceptance/openstack/identity/v3/endpoint_test.go index eac753d217..f0dbd37737 100644 --- a/acceptance/openstack/identity/v3/endpoint_test.go +++ b/internal/acceptance/openstack/identity/v3/endpoint_test.go @@ -8,8 +8,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/endpoints" "github.com/gophercloud/gophercloud/openstack/identity/v3/services" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/identity/v3/federation_test.go b/internal/acceptance/openstack/identity/v3/federation_test.go similarity index 95% rename from acceptance/openstack/identity/v3/federation_test.go rename to internal/acceptance/openstack/identity/v3/federation_test.go index a1b286b9f0..eb84beda31 100644 --- a/acceptance/openstack/identity/v3/federation_test.go +++ b/internal/acceptance/openstack/identity/v3/federation_test.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/federation" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/identity/v3/groups_test.go b/internal/acceptance/openstack/identity/v3/groups_test.go similarity index 95% rename from acceptance/openstack/identity/v3/groups_test.go rename to internal/acceptance/openstack/identity/v3/groups_test.go index b07d7d1b6c..ee16600be4 100644 --- a/acceptance/openstack/identity/v3/groups_test.go +++ b/internal/acceptance/openstack/identity/v3/groups_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/groups" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/identity/v3/identity.go b/internal/acceptance/openstack/identity/v3/identity.go similarity index 99% rename from acceptance/openstack/identity/v3/identity.go rename to internal/acceptance/openstack/identity/v3/identity.go index 3824b2aa0a..c4c5282280 100644 --- a/acceptance/openstack/identity/v3/identity.go +++ b/internal/acceptance/openstack/identity/v3/identity.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/domains" "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts" "github.com/gophercloud/gophercloud/openstack/identity/v3/groups" diff --git a/acceptance/openstack/identity/v3/limits_test.go b/internal/acceptance/openstack/identity/v3/limits_test.go similarity index 97% rename from acceptance/openstack/identity/v3/limits_test.go rename to internal/acceptance/openstack/identity/v3/limits_test.go index 05ef790829..af36e3b420 100644 --- a/acceptance/openstack/identity/v3/limits_test.go +++ b/internal/acceptance/openstack/identity/v3/limits_test.go @@ -7,8 +7,8 @@ import ( "os" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/limits" "github.com/gophercloud/gophercloud/openstack/identity/v3/registeredlimits" "github.com/gophercloud/gophercloud/openstack/identity/v3/services" diff --git a/acceptance/openstack/identity/v3/oauth1_test.go b/internal/acceptance/openstack/identity/v3/oauth1_test.go similarity index 98% rename from acceptance/openstack/identity/v3/oauth1_test.go rename to internal/acceptance/openstack/identity/v3/oauth1_test.go index 0a8dd3c0ee..7270518478 100644 --- a/acceptance/openstack/identity/v3/oauth1_test.go +++ b/internal/acceptance/openstack/identity/v3/oauth1_test.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack" "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/oauth1" "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens" diff --git a/acceptance/openstack/identity/v3/osinherit_test.go b/internal/acceptance/openstack/identity/v3/osinherit_test.go similarity index 99% rename from acceptance/openstack/identity/v3/osinherit_test.go rename to internal/acceptance/openstack/identity/v3/osinherit_test.go index 6ac777c0ec..b75171e08b 100644 --- a/acceptance/openstack/identity/v3/osinherit_test.go +++ b/internal/acceptance/openstack/identity/v3/osinherit_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/identity/v3/domains" "github.com/gophercloud/gophercloud/openstack/identity/v3/groups" "github.com/gophercloud/gophercloud/openstack/identity/v3/osinherit" diff --git a/acceptance/openstack/identity/v3/pkg.go b/internal/acceptance/openstack/identity/v3/pkg.go similarity index 100% rename from acceptance/openstack/identity/v3/pkg.go rename to internal/acceptance/openstack/identity/v3/pkg.go diff --git a/acceptance/openstack/identity/v3/policies_test.go b/internal/acceptance/openstack/identity/v3/policies_test.go similarity index 96% rename from acceptance/openstack/identity/v3/policies_test.go rename to internal/acceptance/openstack/identity/v3/policies_test.go index 01367018b8..39d43e08a9 100644 --- a/acceptance/openstack/identity/v3/policies_test.go +++ b/internal/acceptance/openstack/identity/v3/policies_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/policies" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/identity/v3/projectendpoint_test.go b/internal/acceptance/openstack/identity/v3/projectendpoint_test.go similarity index 91% rename from acceptance/openstack/identity/v3/projectendpoint_test.go rename to internal/acceptance/openstack/identity/v3/projectendpoint_test.go index e8c5770a72..af4542d553 100644 --- a/acceptance/openstack/identity/v3/projectendpoint_test.go +++ b/internal/acceptance/openstack/identity/v3/projectendpoint_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/endpoints" "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/projectendpoints" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/identity/v3/projects_test.go b/internal/acceptance/openstack/identity/v3/projects_test.go similarity index 98% rename from acceptance/openstack/identity/v3/projects_test.go rename to internal/acceptance/openstack/identity/v3/projects_test.go index 4c23a45988..08265e1595 100644 --- a/acceptance/openstack/identity/v3/projects_test.go +++ b/internal/acceptance/openstack/identity/v3/projects_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/projects" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/identity/v3/reauth_test.go b/internal/acceptance/openstack/identity/v3/reauth_test.go similarity index 92% rename from acceptance/openstack/identity/v3/reauth_test.go rename to internal/acceptance/openstack/identity/v3/reauth_test.go index f34a997adb..0c1b74991d 100644 --- a/acceptance/openstack/identity/v3/reauth_test.go +++ b/internal/acceptance/openstack/identity/v3/reauth_test.go @@ -6,7 +6,7 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/identity/v3/regions_test.go b/internal/acceptance/openstack/identity/v3/regions_test.go similarity index 94% rename from acceptance/openstack/identity/v3/regions_test.go rename to internal/acceptance/openstack/identity/v3/regions_test.go index 8bc9d41f02..3b1173555d 100644 --- a/acceptance/openstack/identity/v3/regions_test.go +++ b/internal/acceptance/openstack/identity/v3/regions_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/regions" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/identity/v3/registeredlimits_test.go b/internal/acceptance/openstack/identity/v3/registeredlimits_test.go similarity index 96% rename from acceptance/openstack/identity/v3/registeredlimits_test.go rename to internal/acceptance/openstack/identity/v3/registeredlimits_test.go index 8fd24f4a5a..fa3f910559 100644 --- a/acceptance/openstack/identity/v3/registeredlimits_test.go +++ b/internal/acceptance/openstack/identity/v3/registeredlimits_test.go @@ -7,8 +7,8 @@ import ( "os" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/registeredlimits" "github.com/gophercloud/gophercloud/openstack/identity/v3/services" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/identity/v3/roles_test.go b/internal/acceptance/openstack/identity/v3/roles_test.go similarity index 99% rename from acceptance/openstack/identity/v3/roles_test.go rename to internal/acceptance/openstack/identity/v3/roles_test.go index f61bddf0a4..cd8f6c5523 100644 --- a/acceptance/openstack/identity/v3/roles_test.go +++ b/internal/acceptance/openstack/identity/v3/roles_test.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/domains" "github.com/gophercloud/gophercloud/openstack/identity/v3/groups" "github.com/gophercloud/gophercloud/openstack/identity/v3/roles" diff --git a/acceptance/openstack/identity/v3/service_test.go b/internal/acceptance/openstack/identity/v3/service_test.go similarity index 92% rename from acceptance/openstack/identity/v3/service_test.go rename to internal/acceptance/openstack/identity/v3/service_test.go index 246d9d8ec3..38eee8a4b9 100644 --- a/acceptance/openstack/identity/v3/service_test.go +++ b/internal/acceptance/openstack/identity/v3/service_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/services" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/identity/v3/token_test.go b/internal/acceptance/openstack/identity/v3/token_test.go similarity index 89% rename from acceptance/openstack/identity/v3/token_test.go rename to internal/acceptance/openstack/identity/v3/token_test.go index 85ae0eff67..e2d052d4d2 100644 --- a/acceptance/openstack/identity/v3/token_test.go +++ b/internal/acceptance/openstack/identity/v3/token_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack" "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/identity/v3/trusts_test.go b/internal/acceptance/openstack/identity/v3/trusts_test.go similarity index 96% rename from acceptance/openstack/identity/v3/trusts_test.go rename to internal/acceptance/openstack/identity/v3/trusts_test.go index 66dd42d08c..63b5c1afb7 100644 --- a/acceptance/openstack/identity/v3/trusts_test.go +++ b/internal/acceptance/openstack/identity/v3/trusts_test.go @@ -7,8 +7,8 @@ import ( "testing" "time" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack" "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts" "github.com/gophercloud/gophercloud/openstack/identity/v3/roles" diff --git a/acceptance/openstack/identity/v3/users_test.go b/internal/acceptance/openstack/identity/v3/users_test.go similarity index 98% rename from acceptance/openstack/identity/v3/users_test.go rename to internal/acceptance/openstack/identity/v3/users_test.go index a5edb00854..9379a20930 100644 --- a/acceptance/openstack/identity/v3/users_test.go +++ b/internal/acceptance/openstack/identity/v3/users_test.go @@ -6,8 +6,8 @@ package v3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/identity/v3/groups" "github.com/gophercloud/gophercloud/openstack/identity/v3/projects" "github.com/gophercloud/gophercloud/openstack/identity/v3/users" diff --git a/acceptance/openstack/imageservice/v2/imagedata_test.go b/internal/acceptance/openstack/imageservice/v2/imagedata_test.go similarity index 82% rename from acceptance/openstack/imageservice/v2/imagedata_test.go rename to internal/acceptance/openstack/imageservice/v2/imagedata_test.go index d19c38d4a9..d5c1c6f260 100644 --- a/acceptance/openstack/imageservice/v2/imagedata_test.go +++ b/internal/acceptance/openstack/imageservice/v2/imagedata_test.go @@ -3,8 +3,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/imageservice/v2/imageimport_test.go b/internal/acceptance/openstack/imageservice/v2/imageimport_test.go similarity index 84% rename from acceptance/openstack/imageservice/v2/imageimport_test.go rename to internal/acceptance/openstack/imageservice/v2/imageimport_test.go index 53dbea4d3d..4d032dbfb3 100644 --- a/acceptance/openstack/imageservice/v2/imageimport_test.go +++ b/internal/acceptance/openstack/imageservice/v2/imageimport_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/imageservice/v2/images_test.go b/internal/acceptance/openstack/imageservice/v2/images_test.go similarity index 97% rename from acceptance/openstack/imageservice/v2/images_test.go rename to internal/acceptance/openstack/imageservice/v2/images_test.go index ac6008cef8..a904471c5d 100644 --- a/acceptance/openstack/imageservice/v2/images_test.go +++ b/internal/acceptance/openstack/imageservice/v2/images_test.go @@ -8,8 +8,8 @@ import ( "testing" "time" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/imageservice/v2/imageservice.go b/internal/acceptance/openstack/imageservice/v2/imageservice.go similarity index 98% rename from acceptance/openstack/imageservice/v2/imageservice.go rename to internal/acceptance/openstack/imageservice/v2/imageservice.go index fd55741aa6..f093fe3123 100644 --- a/acceptance/openstack/imageservice/v2/imageservice.go +++ b/internal/acceptance/openstack/imageservice/v2/imageservice.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata" "github.com/gophercloud/gophercloud/openstack/imageservice/v2/imageimport" "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images" diff --git a/acceptance/openstack/imageservice/v2/tasks_test.go b/internal/acceptance/openstack/imageservice/v2/tasks_test.go similarity index 91% rename from acceptance/openstack/imageservice/v2/tasks_test.go rename to internal/acceptance/openstack/imageservice/v2/tasks_test.go index b06980c761..e751118797 100644 --- a/acceptance/openstack/imageservice/v2/tasks_test.go +++ b/internal/acceptance/openstack/imageservice/v2/tasks_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/imageservice/v2/tasks" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/keymanager/v1/acls_test.go b/internal/acceptance/openstack/keymanager/v1/acls_test.go similarity index 96% rename from acceptance/openstack/keymanager/v1/acls_test.go rename to internal/acceptance/openstack/keymanager/v1/acls_test.go index 5defa5b78e..5638443078 100644 --- a/acceptance/openstack/keymanager/v1/acls_test.go +++ b/internal/acceptance/openstack/keymanager/v1/acls_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/keymanager/v1/acls" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/keymanager/v1/containers_test.go b/internal/acceptance/openstack/keymanager/v1/containers_test.go similarity index 97% rename from acceptance/openstack/keymanager/v1/containers_test.go rename to internal/acceptance/openstack/keymanager/v1/containers_test.go index b4699b3dee..cf7e162f8f 100644 --- a/acceptance/openstack/keymanager/v1/containers_test.go +++ b/internal/acceptance/openstack/keymanager/v1/containers_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/keymanager/v1/containers" "github.com/gophercloud/gophercloud/openstack/keymanager/v1/secrets" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/keymanager/v1/keymanager.go b/internal/acceptance/openstack/keymanager/v1/keymanager.go similarity index 99% rename from acceptance/openstack/keymanager/v1/keymanager.go rename to internal/acceptance/openstack/keymanager/v1/keymanager.go index e4b6f95015..c0e9dd2728 100644 --- a/acceptance/openstack/keymanager/v1/keymanager.go +++ b/internal/acceptance/openstack/keymanager/v1/keymanager.go @@ -15,7 +15,7 @@ import ( "time" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/keymanager/v1/containers" "github.com/gophercloud/gophercloud/openstack/keymanager/v1/orders" "github.com/gophercloud/gophercloud/openstack/keymanager/v1/secrets" diff --git a/acceptance/openstack/keymanager/v1/orders_test.go b/internal/acceptance/openstack/keymanager/v1/orders_test.go similarity index 94% rename from acceptance/openstack/keymanager/v1/orders_test.go rename to internal/acceptance/openstack/keymanager/v1/orders_test.go index cb9095af4f..f300f8fa7e 100644 --- a/acceptance/openstack/keymanager/v1/orders_test.go +++ b/internal/acceptance/openstack/keymanager/v1/orders_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/keymanager/v1/containers" "github.com/gophercloud/gophercloud/openstack/keymanager/v1/orders" "github.com/gophercloud/gophercloud/openstack/keymanager/v1/secrets" diff --git a/acceptance/openstack/keymanager/v1/secrets_test.go b/internal/acceptance/openstack/keymanager/v1/secrets_test.go similarity index 98% rename from acceptance/openstack/keymanager/v1/secrets_test.go rename to internal/acceptance/openstack/keymanager/v1/secrets_test.go index 761ffc1338..59c989bb2e 100644 --- a/acceptance/openstack/keymanager/v1/secrets_test.go +++ b/internal/acceptance/openstack/keymanager/v1/secrets_test.go @@ -7,8 +7,8 @@ import ( "testing" "time" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/keymanager/v1/secrets" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/loadbalancer/v2/amphorae_test.go b/internal/acceptance/openstack/loadbalancer/v2/amphorae_test.go similarity index 84% rename from acceptance/openstack/loadbalancer/v2/amphorae_test.go rename to internal/acceptance/openstack/loadbalancer/v2/amphorae_test.go index 42c14300bb..b2ec529e3f 100644 --- a/acceptance/openstack/loadbalancer/v2/amphorae_test.go +++ b/internal/acceptance/openstack/loadbalancer/v2/amphorae_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/amphorae" ) diff --git a/acceptance/openstack/loadbalancer/v2/l7policies_test.go b/internal/acceptance/openstack/loadbalancer/v2/l7policies_test.go similarity index 85% rename from acceptance/openstack/loadbalancer/v2/l7policies_test.go rename to internal/acceptance/openstack/loadbalancer/v2/l7policies_test.go index 3ad3c9755b..66c6422d6e 100644 --- a/acceptance/openstack/loadbalancer/v2/l7policies_test.go +++ b/internal/acceptance/openstack/loadbalancer/v2/l7policies_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies" ) diff --git a/acceptance/openstack/loadbalancer/v2/listeners_test.go b/internal/acceptance/openstack/loadbalancer/v2/listeners_test.go similarity index 85% rename from acceptance/openstack/loadbalancer/v2/listeners_test.go rename to internal/acceptance/openstack/loadbalancer/v2/listeners_test.go index ff06f4af41..a760224ee8 100644 --- a/acceptance/openstack/loadbalancer/v2/listeners_test.go +++ b/internal/acceptance/openstack/loadbalancer/v2/listeners_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners" ) diff --git a/acceptance/openstack/loadbalancer/v2/loadbalancer.go b/internal/acceptance/openstack/loadbalancer/v2/loadbalancer.go similarity index 99% rename from acceptance/openstack/loadbalancer/v2/loadbalancer.go rename to internal/acceptance/openstack/loadbalancer/v2/loadbalancer.go index eb11d68c17..72bd638ad0 100644 --- a/acceptance/openstack/loadbalancer/v2/loadbalancer.go +++ b/internal/acceptance/openstack/loadbalancer/v2/loadbalancer.go @@ -6,8 +6,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers" diff --git a/acceptance/openstack/loadbalancer/v2/loadbalancers_test.go b/internal/acceptance/openstack/loadbalancer/v2/loadbalancers_test.go similarity index 98% rename from acceptance/openstack/loadbalancer/v2/loadbalancers_test.go rename to internal/acceptance/openstack/loadbalancer/v2/loadbalancers_test.go index 2a987bd9b9..f18f0abdae 100644 --- a/acceptance/openstack/loadbalancer/v2/loadbalancers_test.go +++ b/internal/acceptance/openstack/loadbalancer/v2/loadbalancers_test.go @@ -6,10 +6,10 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions/qos/policies" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2/extensions/qos/policies" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers" diff --git a/acceptance/openstack/loadbalancer/v2/monitors_test.go b/internal/acceptance/openstack/loadbalancer/v2/monitors_test.go similarity index 84% rename from acceptance/openstack/loadbalancer/v2/monitors_test.go rename to internal/acceptance/openstack/loadbalancer/v2/monitors_test.go index a721f51438..483b0cef51 100644 --- a/acceptance/openstack/loadbalancer/v2/monitors_test.go +++ b/internal/acceptance/openstack/loadbalancer/v2/monitors_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors" ) diff --git a/acceptance/openstack/loadbalancer/v2/pkg.go b/internal/acceptance/openstack/loadbalancer/v2/pkg.go similarity index 100% rename from acceptance/openstack/loadbalancer/v2/pkg.go rename to internal/acceptance/openstack/loadbalancer/v2/pkg.go diff --git a/acceptance/openstack/loadbalancer/v2/pools_test.go b/internal/acceptance/openstack/loadbalancer/v2/pools_test.go similarity index 84% rename from acceptance/openstack/loadbalancer/v2/pools_test.go rename to internal/acceptance/openstack/loadbalancer/v2/pools_test.go index 8a9724dd94..9ae691f9e8 100644 --- a/acceptance/openstack/loadbalancer/v2/pools_test.go +++ b/internal/acceptance/openstack/loadbalancer/v2/pools_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools" ) diff --git a/acceptance/openstack/loadbalancer/v2/providers_test.go b/internal/acceptance/openstack/loadbalancer/v2/providers_test.go similarity index 85% rename from acceptance/openstack/loadbalancer/v2/providers_test.go rename to internal/acceptance/openstack/loadbalancer/v2/providers_test.go index c65511bbf9..f71cb191c9 100644 --- a/acceptance/openstack/loadbalancer/v2/providers_test.go +++ b/internal/acceptance/openstack/loadbalancer/v2/providers_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/providers" ) diff --git a/acceptance/openstack/loadbalancer/v2/quotas_test.go b/internal/acceptance/openstack/loadbalancer/v2/quotas_test.go similarity index 94% rename from acceptance/openstack/loadbalancer/v2/quotas_test.go rename to internal/acceptance/openstack/loadbalancer/v2/quotas_test.go index 35dcb2e54a..e88dca5b44 100644 --- a/acceptance/openstack/loadbalancer/v2/quotas_test.go +++ b/internal/acceptance/openstack/loadbalancer/v2/quotas_test.go @@ -10,8 +10,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/quotas" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/messaging/v2/claims_test.go b/internal/acceptance/openstack/messaging/v2/claims_test.go similarity index 92% rename from acceptance/openstack/messaging/v2/claims_test.go rename to internal/acceptance/openstack/messaging/v2/claims_test.go index 32fa87862f..d08ed61b2a 100644 --- a/acceptance/openstack/messaging/v2/claims_test.go +++ b/internal/acceptance/openstack/messaging/v2/claims_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/messaging/v2/claims" ) diff --git a/acceptance/openstack/messaging/v2/message_test.go b/internal/acceptance/openstack/messaging/v2/message_test.go similarity index 98% rename from acceptance/openstack/messaging/v2/message_test.go rename to internal/acceptance/openstack/messaging/v2/message_test.go index b562023c61..bef7c4b94a 100644 --- a/acceptance/openstack/messaging/v2/message_test.go +++ b/internal/acceptance/openstack/messaging/v2/message_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/messaging/v2/messages" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/messaging/v2/messaging.go b/internal/acceptance/openstack/messaging/v2/messaging.go similarity index 98% rename from acceptance/openstack/messaging/v2/messaging.go rename to internal/acceptance/openstack/messaging/v2/messaging.go index 09f2641e09..00513b7e24 100644 --- a/acceptance/openstack/messaging/v2/messaging.go +++ b/internal/acceptance/openstack/messaging/v2/messaging.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/messaging/v2/claims" "github.com/gophercloud/gophercloud/openstack/messaging/v2/messages" "github.com/gophercloud/gophercloud/openstack/messaging/v2/queues" diff --git a/acceptance/openstack/messaging/v2/queue_test.go b/internal/acceptance/openstack/messaging/v2/queue_test.go similarity index 96% rename from acceptance/openstack/messaging/v2/queue_test.go rename to internal/acceptance/openstack/messaging/v2/queue_test.go index c34d104ef5..bdbc5885ec 100644 --- a/acceptance/openstack/messaging/v2/queue_test.go +++ b/internal/acceptance/openstack/messaging/v2/queue_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/messaging/v2/queues" "github.com/gophercloud/gophercloud/pagination" ) diff --git a/acceptance/openstack/networking/v2/apiversion_test.go b/internal/acceptance/openstack/networking/v2/apiversion_test.go similarity index 90% rename from acceptance/openstack/networking/v2/apiversion_test.go rename to internal/acceptance/openstack/networking/v2/apiversion_test.go index 9ad3e9212b..ab89b438fd 100644 --- a/acceptance/openstack/networking/v2/apiversion_test.go +++ b/internal/acceptance/openstack/networking/v2/apiversion_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/apiversions" ) diff --git a/acceptance/openstack/networking/v2/extension_test.go b/internal/acceptance/openstack/networking/v2/extension_test.go similarity index 88% rename from acceptance/openstack/networking/v2/extension_test.go rename to internal/acceptance/openstack/networking/v2/extension_test.go index 4fed3e1fd9..06c6c632c1 100644 --- a/acceptance/openstack/networking/v2/extension_test.go +++ b/internal/acceptance/openstack/networking/v2/extension_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/common/extensions" ) diff --git a/acceptance/openstack/networking/v2/extensions/agents/agents_test.go b/internal/acceptance/openstack/networking/v2/extensions/agents/agents_test.go similarity index 94% rename from acceptance/openstack/networking/v2/extensions/agents/agents_test.go rename to internal/acceptance/openstack/networking/v2/extensions/agents/agents_test.go index db34e75a1c..b9186e3bde 100644 --- a/acceptance/openstack/networking/v2/extensions/agents/agents_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/agents/agents_test.go @@ -7,10 +7,10 @@ import ( "testing" "time" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - spk "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions/bgp/speakers" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + spk "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2/extensions/bgp/speakers" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/agents" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/bgp/speakers" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/agents/doc.go b/internal/acceptance/openstack/networking/v2/extensions/agents/doc.go similarity index 100% rename from acceptance/openstack/networking/v2/extensions/agents/doc.go rename to internal/acceptance/openstack/networking/v2/extensions/agents/doc.go diff --git a/acceptance/openstack/networking/v2/extensions/attributestags_test.go b/internal/acceptance/openstack/networking/v2/extensions/attributestags_test.go similarity index 95% rename from acceptance/openstack/networking/v2/extensions/attributestags_test.go rename to internal/acceptance/openstack/networking/v2/extensions/attributestags_test.go index b30a10e894..f9843281a9 100644 --- a/acceptance/openstack/networking/v2/extensions/attributestags_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/attributestags_test.go @@ -9,9 +9,9 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/attributestags" "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/bgp/peers/bgppeers_test.go b/internal/acceptance/openstack/networking/v2/extensions/bgp/peers/bgppeers_test.go similarity index 92% rename from acceptance/openstack/networking/v2/extensions/bgp/peers/bgppeers_test.go rename to internal/acceptance/openstack/networking/v2/extensions/bgp/peers/bgppeers_test.go index 37a2e7f94a..28e790b901 100644 --- a/acceptance/openstack/networking/v2/extensions/bgp/peers/bgppeers_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/bgp/peers/bgppeers_test.go @@ -3,8 +3,8 @@ package peers import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/bgp/peers" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/bgp/peers/doc.go b/internal/acceptance/openstack/networking/v2/extensions/bgp/peers/doc.go similarity index 100% rename from acceptance/openstack/networking/v2/extensions/bgp/peers/doc.go rename to internal/acceptance/openstack/networking/v2/extensions/bgp/peers/doc.go diff --git a/acceptance/openstack/networking/v2/extensions/bgp/peers/peers.go b/internal/acceptance/openstack/networking/v2/extensions/bgp/peers/peers.go similarity index 93% rename from acceptance/openstack/networking/v2/extensions/bgp/peers/peers.go rename to internal/acceptance/openstack/networking/v2/extensions/bgp/peers/peers.go index cd0b102dab..b92a488edf 100644 --- a/acceptance/openstack/networking/v2/extensions/bgp/peers/peers.go +++ b/internal/acceptance/openstack/networking/v2/extensions/bgp/peers/peers.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/bgp/peers" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/bgp/speakers/bgpspeakers_test.go b/internal/acceptance/openstack/networking/v2/extensions/bgp/speakers/bgpspeakers_test.go similarity index 92% rename from acceptance/openstack/networking/v2/extensions/bgp/speakers/bgpspeakers_test.go rename to internal/acceptance/openstack/networking/v2/extensions/bgp/speakers/bgpspeakers_test.go index 9a7a9f3cde..2f45251cf7 100644 --- a/acceptance/openstack/networking/v2/extensions/bgp/speakers/bgpspeakers_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/bgp/speakers/bgpspeakers_test.go @@ -3,10 +3,10 @@ package speakers import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - ap "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions/bgp/peers" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + ap "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2/extensions/bgp/peers" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/bgp/peers" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/bgp/speakers" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/bgp/speakers/doc.go b/internal/acceptance/openstack/networking/v2/extensions/bgp/speakers/doc.go similarity index 100% rename from acceptance/openstack/networking/v2/extensions/bgp/speakers/doc.go rename to internal/acceptance/openstack/networking/v2/extensions/bgp/speakers/doc.go diff --git a/acceptance/openstack/networking/v2/extensions/bgp/speakers/speakers.go b/internal/acceptance/openstack/networking/v2/extensions/bgp/speakers/speakers.go similarity index 95% rename from acceptance/openstack/networking/v2/extensions/bgp/speakers/speakers.go rename to internal/acceptance/openstack/networking/v2/extensions/bgp/speakers/speakers.go index 00b706c53e..9a04eae2a9 100644 --- a/acceptance/openstack/networking/v2/extensions/bgp/speakers/speakers.go +++ b/internal/acceptance/openstack/networking/v2/extensions/bgp/speakers/speakers.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/bgp/speakers" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/dns/dns.go b/internal/acceptance/openstack/networking/v2/extensions/dns/dns.go similarity index 98% rename from acceptance/openstack/networking/v2/extensions/dns/dns.go rename to internal/acceptance/openstack/networking/v2/extensions/dns/dns.go index e6f5b2e20e..72fc944ecf 100644 --- a/acceptance/openstack/networking/v2/extensions/dns/dns.go +++ b/internal/acceptance/openstack/networking/v2/extensions/dns/dns.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/dns" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" diff --git a/acceptance/openstack/networking/v2/extensions/dns/dns_test.go b/internal/acceptance/openstack/networking/v2/extensions/dns/dns_test.go similarity index 95% rename from acceptance/openstack/networking/v2/extensions/dns/dns_test.go rename to internal/acceptance/openstack/networking/v2/extensions/dns/dns_test.go index 005d470b23..654112fe74 100644 --- a/acceptance/openstack/networking/v2/extensions/dns/dns_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/dns/dns_test.go @@ -7,10 +7,10 @@ import ( "os" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions/layer3" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2/extensions/layer3" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/common/extensions" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/dns" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" diff --git a/acceptance/openstack/networking/v2/extensions/extensions.go b/internal/acceptance/openstack/networking/v2/extensions/extensions.go similarity index 98% rename from acceptance/openstack/networking/v2/extensions/extensions.go rename to internal/acceptance/openstack/networking/v2/extensions/extensions.go index fe2999d066..83f64bd6ad 100644 --- a/acceptance/openstack/networking/v2/extensions/extensions.go +++ b/internal/acceptance/openstack/networking/v2/extensions/extensions.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules" diff --git a/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go b/internal/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go similarity index 95% rename from acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go rename to internal/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go index 95533af241..2a1079c8ed 100644 --- a/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go @@ -6,9 +6,9 @@ package fwaas import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - layer3 "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions/layer3" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + layer3 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2/extensions/layer3" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/routerinsertion" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/fwaas/fwaas.go b/internal/acceptance/openstack/networking/v2/extensions/fwaas/fwaas.go similarity index 99% rename from acceptance/openstack/networking/v2/extensions/fwaas/fwaas.go rename to internal/acceptance/openstack/networking/v2/extensions/fwaas/fwaas.go index 5f5bde95ff..4169e84288 100644 --- a/acceptance/openstack/networking/v2/extensions/fwaas/fwaas.go +++ b/internal/acceptance/openstack/networking/v2/extensions/fwaas/fwaas.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/policies" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/routerinsertion" diff --git a/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go b/internal/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go similarity index 91% rename from acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go rename to internal/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go index a10839b8f4..1a474e83cc 100644 --- a/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go @@ -6,8 +6,8 @@ package fwaas import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/policies" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go b/internal/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go similarity index 90% rename from acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go rename to internal/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go index 343211990e..59a4ad19f5 100644 --- a/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go @@ -6,8 +6,8 @@ package fwaas import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/rules" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/fwaas_v2/fwaas_v2.go b/internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/fwaas_v2.go similarity index 98% rename from acceptance/openstack/networking/v2/extensions/fwaas_v2/fwaas_v2.go rename to internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/fwaas_v2.go index 57a621a8bd..d99106bf35 100644 --- a/acceptance/openstack/networking/v2/extensions/fwaas_v2/fwaas_v2.go +++ b/internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/fwaas_v2.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas_v2/groups" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas_v2/policies" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas_v2/rules" diff --git a/acceptance/openstack/networking/v2/extensions/fwaas_v2/groups_test.go b/internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/groups_test.go similarity index 96% rename from acceptance/openstack/networking/v2/extensions/fwaas_v2/groups_test.go rename to internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/groups_test.go index 0183f3c8ab..c09f3ab130 100644 --- a/acceptance/openstack/networking/v2/extensions/fwaas_v2/groups_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/groups_test.go @@ -6,8 +6,8 @@ package fwaas_v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas_v2/groups" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/fwaas_v2/policy_test.go b/internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/policy_test.go similarity index 94% rename from acceptance/openstack/networking/v2/extensions/fwaas_v2/policy_test.go rename to internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/policy_test.go index b2cc55ae64..2a375f2584 100644 --- a/acceptance/openstack/networking/v2/extensions/fwaas_v2/policy_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/policy_test.go @@ -6,8 +6,8 @@ package fwaas_v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas_v2/policies" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/fwaas_v2/rule_test.go b/internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/rule_test.go similarity index 93% rename from acceptance/openstack/networking/v2/extensions/fwaas_v2/rule_test.go rename to internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/rule_test.go index 43549fd622..c6eb6d2332 100644 --- a/acceptance/openstack/networking/v2/extensions/fwaas_v2/rule_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/rule_test.go @@ -8,8 +8,8 @@ import ( "strconv" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas_v2/rules" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/layer3/addressscopes_test.go b/internal/acceptance/openstack/networking/v2/extensions/layer3/addressscopes_test.go similarity index 91% rename from acceptance/openstack/networking/v2/extensions/layer3/addressscopes_test.go rename to internal/acceptance/openstack/networking/v2/extensions/layer3/addressscopes_test.go index 1687b148b3..6b4384422d 100644 --- a/acceptance/openstack/networking/v2/extensions/layer3/addressscopes_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/layer3/addressscopes_test.go @@ -6,8 +6,8 @@ package layer3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/addressscopes" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/layer3/extraroutes_test.go b/internal/acceptance/openstack/networking/v2/extensions/layer3/extraroutes_test.go similarity index 92% rename from acceptance/openstack/networking/v2/extensions/layer3/extraroutes_test.go rename to internal/acceptance/openstack/networking/v2/extensions/layer3/extraroutes_test.go index b5b4c9180e..ccf1e545be 100644 --- a/acceptance/openstack/networking/v2/extensions/layer3/extraroutes_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/layer3/extraroutes_test.go @@ -8,9 +8,9 @@ import ( "net" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/extraroutes" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go b/internal/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go similarity index 96% rename from acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go rename to internal/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go index 81d1d18f05..93dec689fa 100644 --- a/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go @@ -6,9 +6,9 @@ package layer3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/layer3/l3_scheduling_test.go b/internal/acceptance/openstack/networking/v2/extensions/layer3/l3_scheduling_test.go similarity index 92% rename from acceptance/openstack/networking/v2/extensions/layer3/l3_scheduling_test.go rename to internal/acceptance/openstack/networking/v2/extensions/layer3/l3_scheduling_test.go index ec32dfda11..34d91ca29c 100644 --- a/acceptance/openstack/networking/v2/extensions/layer3/l3_scheduling_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/layer3/l3_scheduling_test.go @@ -6,9 +6,9 @@ package layer3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/common/extensions" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/agents" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers" diff --git a/acceptance/openstack/networking/v2/extensions/layer3/layer3.go b/internal/acceptance/openstack/networking/v2/extensions/layer3/layer3.go similarity index 98% rename from acceptance/openstack/networking/v2/extensions/layer3/layer3.go rename to internal/acceptance/openstack/networking/v2/extensions/layer3/layer3.go index 6c1cdca080..8e4f5e8590 100644 --- a/acceptance/openstack/networking/v2/extensions/layer3/layer3.go +++ b/internal/acceptance/openstack/networking/v2/extensions/layer3/layer3.go @@ -6,8 +6,8 @@ import ( "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/addressscopes" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/portforwarding" diff --git a/acceptance/openstack/networking/v2/extensions/layer3/portforwardings_test.go b/internal/acceptance/openstack/networking/v2/extensions/layer3/portforwardings_test.go similarity index 91% rename from acceptance/openstack/networking/v2/extensions/layer3/portforwardings_test.go rename to internal/acceptance/openstack/networking/v2/extensions/layer3/portforwardings_test.go index 0aa35e0d3b..f5ae90b252 100644 --- a/acceptance/openstack/networking/v2/extensions/layer3/portforwardings_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/layer3/portforwardings_test.go @@ -3,9 +3,9 @@ package layer3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/portforwarding" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/layer3/routers_test.go b/internal/acceptance/openstack/networking/v2/extensions/layer3/routers_test.go similarity index 96% rename from acceptance/openstack/networking/v2/extensions/layer3/routers_test.go rename to internal/acceptance/openstack/networking/v2/extensions/layer3/routers_test.go index c4bb5eb40e..91e5af616a 100644 --- a/acceptance/openstack/networking/v2/extensions/layer3/routers_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/layer3/routers_test.go @@ -6,9 +6,9 @@ package layer3 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/lbaas.go b/internal/acceptance/openstack/networking/v2/extensions/lbaas/lbaas.go similarity index 98% rename from acceptance/openstack/networking/v2/extensions/lbaas/lbaas.go rename to internal/acceptance/openstack/networking/v2/extensions/lbaas/lbaas.go index b31d3e5b42..90b54ef253 100644 --- a/acceptance/openstack/networking/v2/extensions/lbaas/lbaas.go +++ b/internal/acceptance/openstack/networking/v2/extensions/lbaas/lbaas.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools" diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/members_test.go b/internal/acceptance/openstack/networking/v2/extensions/lbaas/members_test.go similarity index 90% rename from acceptance/openstack/networking/v2/extensions/lbaas/members_test.go rename to internal/acceptance/openstack/networking/v2/extensions/lbaas/members_test.go index 78be8832d4..93cdfe4984 100644 --- a/acceptance/openstack/networking/v2/extensions/lbaas/members_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/lbaas/members_test.go @@ -7,9 +7,9 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members" ) diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/monitors_test.go b/internal/acceptance/openstack/networking/v2/extensions/lbaas/monitors_test.go similarity index 92% rename from acceptance/openstack/networking/v2/extensions/lbaas/monitors_test.go rename to internal/acceptance/openstack/networking/v2/extensions/lbaas/monitors_test.go index 27ea62158b..e871065e6c 100644 --- a/acceptance/openstack/networking/v2/extensions/lbaas/monitors_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/lbaas/monitors_test.go @@ -6,8 +6,8 @@ package lbaas import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors" ) diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/pools_test.go b/internal/acceptance/openstack/networking/v2/extensions/lbaas/pools_test.go similarity index 93% rename from acceptance/openstack/networking/v2/extensions/lbaas/pools_test.go rename to internal/acceptance/openstack/networking/v2/extensions/lbaas/pools_test.go index 0c8ba65d0c..4019b08ba3 100644 --- a/acceptance/openstack/networking/v2/extensions/lbaas/pools_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/lbaas/pools_test.go @@ -6,9 +6,9 @@ package lbaas import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools" ) diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/vips_test.go b/internal/acceptance/openstack/networking/v2/extensions/lbaas/vips_test.go similarity index 90% rename from acceptance/openstack/networking/v2/extensions/lbaas/vips_test.go rename to internal/acceptance/openstack/networking/v2/extensions/lbaas/vips_test.go index a954f25e28..3ae32d445e 100644 --- a/acceptance/openstack/networking/v2/extensions/lbaas/vips_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/lbaas/vips_test.go @@ -6,9 +6,9 @@ package lbaas import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips" ) diff --git a/acceptance/openstack/networking/v2/extensions/lbaas_v2/l7policies_test.go b/internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/l7policies_test.go similarity index 86% rename from acceptance/openstack/networking/v2/extensions/lbaas_v2/l7policies_test.go rename to internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/l7policies_test.go index aa69b9e448..4aa1fa9aea 100644 --- a/acceptance/openstack/networking/v2/extensions/lbaas_v2/l7policies_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/l7policies_test.go @@ -6,8 +6,8 @@ package lbaas_v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies" ) diff --git a/acceptance/openstack/networking/v2/extensions/lbaas_v2/lbaas_v2.go b/internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/lbaas_v2.go similarity index 99% rename from acceptance/openstack/networking/v2/extensions/lbaas_v2/lbaas_v2.go rename to internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/lbaas_v2.go index 13fddaf803..897d66c568 100644 --- a/acceptance/openstack/networking/v2/extensions/lbaas_v2/lbaas_v2.go +++ b/internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/lbaas_v2.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers" diff --git a/acceptance/openstack/networking/v2/extensions/lbaas_v2/listeners_test.go b/internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/listeners_test.go similarity index 86% rename from acceptance/openstack/networking/v2/extensions/lbaas_v2/listeners_test.go rename to internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/listeners_test.go index 72d4b72282..2feb6d9ace 100644 --- a/acceptance/openstack/networking/v2/extensions/lbaas_v2/listeners_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/listeners_test.go @@ -6,8 +6,8 @@ package lbaas_v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners" ) diff --git a/acceptance/openstack/networking/v2/extensions/lbaas_v2/loadbalancers_test.go b/internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/loadbalancers_test.go similarity index 97% rename from acceptance/openstack/networking/v2/extensions/lbaas_v2/loadbalancers_test.go rename to internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/loadbalancers_test.go index 8529deb957..11ee1f8ce0 100644 --- a/acceptance/openstack/networking/v2/extensions/lbaas_v2/loadbalancers_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/loadbalancers_test.go @@ -6,9 +6,9 @@ package lbaas_v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/l7policies" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers" diff --git a/acceptance/openstack/networking/v2/extensions/lbaas_v2/monitors_test.go b/internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/monitors_test.go similarity index 86% rename from acceptance/openstack/networking/v2/extensions/lbaas_v2/monitors_test.go rename to internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/monitors_test.go index 18e145bc90..2450bfd687 100644 --- a/acceptance/openstack/networking/v2/extensions/lbaas_v2/monitors_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/monitors_test.go @@ -6,8 +6,8 @@ package lbaas_v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors" ) diff --git a/acceptance/openstack/networking/v2/extensions/lbaas_v2/pools_test.go b/internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/pools_test.go similarity index 86% rename from acceptance/openstack/networking/v2/extensions/lbaas_v2/pools_test.go rename to internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/pools_test.go index 69c4f6e1fc..efc2978cbd 100644 --- a/acceptance/openstack/networking/v2/extensions/lbaas_v2/pools_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/lbaas_v2/pools_test.go @@ -6,8 +6,8 @@ package lbaas_v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools" ) diff --git a/acceptance/openstack/networking/v2/extensions/mtu/mtu.go b/internal/acceptance/openstack/networking/v2/extensions/mtu/mtu.go similarity index 96% rename from acceptance/openstack/networking/v2/extensions/mtu/mtu.go rename to internal/acceptance/openstack/networking/v2/extensions/mtu/mtu.go index 36c06f9e8d..a02053f724 100644 --- a/acceptance/openstack/networking/v2/extensions/mtu/mtu.go +++ b/internal/acceptance/openstack/networking/v2/extensions/mtu/mtu.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/mtu" "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/mtu/mtu_test.go b/internal/acceptance/openstack/networking/v2/extensions/mtu/mtu_test.go similarity index 94% rename from acceptance/openstack/networking/v2/extensions/mtu/mtu_test.go rename to internal/acceptance/openstack/networking/v2/extensions/mtu/mtu_test.go index 8264d2d504..7b10c99434 100644 --- a/acceptance/openstack/networking/v2/extensions/mtu/mtu_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/mtu/mtu_test.go @@ -6,9 +6,9 @@ package mtu import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/common/extensions" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/mtu" "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" diff --git a/acceptance/openstack/networking/v2/extensions/networkipavailabilities/networkipavailabilities_test.go b/internal/acceptance/openstack/networking/v2/extensions/networkipavailabilities/networkipavailabilities_test.go similarity index 87% rename from acceptance/openstack/networking/v2/extensions/networkipavailabilities/networkipavailabilities_test.go rename to internal/acceptance/openstack/networking/v2/extensions/networkipavailabilities/networkipavailabilities_test.go index 14b7106e29..e0bcebc1f7 100644 --- a/acceptance/openstack/networking/v2/extensions/networkipavailabilities/networkipavailabilities_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/networkipavailabilities/networkipavailabilities_test.go @@ -6,8 +6,8 @@ package networkipavailabilities import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/networkipavailabilities" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding.go b/internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding.go similarity index 96% rename from acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding.go rename to internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding.go index 2957176311..607cf1cd9c 100644 --- a/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding.go +++ b/internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsbinding" "github.com/gophercloud/gophercloud/openstack/networking/v2/ports" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go b/internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go similarity index 90% rename from acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go rename to internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go index 8ab86b9ca9..50f5e8c99a 100644 --- a/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go @@ -6,9 +6,9 @@ package portsbinding import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsbinding" "github.com/gophercloud/gophercloud/openstack/networking/v2/ports" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/provider_test.go b/internal/acceptance/openstack/networking/v2/extensions/provider_test.go similarity index 75% rename from acceptance/openstack/networking/v2/extensions/provider_test.go rename to internal/acceptance/openstack/networking/v2/extensions/provider_test.go index 9e8f622d47..6b21141b9a 100644 --- a/acceptance/openstack/networking/v2/extensions/provider_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/provider_test.go @@ -6,9 +6,9 @@ package extensions import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/qos/policies/policies.go b/internal/acceptance/openstack/networking/v2/extensions/qos/policies/policies.go similarity index 95% rename from acceptance/openstack/networking/v2/extensions/qos/policies/policies.go rename to internal/acceptance/openstack/networking/v2/extensions/qos/policies/policies.go index 88b3228df9..91d4a398bc 100644 --- a/acceptance/openstack/networking/v2/extensions/qos/policies/policies.go +++ b/internal/acceptance/openstack/networking/v2/extensions/qos/policies/policies.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/qos/policies" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/qos/policies/policies_test.go b/internal/acceptance/openstack/networking/v2/extensions/qos/policies/policies_test.go similarity index 92% rename from acceptance/openstack/networking/v2/extensions/qos/policies/policies_test.go rename to internal/acceptance/openstack/networking/v2/extensions/qos/policies/policies_test.go index 7dcbd68f1c..4bda08b2d0 100644 --- a/acceptance/openstack/networking/v2/extensions/qos/policies/policies_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/qos/policies/policies_test.go @@ -6,8 +6,8 @@ package policies import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/common/extensions" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/qos/policies" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/qos/rules/rules.go b/internal/acceptance/openstack/networking/v2/extensions/qos/rules/rules.go similarity index 100% rename from acceptance/openstack/networking/v2/extensions/qos/rules/rules.go rename to internal/acceptance/openstack/networking/v2/extensions/qos/rules/rules.go diff --git a/acceptance/openstack/networking/v2/extensions/qos/rules/rules_test.go b/internal/acceptance/openstack/networking/v2/extensions/qos/rules/rules_test.go similarity index 94% rename from acceptance/openstack/networking/v2/extensions/qos/rules/rules_test.go rename to internal/acceptance/openstack/networking/v2/extensions/qos/rules/rules_test.go index 43cfaaedea..8c88e31b0f 100644 --- a/acceptance/openstack/networking/v2/extensions/qos/rules/rules_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/qos/rules/rules_test.go @@ -3,9 +3,9 @@ package rules import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - accpolicies "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions/qos/policies" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + accpolicies "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2/extensions/qos/policies" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/common/extensions" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/qos/policies" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/qos/rules" diff --git a/acceptance/openstack/networking/v2/extensions/qos/ruletypes/ruletypes_test.go b/internal/acceptance/openstack/networking/v2/extensions/qos/ruletypes/ruletypes_test.go similarity index 89% rename from acceptance/openstack/networking/v2/extensions/qos/ruletypes/ruletypes_test.go rename to internal/acceptance/openstack/networking/v2/extensions/qos/ruletypes/ruletypes_test.go index baa44ca05f..df89bff06e 100644 --- a/acceptance/openstack/networking/v2/extensions/qos/ruletypes/ruletypes_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/qos/ruletypes/ruletypes_test.go @@ -3,8 +3,8 @@ package ruletypes import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/common/extensions" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/qos/ruletypes" ) diff --git a/acceptance/openstack/networking/v2/extensions/quotas/quotas.go b/internal/acceptance/openstack/networking/v2/extensions/quotas/quotas.go similarity index 100% rename from acceptance/openstack/networking/v2/extensions/quotas/quotas.go rename to internal/acceptance/openstack/networking/v2/extensions/quotas/quotas.go diff --git a/acceptance/openstack/networking/v2/extensions/quotas/quotas_test.go b/internal/acceptance/openstack/networking/v2/extensions/quotas/quotas_test.go similarity index 93% rename from acceptance/openstack/networking/v2/extensions/quotas/quotas_test.go rename to internal/acceptance/openstack/networking/v2/extensions/quotas/quotas_test.go index c462cd3338..5749c90433 100644 --- a/acceptance/openstack/networking/v2/extensions/quotas/quotas_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/quotas/quotas_test.go @@ -9,8 +9,8 @@ import ( "reflect" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/quotas" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/rbacpolicies/rbacpolicies.go b/internal/acceptance/openstack/networking/v2/extensions/rbacpolicies/rbacpolicies.go similarity index 100% rename from acceptance/openstack/networking/v2/extensions/rbacpolicies/rbacpolicies.go rename to internal/acceptance/openstack/networking/v2/extensions/rbacpolicies/rbacpolicies.go diff --git a/acceptance/openstack/networking/v2/extensions/rbacpolicies/rbacpolicies_test.go b/internal/acceptance/openstack/networking/v2/extensions/rbacpolicies/rbacpolicies_test.go similarity index 87% rename from acceptance/openstack/networking/v2/extensions/rbacpolicies/rbacpolicies_test.go rename to internal/acceptance/openstack/networking/v2/extensions/rbacpolicies/rbacpolicies_test.go index 7b071cb304..8015610a67 100644 --- a/acceptance/openstack/networking/v2/extensions/rbacpolicies/rbacpolicies_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/rbacpolicies/rbacpolicies_test.go @@ -6,10 +6,10 @@ package rbacpolicies import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - projects "github.com/gophercloud/gophercloud/acceptance/openstack/identity/v3" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + projects "github.com/gophercloud/gophercloud/internal/acceptance/openstack/identity/v3" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/rbacpolicies" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/security_test.go b/internal/acceptance/openstack/networking/v2/extensions/security_test.go similarity index 90% rename from acceptance/openstack/networking/v2/extensions/security_test.go rename to internal/acceptance/openstack/networking/v2/extensions/security_test.go index 967177b8cb..aaf772e7d5 100644 --- a/acceptance/openstack/networking/v2/extensions/security_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/security_test.go @@ -6,9 +6,9 @@ package extensions import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools.go b/internal/acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools.go similarity index 96% rename from acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools.go rename to internal/acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools.go index 6380264b10..a7370cc3d5 100644 --- a/acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools.go +++ b/internal/acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/subnetpools" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools_test.go b/internal/acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools_test.go similarity index 91% rename from acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools_test.go rename to internal/acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools_test.go index 0989300019..12301d2b07 100644 --- a/acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/subnetpools/subnetpools_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/subnetpools" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/trunk_details/trunks_test.go b/internal/acceptance/openstack/networking/v2/extensions/trunk_details/trunks_test.go similarity index 93% rename from acceptance/openstack/networking/v2/extensions/trunk_details/trunks_test.go rename to internal/acceptance/openstack/networking/v2/extensions/trunk_details/trunks_test.go index 309d090ffa..d2d5855540 100644 --- a/acceptance/openstack/networking/v2/extensions/trunk_details/trunks_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/trunk_details/trunks_test.go @@ -6,9 +6,9 @@ package trunk_details import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - v2 "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - v2Trunks "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions/trunks" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + v2 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + v2Trunks "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2/extensions/trunks" "github.com/gophercloud/gophercloud/openstack/common/extensions" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunk_details" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks" diff --git a/acceptance/openstack/networking/v2/extensions/trunks/trunks.go b/internal/acceptance/openstack/networking/v2/extensions/trunks/trunks.go similarity index 95% rename from acceptance/openstack/networking/v2/extensions/trunks/trunks.go rename to internal/acceptance/openstack/networking/v2/extensions/trunks/trunks.go index 18fc920fd6..215120dae8 100644 --- a/acceptance/openstack/networking/v2/extensions/trunks/trunks.go +++ b/internal/acceptance/openstack/networking/v2/extensions/trunks/trunks.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks" ) diff --git a/acceptance/openstack/networking/v2/extensions/trunks/trunks_test.go b/internal/acceptance/openstack/networking/v2/extensions/trunks/trunks_test.go similarity index 97% rename from acceptance/openstack/networking/v2/extensions/trunks/trunks_test.go rename to internal/acceptance/openstack/networking/v2/extensions/trunks/trunks_test.go index 0e62059278..a41209c95c 100644 --- a/acceptance/openstack/networking/v2/extensions/trunks/trunks_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/trunks/trunks_test.go @@ -7,9 +7,9 @@ import ( "sort" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - v2 "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + v2 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/common/extensions" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/attributestags" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunks" diff --git a/acceptance/openstack/networking/v2/extensions/vlantransparent/vlantransparent.go b/internal/acceptance/openstack/networking/v2/extensions/vlantransparent/vlantransparent.go similarity index 97% rename from acceptance/openstack/networking/v2/extensions/vlantransparent/vlantransparent.go rename to internal/acceptance/openstack/networking/v2/extensions/vlantransparent/vlantransparent.go index e91ada32d6..e061ea3813 100644 --- a/acceptance/openstack/networking/v2/extensions/vlantransparent/vlantransparent.go +++ b/internal/acceptance/openstack/networking/v2/extensions/vlantransparent/vlantransparent.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/vlantransparent" "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/vlantransparent/vlantransparent_test.go b/internal/acceptance/openstack/networking/v2/extensions/vlantransparent/vlantransparent_test.go similarity index 85% rename from acceptance/openstack/networking/v2/extensions/vlantransparent/vlantransparent_test.go rename to internal/acceptance/openstack/networking/v2/extensions/vlantransparent/vlantransparent_test.go index ff5692752a..c919866309 100644 --- a/acceptance/openstack/networking/v2/extensions/vlantransparent/vlantransparent_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/vlantransparent/vlantransparent_test.go @@ -6,9 +6,9 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networkingv2 "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networkingv2 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/common/extensions" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/vpnaas/group_test.go b/internal/acceptance/openstack/networking/v2/extensions/vpnaas/group_test.go similarity index 91% rename from acceptance/openstack/networking/v2/extensions/vpnaas/group_test.go rename to internal/acceptance/openstack/networking/v2/extensions/vpnaas/group_test.go index fafd6df496..b65c356e81 100644 --- a/acceptance/openstack/networking/v2/extensions/vpnaas/group_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/vpnaas/group_test.go @@ -6,8 +6,8 @@ package vpnaas import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/vpnaas/endpointgroups" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/vpnaas/ikepolicy_test.go b/internal/acceptance/openstack/networking/v2/extensions/vpnaas/ikepolicy_test.go similarity index 91% rename from acceptance/openstack/networking/v2/extensions/vpnaas/ikepolicy_test.go rename to internal/acceptance/openstack/networking/v2/extensions/vpnaas/ikepolicy_test.go index 0c2715d9ab..f203c2f42e 100644 --- a/acceptance/openstack/networking/v2/extensions/vpnaas/ikepolicy_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/vpnaas/ikepolicy_test.go @@ -6,8 +6,8 @@ package vpnaas import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/vpnaas/ikepolicies" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/vpnaas/ipsecpolicy_test.go b/internal/acceptance/openstack/networking/v2/extensions/vpnaas/ipsecpolicy_test.go similarity index 90% rename from acceptance/openstack/networking/v2/extensions/vpnaas/ipsecpolicy_test.go rename to internal/acceptance/openstack/networking/v2/extensions/vpnaas/ipsecpolicy_test.go index d0d5729693..d36e1bff48 100644 --- a/acceptance/openstack/networking/v2/extensions/vpnaas/ipsecpolicy_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/vpnaas/ipsecpolicy_test.go @@ -6,8 +6,8 @@ package vpnaas import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/vpnaas/ipsecpolicies" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/vpnaas/service_test.go b/internal/acceptance/openstack/networking/v2/extensions/vpnaas/service_test.go similarity index 83% rename from acceptance/openstack/networking/v2/extensions/vpnaas/service_test.go rename to internal/acceptance/openstack/networking/v2/extensions/vpnaas/service_test.go index d8b7daa42b..17de845fa9 100644 --- a/acceptance/openstack/networking/v2/extensions/vpnaas/service_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/vpnaas/service_test.go @@ -6,9 +6,9 @@ package vpnaas import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - layer3 "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions/layer3" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + layer3 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2/extensions/layer3" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/vpnaas/services" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/networking/v2/extensions/vpnaas/siteconnection_test.go b/internal/acceptance/openstack/networking/v2/extensions/vpnaas/siteconnection_test.go similarity index 89% rename from acceptance/openstack/networking/v2/extensions/vpnaas/siteconnection_test.go rename to internal/acceptance/openstack/networking/v2/extensions/vpnaas/siteconnection_test.go index 5f8bf4bea0..9dab42c48c 100644 --- a/acceptance/openstack/networking/v2/extensions/vpnaas/siteconnection_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/vpnaas/siteconnection_test.go @@ -6,10 +6,10 @@ package vpnaas import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - networks "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2" - layer3 "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions/layer3" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networks "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + layer3 "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2/extensions/layer3" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/vpnaas/siteconnections" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/networking/v2/extensions/vpnaas/vpnaas.go b/internal/acceptance/openstack/networking/v2/extensions/vpnaas/vpnaas.go similarity index 99% rename from acceptance/openstack/networking/v2/extensions/vpnaas/vpnaas.go rename to internal/acceptance/openstack/networking/v2/extensions/vpnaas/vpnaas.go index 2ba6a09050..a165aa328a 100644 --- a/acceptance/openstack/networking/v2/extensions/vpnaas/vpnaas.go +++ b/internal/acceptance/openstack/networking/v2/extensions/vpnaas/vpnaas.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/vpnaas/endpointgroups" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/vpnaas/ikepolicies" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/vpnaas/ipsecpolicies" diff --git a/acceptance/openstack/networking/v2/networking.go b/internal/acceptance/openstack/networking/v2/networking.go similarity index 99% rename from acceptance/openstack/networking/v2/networking.go rename to internal/acceptance/openstack/networking/v2/networking.go index aae456b198..6777b39dcb 100644 --- a/acceptance/openstack/networking/v2/networking.go +++ b/internal/acceptance/openstack/networking/v2/networking.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/extradhcpopts" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsecurity" "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" diff --git a/acceptance/openstack/networking/v2/networks_test.go b/internal/acceptance/openstack/networking/v2/networks_test.go similarity index 97% rename from acceptance/openstack/networking/v2/networks_test.go rename to internal/acceptance/openstack/networking/v2/networks_test.go index cf8a88e60d..1208e058c8 100644 --- a/acceptance/openstack/networking/v2/networks_test.go +++ b/internal/acceptance/openstack/networking/v2/networks_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsecurity" "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" diff --git a/acceptance/openstack/networking/v2/ports_test.go b/internal/acceptance/openstack/networking/v2/ports_test.go similarity index 98% rename from acceptance/openstack/networking/v2/ports_test.go rename to internal/acceptance/openstack/networking/v2/ports_test.go index 815a5c53b7..19151c2fe3 100644 --- a/acceptance/openstack/networking/v2/ports_test.go +++ b/internal/acceptance/openstack/networking/v2/ports_test.go @@ -7,9 +7,9 @@ import ( "strings" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - extensions "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + extensions "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2/extensions" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/extradhcpopts" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsecurity" "github.com/gophercloud/gophercloud/openstack/networking/v2/ports" diff --git a/acceptance/openstack/networking/v2/subnets_test.go b/internal/acceptance/openstack/networking/v2/subnets_test.go similarity index 97% rename from acceptance/openstack/networking/v2/subnets_test.go rename to internal/acceptance/openstack/networking/v2/subnets_test.go index 6b45d7c6a0..e7f3b71ebb 100644 --- a/acceptance/openstack/networking/v2/subnets_test.go +++ b/internal/acceptance/openstack/networking/v2/subnets_test.go @@ -8,9 +8,9 @@ import ( "strings" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - subnetpools "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions/subnetpools" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + subnetpools "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2/extensions/subnetpools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/objectstorage/v1/accounts_test.go b/internal/acceptance/openstack/objectstorage/v1/accounts_test.go similarity index 95% rename from acceptance/openstack/objectstorage/v1/accounts_test.go rename to internal/acceptance/openstack/objectstorage/v1/accounts_test.go index a484dc1601..b6792ce9f5 100644 --- a/acceptance/openstack/objectstorage/v1/accounts_test.go +++ b/internal/acceptance/openstack/objectstorage/v1/accounts_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/objectstorage/v1/containers_test.go b/internal/acceptance/openstack/objectstorage/v1/containers_test.go similarity index 98% rename from acceptance/openstack/objectstorage/v1/containers_test.go rename to internal/acceptance/openstack/objectstorage/v1/containers_test.go index d754fe3a59..314b8019e7 100644 --- a/acceptance/openstack/objectstorage/v1/containers_test.go +++ b/internal/acceptance/openstack/objectstorage/v1/containers_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/objectstorage/v1/objects_test.go b/internal/acceptance/openstack/objectstorage/v1/objects_test.go similarity index 98% rename from acceptance/openstack/objectstorage/v1/objects_test.go rename to internal/acceptance/openstack/objectstorage/v1/objects_test.go index 0569428f3d..e60fba9178 100644 --- a/acceptance/openstack/objectstorage/v1/objects_test.go +++ b/internal/acceptance/openstack/objectstorage/v1/objects_test.go @@ -11,8 +11,8 @@ import ( "testing" "time" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers" "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/objectstorage/v1/pkg.go b/internal/acceptance/openstack/objectstorage/v1/pkg.go similarity index 100% rename from acceptance/openstack/objectstorage/v1/pkg.go rename to internal/acceptance/openstack/objectstorage/v1/pkg.go diff --git a/acceptance/openstack/objectstorage/v1/versioning_test.go b/internal/acceptance/openstack/objectstorage/v1/versioning_test.go similarity index 97% rename from acceptance/openstack/objectstorage/v1/versioning_test.go rename to internal/acceptance/openstack/objectstorage/v1/versioning_test.go index 30ebadecc6..2c90f09ec9 100644 --- a/acceptance/openstack/objectstorage/v1/versioning_test.go +++ b/internal/acceptance/openstack/objectstorage/v1/versioning_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers" "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/orchestration/v1/buildinfo_test.go b/internal/acceptance/openstack/orchestration/v1/buildinfo_test.go similarity index 86% rename from acceptance/openstack/orchestration/v1/buildinfo_test.go rename to internal/acceptance/openstack/orchestration/v1/buildinfo_test.go index cec6376f80..0bbea7be74 100644 --- a/acceptance/openstack/orchestration/v1/buildinfo_test.go +++ b/internal/acceptance/openstack/orchestration/v1/buildinfo_test.go @@ -6,7 +6,7 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/orchestration/v1/buildinfo" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/orchestration/v1/orchestration.go b/internal/acceptance/openstack/orchestration/v1/orchestration.go similarity index 98% rename from acceptance/openstack/orchestration/v1/orchestration.go rename to internal/acceptance/openstack/orchestration/v1/orchestration.go index b26b9a8c19..48c155505d 100644 --- a/acceptance/openstack/orchestration/v1/orchestration.go +++ b/internal/acceptance/openstack/orchestration/v1/orchestration.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/orchestration/v1/stacks" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/orchestration/v1/stackevents_test.go b/internal/acceptance/openstack/orchestration/v1/stackevents_test.go similarity index 93% rename from acceptance/openstack/orchestration/v1/stackevents_test.go rename to internal/acceptance/openstack/orchestration/v1/stackevents_test.go index 150d51c9d8..a5de54486d 100644 --- a/acceptance/openstack/orchestration/v1/stackevents_test.go +++ b/internal/acceptance/openstack/orchestration/v1/stackevents_test.go @@ -6,7 +6,7 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/orchestration/v1/stackevents" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/orchestration/v1/stackresources_test.go b/internal/acceptance/openstack/orchestration/v1/stackresources_test.go similarity index 92% rename from acceptance/openstack/orchestration/v1/stackresources_test.go rename to internal/acceptance/openstack/orchestration/v1/stackresources_test.go index 29c20e92e7..2033419a1c 100644 --- a/acceptance/openstack/orchestration/v1/stackresources_test.go +++ b/internal/acceptance/openstack/orchestration/v1/stackresources_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/orchestration/v1/stackresources" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/orchestration/v1/stacks_test.go b/internal/acceptance/openstack/orchestration/v1/stacks_test.go similarity index 90% rename from acceptance/openstack/orchestration/v1/stacks_test.go rename to internal/acceptance/openstack/orchestration/v1/stacks_test.go index f49818e4c3..02e4d57299 100644 --- a/acceptance/openstack/orchestration/v1/stacks_test.go +++ b/internal/acceptance/openstack/orchestration/v1/stacks_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/orchestration/v1/stacks" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/orchestration/v1/stacktemplates_test.go b/internal/acceptance/openstack/orchestration/v1/stacktemplates_test.go similarity index 90% rename from acceptance/openstack/orchestration/v1/stacktemplates_test.go rename to internal/acceptance/openstack/orchestration/v1/stacktemplates_test.go index 7513bcb43f..738d3fda44 100644 --- a/acceptance/openstack/orchestration/v1/stacktemplates_test.go +++ b/internal/acceptance/openstack/orchestration/v1/stacktemplates_test.go @@ -6,8 +6,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/orchestration/v1/stacktemplates" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/orchestration/v1/testdata/samplefile b/internal/acceptance/openstack/orchestration/v1/testdata/samplefile similarity index 100% rename from acceptance/openstack/orchestration/v1/testdata/samplefile rename to internal/acceptance/openstack/orchestration/v1/testdata/samplefile diff --git a/acceptance/openstack/pkg.go b/internal/acceptance/openstack/pkg.go similarity index 100% rename from acceptance/openstack/pkg.go rename to internal/acceptance/openstack/pkg.go diff --git a/acceptance/openstack/placement/v1/pkg.go b/internal/acceptance/openstack/placement/v1/pkg.go similarity index 100% rename from acceptance/openstack/placement/v1/pkg.go rename to internal/acceptance/openstack/placement/v1/pkg.go diff --git a/acceptance/openstack/placement/v1/placement.go b/internal/acceptance/openstack/placement/v1/placement.go similarity index 97% rename from acceptance/openstack/placement/v1/placement.go rename to internal/acceptance/openstack/placement/v1/placement.go index 3ae96328b6..3fc3cf9397 100644 --- a/acceptance/openstack/placement/v1/placement.go +++ b/internal/acceptance/openstack/placement/v1/placement.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/placement/v1/resourceproviders" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/placement/v1/resourceproviders_test.go b/internal/acceptance/openstack/placement/v1/resourceproviders_test.go similarity index 96% rename from acceptance/openstack/placement/v1/resourceproviders_test.go rename to internal/acceptance/openstack/placement/v1/resourceproviders_test.go index ee915ea035..52c1140ff3 100644 --- a/acceptance/openstack/placement/v1/resourceproviders_test.go +++ b/internal/acceptance/openstack/placement/v1/resourceproviders_test.go @@ -3,8 +3,8 @@ package v1 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/placement/v1/resourceproviders" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/availabilityzones_test.go b/internal/acceptance/openstack/sharedfilesystems/v2/availabilityzones_test.go similarity index 91% rename from acceptance/openstack/sharedfilesystems/v2/availabilityzones_test.go rename to internal/acceptance/openstack/sharedfilesystems/v2/availabilityzones_test.go index ed42cdfef9..acb85406a0 100644 --- a/acceptance/openstack/sharedfilesystems/v2/availabilityzones_test.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/availabilityzones_test.go @@ -6,7 +6,7 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/availabilityzones" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/messages/messages.go b/internal/acceptance/openstack/sharedfilesystems/v2/messages/messages.go similarity index 100% rename from acceptance/openstack/sharedfilesystems/v2/messages/messages.go rename to internal/acceptance/openstack/sharedfilesystems/v2/messages/messages.go diff --git a/acceptance/openstack/sharedfilesystems/v2/messages/messages_test.go b/internal/acceptance/openstack/sharedfilesystems/v2/messages/messages_test.go similarity index 95% rename from acceptance/openstack/sharedfilesystems/v2/messages/messages_test.go rename to internal/acceptance/openstack/sharedfilesystems/v2/messages/messages_test.go index d3e65603d9..e3e92b0da0 100644 --- a/acceptance/openstack/sharedfilesystems/v2/messages/messages_test.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/messages/messages_test.go @@ -3,8 +3,8 @@ package messages import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/messages" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/messages/pkg.go b/internal/acceptance/openstack/sharedfilesystems/v2/messages/pkg.go similarity index 100% rename from acceptance/openstack/sharedfilesystems/v2/messages/pkg.go rename to internal/acceptance/openstack/sharedfilesystems/v2/messages/pkg.go diff --git a/acceptance/openstack/sharedfilesystems/v2/pkg.go b/internal/acceptance/openstack/sharedfilesystems/v2/pkg.go similarity index 100% rename from acceptance/openstack/sharedfilesystems/v2/pkg.go rename to internal/acceptance/openstack/sharedfilesystems/v2/pkg.go diff --git a/acceptance/openstack/sharedfilesystems/v2/replicas.go b/internal/acceptance/openstack/sharedfilesystems/v2/replicas.go similarity index 98% rename from acceptance/openstack/sharedfilesystems/v2/replicas.go rename to internal/acceptance/openstack/sharedfilesystems/v2/replicas.go index 5756986c78..3c08152250 100644 --- a/acceptance/openstack/sharedfilesystems/v2/replicas.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/replicas.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/replicas" diff --git a/acceptance/openstack/sharedfilesystems/v2/replicas_test.go b/internal/acceptance/openstack/sharedfilesystems/v2/replicas_test.go similarity index 98% rename from acceptance/openstack/sharedfilesystems/v2/replicas_test.go rename to internal/acceptance/openstack/sharedfilesystems/v2/replicas_test.go index 6fa28cada6..1b54d79b60 100644 --- a/acceptance/openstack/sharedfilesystems/v2/replicas_test.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/replicas_test.go @@ -7,8 +7,8 @@ import ( "testing" "time" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/replicas" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/schedulerstats_test.go b/internal/acceptance/openstack/sharedfilesystems/v2/schedulerstats_test.go similarity index 82% rename from acceptance/openstack/sharedfilesystems/v2/schedulerstats_test.go rename to internal/acceptance/openstack/sharedfilesystems/v2/schedulerstats_test.go index aebe388672..2d51348cab 100644 --- a/acceptance/openstack/sharedfilesystems/v2/schedulerstats_test.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/schedulerstats_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/schedulerstats" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/securityservices.go b/internal/acceptance/openstack/sharedfilesystems/v2/securityservices.go similarity index 96% rename from acceptance/openstack/sharedfilesystems/v2/securityservices.go rename to internal/acceptance/openstack/sharedfilesystems/v2/securityservices.go index 342a91789e..47b93afb98 100644 --- a/acceptance/openstack/sharedfilesystems/v2/securityservices.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/securityservices.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/securityservices" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/securityservices_test.go b/internal/acceptance/openstack/sharedfilesystems/v2/securityservices_test.go similarity index 97% rename from acceptance/openstack/sharedfilesystems/v2/securityservices_test.go rename to internal/acceptance/openstack/sharedfilesystems/v2/securityservices_test.go index e0e1b16f68..e578c52e3e 100644 --- a/acceptance/openstack/sharedfilesystems/v2/securityservices_test.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/securityservices_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/securityservices" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/services_test.go b/internal/acceptance/openstack/sharedfilesystems/v2/services_test.go similarity index 83% rename from acceptance/openstack/sharedfilesystems/v2/services_test.go rename to internal/acceptance/openstack/sharedfilesystems/v2/services_test.go index b1340e8752..a0745ab795 100644 --- a/acceptance/openstack/sharedfilesystems/v2/services_test.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/services_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/services" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/shareaccessrules.go b/internal/acceptance/openstack/sharedfilesystems/v2/shareaccessrules.go similarity index 97% rename from acceptance/openstack/sharedfilesystems/v2/shareaccessrules.go rename to internal/acceptance/openstack/sharedfilesystems/v2/shareaccessrules.go index 2345924e8c..2659cc9834 100644 --- a/acceptance/openstack/sharedfilesystems/v2/shareaccessrules.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/shareaccessrules.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/shareaccessrules" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/shares" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/shareaccessrules_test.go b/internal/acceptance/openstack/sharedfilesystems/v2/shareaccessrules_test.go similarity index 96% rename from acceptance/openstack/sharedfilesystems/v2/shareaccessrules_test.go rename to internal/acceptance/openstack/sharedfilesystems/v2/shareaccessrules_test.go index 6670c22ebe..d5a279a923 100644 --- a/acceptance/openstack/sharedfilesystems/v2/shareaccessrules_test.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/shareaccessrules_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/sharenetworks.go b/internal/acceptance/openstack/sharedfilesystems/v2/sharenetworks.go similarity index 92% rename from acceptance/openstack/sharedfilesystems/v2/sharenetworks.go rename to internal/acceptance/openstack/sharedfilesystems/v2/sharenetworks.go index 55aad83eee..3a269df8b5 100644 --- a/acceptance/openstack/sharedfilesystems/v2/sharenetworks.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/sharenetworks.go @@ -4,8 +4,8 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/sharenetworks" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/sharenetworks_test.go b/internal/acceptance/openstack/sharedfilesystems/v2/sharenetworks_test.go similarity index 98% rename from acceptance/openstack/sharedfilesystems/v2/sharenetworks_test.go rename to internal/acceptance/openstack/sharedfilesystems/v2/sharenetworks_test.go index bcd3f78a89..2b75e52300 100644 --- a/acceptance/openstack/sharedfilesystems/v2/sharenetworks_test.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/sharenetworks_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/sharenetworks" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/sharedfilesystems/v2/shares.go b/internal/acceptance/openstack/sharedfilesystems/v2/shares.go similarity index 98% rename from acceptance/openstack/sharedfilesystems/v2/shares.go rename to internal/acceptance/openstack/sharedfilesystems/v2/shares.go index 9179a30cf1..cce4f7feb1 100644 --- a/acceptance/openstack/sharedfilesystems/v2/shares.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/shares.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/messages" diff --git a/acceptance/openstack/sharedfilesystems/v2/shares_test.go b/internal/acceptance/openstack/sharedfilesystems/v2/shares_test.go similarity index 99% rename from acceptance/openstack/sharedfilesystems/v2/shares_test.go rename to internal/acceptance/openstack/sharedfilesystems/v2/shares_test.go index b1c14d02b0..e05e1b090c 100644 --- a/acceptance/openstack/sharedfilesystems/v2/shares_test.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/shares_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/shares" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/sharetransfers.go b/internal/acceptance/openstack/sharedfilesystems/v2/sharetransfers.go similarity index 100% rename from acceptance/openstack/sharedfilesystems/v2/sharetransfers.go rename to internal/acceptance/openstack/sharedfilesystems/v2/sharetransfers.go diff --git a/acceptance/openstack/sharedfilesystems/v2/sharetransfers_test.go b/internal/acceptance/openstack/sharedfilesystems/v2/sharetransfers_test.go similarity index 93% rename from acceptance/openstack/sharedfilesystems/v2/sharetransfers_test.go rename to internal/acceptance/openstack/sharedfilesystems/v2/sharetransfers_test.go index 8e3b70df48..09a188682c 100644 --- a/acceptance/openstack/sharedfilesystems/v2/sharetransfers_test.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/sharetransfers_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" th "github.com/gophercloud/gophercloud/testhelper" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/sharetransfers" diff --git a/acceptance/openstack/sharedfilesystems/v2/sharetypes.go b/internal/acceptance/openstack/sharedfilesystems/v2/sharetypes.go similarity index 95% rename from acceptance/openstack/sharedfilesystems/v2/sharetypes.go rename to internal/acceptance/openstack/sharedfilesystems/v2/sharetypes.go index 4debc1fd33..791f34a08b 100644 --- a/acceptance/openstack/sharedfilesystems/v2/sharetypes.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/sharetypes.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/sharetypes" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/sharetypes_test.go b/internal/acceptance/openstack/sharedfilesystems/v2/sharetypes_test.go similarity index 97% rename from acceptance/openstack/sharedfilesystems/v2/sharetypes_test.go rename to internal/acceptance/openstack/sharedfilesystems/v2/sharetypes_test.go index 0fa951d701..bfaa8c2eda 100644 --- a/acceptance/openstack/sharedfilesystems/v2/sharetypes_test.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/sharetypes_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/sharetypes" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/snapshots.go b/internal/acceptance/openstack/sharedfilesystems/v2/snapshots.go similarity index 97% rename from acceptance/openstack/sharedfilesystems/v2/snapshots.go rename to internal/acceptance/openstack/sharedfilesystems/v2/snapshots.go index e96d02b9b9..641b6440df 100644 --- a/acceptance/openstack/sharedfilesystems/v2/snapshots.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/snapshots.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/snapshots" ) diff --git a/acceptance/openstack/sharedfilesystems/v2/snapshots_test.go b/internal/acceptance/openstack/sharedfilesystems/v2/snapshots_test.go similarity index 97% rename from acceptance/openstack/sharedfilesystems/v2/snapshots_test.go rename to internal/acceptance/openstack/sharedfilesystems/v2/snapshots_test.go index de83e41cd1..cb5a7f9b33 100644 --- a/acceptance/openstack/sharedfilesystems/v2/snapshots_test.go +++ b/internal/acceptance/openstack/sharedfilesystems/v2/snapshots_test.go @@ -6,8 +6,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/snapshots" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/workflow/v2/crontrigger.go b/internal/acceptance/openstack/workflow/v2/crontrigger.go similarity index 97% rename from acceptance/openstack/workflow/v2/crontrigger.go rename to internal/acceptance/openstack/workflow/v2/crontrigger.go index 20a7fd653e..cdd5045133 100644 --- a/acceptance/openstack/workflow/v2/crontrigger.go +++ b/internal/acceptance/openstack/workflow/v2/crontrigger.go @@ -5,7 +5,7 @@ import ( "time" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/workflow/v2/crontriggers" "github.com/gophercloud/gophercloud/openstack/workflow/v2/workflows" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/workflow/v2/crontriggers_test.go b/internal/acceptance/openstack/workflow/v2/crontriggers_test.go similarity index 91% rename from acceptance/openstack/workflow/v2/crontriggers_test.go rename to internal/acceptance/openstack/workflow/v2/crontriggers_test.go index 48642cd5f2..97c0703771 100644 --- a/acceptance/openstack/workflow/v2/crontriggers_test.go +++ b/internal/acceptance/openstack/workflow/v2/crontriggers_test.go @@ -4,8 +4,8 @@ import ( "testing" "time" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/workflow/v2/crontriggers" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/workflow/v2/execution.go b/internal/acceptance/openstack/workflow/v2/execution.go similarity index 97% rename from acceptance/openstack/workflow/v2/execution.go rename to internal/acceptance/openstack/workflow/v2/execution.go index 6eb6d048da..359275e1da 100644 --- a/acceptance/openstack/workflow/v2/execution.go +++ b/internal/acceptance/openstack/workflow/v2/execution.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/workflow/v2/executions" "github.com/gophercloud/gophercloud/openstack/workflow/v2/workflows" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/acceptance/openstack/workflow/v2/executions_test.go b/internal/acceptance/openstack/workflow/v2/executions_test.go similarity index 90% rename from acceptance/openstack/workflow/v2/executions_test.go rename to internal/acceptance/openstack/workflow/v2/executions_test.go index 86c0dd858b..098f3dadb2 100644 --- a/acceptance/openstack/workflow/v2/executions_test.go +++ b/internal/acceptance/openstack/workflow/v2/executions_test.go @@ -3,8 +3,8 @@ package v2 import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/workflow/v2/executions" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/workflow/v2/workflow.go b/internal/acceptance/openstack/workflow/v2/workflow.go similarity index 97% rename from acceptance/openstack/workflow/v2/workflow.go rename to internal/acceptance/openstack/workflow/v2/workflow.go index de95d0ca60..b81b69902e 100644 --- a/acceptance/openstack/workflow/v2/workflow.go +++ b/internal/acceptance/openstack/workflow/v2/workflow.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/workflow/v2/workflows" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/openstack/workflow/v2/workflows_test.go b/internal/acceptance/openstack/workflow/v2/workflows_test.go similarity index 89% rename from acceptance/openstack/workflow/v2/workflows_test.go rename to internal/acceptance/openstack/workflow/v2/workflows_test.go index a5fdde6413..163a52b40b 100644 --- a/acceptance/openstack/workflow/v2/workflows_test.go +++ b/internal/acceptance/openstack/workflow/v2/workflows_test.go @@ -4,8 +4,8 @@ import ( "testing" "time" - "github.com/gophercloud/gophercloud/acceptance/clients" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/workflow/v2/workflows" th "github.com/gophercloud/gophercloud/testhelper" ) diff --git a/acceptance/tools/pkg.go b/internal/acceptance/tools/pkg.go similarity index 100% rename from acceptance/tools/pkg.go rename to internal/acceptance/tools/pkg.go diff --git a/acceptance/tools/tools.go b/internal/acceptance/tools/tools.go similarity index 100% rename from acceptance/tools/tools.go rename to internal/acceptance/tools/tools.go diff --git a/openstack/clustering/v1/profiletypes/testing/requests_test.go b/openstack/clustering/v1/profiletypes/testing/requests_test.go index c4f379b645..3bac5ab349 100644 --- a/openstack/clustering/v1/profiletypes/testing/requests_test.go +++ b/openstack/clustering/v1/profiletypes/testing/requests_test.go @@ -3,7 +3,7 @@ package testing import ( "testing" - "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" "github.com/gophercloud/gophercloud/openstack/clustering/v1/profiletypes" "github.com/gophercloud/gophercloud/pagination" th "github.com/gophercloud/gophercloud/testhelper" diff --git a/script/acceptancetest b/script/acceptancetest index 09db3f38fa..60627a824f 100755 --- a/script/acceptancetest +++ b/script/acceptancetest @@ -17,7 +17,7 @@ mkdir -p ${LOG_DIR} if [[ -z "${ACCEPTANCE_TESTS_FILTER}" ]]; then ACCEPTANCE_TESTS=($(python <<< "print(' '.join($ACCEPTANCE_TESTS))")) else - ACCEPTANCE_TESTS=$(find acceptance/openstack -name '*_test.go' -exec dirname {} \; | sort -n | uniq | grep -P "$ACCEPTANCE_TESTS_FILTER") + ACCEPTANCE_TESTS=$(find internal/acceptance/openstack -name '*_test.go' -exec dirname {} \; | sort -n | uniq | grep -P "$ACCEPTANCE_TESTS_FILTER") ACCEPTANCE_TESTS=($ACCEPTANCE_TESTS) fi From 39c2b02006ee7b55b81098346cb18f0a235ff10c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Fri, 22 Sep 2023 16:15:25 +0200 Subject: [PATCH 044/118] Fix acceptancetest script when running without argument It previously generated an error due to the `ACCEPTANCE_TESTS` variable being undefined. It now runs all acceptance tests. --- script/acceptancetest | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script/acceptancetest b/script/acceptancetest index 60627a824f..9e540b2d84 100755 --- a/script/acceptancetest +++ b/script/acceptancetest @@ -15,11 +15,11 @@ fi mkdir -p ${LOG_DIR} if [[ -z "${ACCEPTANCE_TESTS_FILTER}" ]]; then - ACCEPTANCE_TESTS=($(python <<< "print(' '.join($ACCEPTANCE_TESTS))")) + ACCEPTANCE_TESTS=$(find internal/acceptance/openstack -name '*_test.go' -exec dirname {} \; | sort -n | uniq) else ACCEPTANCE_TESTS=$(find internal/acceptance/openstack -name '*_test.go' -exec dirname {} \; | sort -n | uniq | grep -P "$ACCEPTANCE_TESTS_FILTER") - ACCEPTANCE_TESTS=($ACCEPTANCE_TESTS) fi +ACCEPTANCE_TESTS=($ACCEPTANCE_TESTS) if [[ -z $ACCEPTANCE_TESTS ]]; then echo "No acceptance tests to run" From 4f4a0567959f36d1edc638ce77d275bb0805ba35 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Fri, 22 Sep 2023 15:08:05 -0400 Subject: [PATCH 045/118] Prepare 1.7.0 --- CHANGELOG.md | 16 ++++++++++++++++ provider_client.go | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb9d4172a8..b470df398b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## v1.7.0 (2023-09-22) + +New features and improvements: + +* [GH-2782](https://github.com/gophercloud/gophercloud/pull/2782) [v1] (manual clean backport) Add tag field to compute block_device_v2 + +CI changes: + +* [GH-2760](https://github.com/gophercloud/gophercloud/pull/2760) [v1 backports] semver auto labels +* [GH-2775](https://github.com/gophercloud/gophercloud/pull/2775) [v1] Fix typos in comments +* [GH-2783](https://github.com/gophercloud/gophercloud/pull/2783) [v1] (clean manual backport) ci/functional: fix ubuntu version & add antelope +* [GH-2785](https://github.com/gophercloud/gophercloud/pull/2785) [v1] Acceptance: Handle numerical version names in version comparison helpers +* [GH-2787](https://github.com/gophercloud/gophercloud/pull/2787) backport-v1: fixes to semver label +* [GH-2788](https://github.com/gophercloud/gophercloud/pull/2788) [v1] Make acceptance tests internal + + ## v1.6.0 (2023-08-30) New features and improvements: diff --git a/provider_client.go b/provider_client.go index d1955b65ab..e53b713cd4 100644 --- a/provider_client.go +++ b/provider_client.go @@ -14,7 +14,7 @@ import ( // DefaultUserAgent is the default User-Agent string set in the request header. const ( - DefaultUserAgent = "gophercloud/v1.6.0" + DefaultUserAgent = "gophercloud/v1.7.0" DefaultMaxBackoffRetries = 60 ) From 80b7ededfa080eeab26df8e998afe7527b257f40 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Wed, 4 Oct 2023 11:10:56 -0400 Subject: [PATCH 046/118] ci/unit: switch to coverallsapp/github-action Instead of using an old github action for coverall, switch to the official one. --- .github/workflows/unit.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 9a49c86d26..b438f33a4b 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -6,7 +6,7 @@ permissions: jobs: test: permissions: - checks: write # for shogo82148/actions-goveralls to create a new check based on the results + checks: write # for coverallsapp/github-action to create a new check based on the results contents: read # for actions/checkout to fetch code runs-on: ubuntu-latest strategy: @@ -47,18 +47,22 @@ jobs: ./script/format ./script/unittest -v - - uses: shogo82148/actions-goveralls@v1 + - name: Coveralls Parallel + uses: coverallsapp/github-action@v2 with: - path-to-profile: cover.out + file: cover.out flag-name: Go-${{ matrix.go-version }} parallel: true finish: permissions: - checks: write # for shogo82148/actions-goveralls to create a new check based on the results + checks: write # for coverallsapp/github-action to create a new check based on the results needs: test + if: ${{ always() }} runs-on: ubuntu-latest steps: - - uses: shogo82148/actions-goveralls@v1 - with: - parallel-finished: true + - name: Coveralls Finished + uses: coverallsapp/github-action@v2 + with: + parallel-finished: true + carryforward: Go-${{ join(matrix.go-version.*, '-') }} From 964ece518673a3725f2b0fb142dcfacc2146382b Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Fri, 6 Oct 2023 16:27:07 +0200 Subject: [PATCH 047/118] Fix options initialization in ServiceClient.Request (fixes #2798) Request is a part of the public API, but it relies on being called by Get/Post/etc to properly initialize its options. Namely: 1) it may crash on a nil map assignment if there are MoreHeaders, 2) it does not handle microversions. This change moves the relevant code to Request. --- service_client.go | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/service_client.go b/service_client.go index dd54abe30e..94a161e340 100644 --- a/service_client.go +++ b/service_client.go @@ -47,7 +47,7 @@ func (client *ServiceClient) ServiceURL(parts ...string) string { return client.ResourceBaseURL() + strings.Join(parts, "/") } -func (client *ServiceClient) initReqOpts(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) { +func (client *ServiceClient) initReqOpts(JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) { if v, ok := (JSONBody).(io.Reader); ok { opts.RawBody = v } else if JSONBody != nil { @@ -57,14 +57,6 @@ func (client *ServiceClient) initReqOpts(url string, JSONBody interface{}, JSONR if JSONResponse != nil { opts.JSONResponse = JSONResponse } - - if opts.MoreHeaders == nil { - opts.MoreHeaders = make(map[string]string) - } - - if client.Microversion != "" { - client.setMicroversionHeader(opts) - } } // Get calls `Request` with the "GET" HTTP verb. @@ -72,7 +64,7 @@ func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *Req if opts == nil { opts = new(RequestOpts) } - client.initReqOpts(url, nil, JSONResponse, opts) + client.initReqOpts(nil, JSONResponse, opts) return client.Request("GET", url, opts) } @@ -81,7 +73,7 @@ func (client *ServiceClient) Post(url string, JSONBody interface{}, JSONResponse if opts == nil { opts = new(RequestOpts) } - client.initReqOpts(url, JSONBody, JSONResponse, opts) + client.initReqOpts(JSONBody, JSONResponse, opts) return client.Request("POST", url, opts) } @@ -90,7 +82,7 @@ func (client *ServiceClient) Put(url string, JSONBody interface{}, JSONResponse if opts == nil { opts = new(RequestOpts) } - client.initReqOpts(url, JSONBody, JSONResponse, opts) + client.initReqOpts(JSONBody, JSONResponse, opts) return client.Request("PUT", url, opts) } @@ -99,7 +91,7 @@ func (client *ServiceClient) Patch(url string, JSONBody interface{}, JSONRespons if opts == nil { opts = new(RequestOpts) } - client.initReqOpts(url, JSONBody, JSONResponse, opts) + client.initReqOpts(JSONBody, JSONResponse, opts) return client.Request("PATCH", url, opts) } @@ -108,7 +100,7 @@ func (client *ServiceClient) Delete(url string, opts *RequestOpts) (*http.Respon if opts == nil { opts = new(RequestOpts) } - client.initReqOpts(url, nil, nil, opts) + client.initReqOpts(nil, nil, opts) return client.Request("DELETE", url, opts) } @@ -117,7 +109,7 @@ func (client *ServiceClient) Head(url string, opts *RequestOpts) (*http.Response if opts == nil { opts = new(RequestOpts) } - client.initReqOpts(url, nil, nil, opts) + client.initReqOpts(nil, nil, opts) return client.Request("HEAD", url, opts) } @@ -142,10 +134,19 @@ func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) { // Request carries out the HTTP operation for the service client func (client *ServiceClient) Request(method, url string, options *RequestOpts) (*http.Response, error) { + if options.MoreHeaders == nil { + options.MoreHeaders = make(map[string]string) + } + + if client.Microversion != "" { + client.setMicroversionHeader(options) + } + if len(client.MoreHeaders) > 0 { if options == nil { options = new(RequestOpts) } + for k, v := range client.MoreHeaders { options.MoreHeaders[k] = v } From 8d0b6da95c0476e3b8f867a0981148f504a7ac6d Mon Sep 17 00:00:00 2001 From: Iury Gregory Melo Ferreira Date: Fri, 6 Oct 2023 12:12:20 -0400 Subject: [PATCH 048/118] Add job for bobcat stable/2023.2 This commit adds bobcat release to all functional workflows. --- .github/workflows/functional-baremetal.yaml | 3 +++ .github/workflows/functional-basic.yaml | 3 +++ .github/workflows/functional-blockstorage.yaml | 3 +++ .github/workflows/functional-clustering.yaml | 3 +++ .github/workflows/functional-compute.yaml | 3 +++ .github/workflows/functional-containerinfra.yaml | 3 +++ .github/workflows/functional-dns.yaml | 3 +++ .github/workflows/functional-fwaas_v2.yaml | 3 +++ .github/workflows/functional-identity.yaml | 3 +++ .github/workflows/functional-imageservice.yaml | 3 +++ .github/workflows/functional-keymanager.yaml | 3 +++ .github/workflows/functional-loadbalancer.yaml | 3 +++ .github/workflows/functional-messaging.yaml | 3 +++ .github/workflows/functional-networking.yaml | 3 +++ .github/workflows/functional-objectstorage.yaml | 3 +++ .github/workflows/functional-orchestration.yaml | 3 +++ .github/workflows/functional-placement.yaml | 3 +++ .github/workflows/functional-sharedfilesystems.yaml | 3 +++ 18 files changed, 54 insertions(+) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index 5002c08be0..6a8eb98fcf 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index b836cfb711..879bd678ad 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -15,6 +15,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index 4b8f69133e..e34f2c3de8 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-clustering.yaml b/.github/workflows/functional-clustering.yaml index 3a08f8b1d6..6d86dc6880 100644 --- a/.github/workflows/functional-clustering.yaml +++ b/.github/workflows/functional-clustering.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index 65311bce6e..cdc789793f 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index cbdbb5cce1..2c7b4a3480 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -12,6 +12,9 @@ jobs: - name: "master" openstack_version: "master" ubuntu_version: "22.04" + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index e332d273ae..427832a95a 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -13,6 +13,9 @@ jobs: - name: "master" openstack_version: "master" ubuntu_version: "22.04" + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml index ecd53ef5be..17dd723f29 100644 --- a/.github/workflows/functional-fwaas_v2.yaml +++ b/.github/workflows/functional-fwaas_v2.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml index 3170e41e06..43e638381f 100644 --- a/.github/workflows/functional-identity.yaml +++ b/.github/workflows/functional-identity.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-imageservice.yaml b/.github/workflows/functional-imageservice.yaml index 744ee93a05..a85e6621e2 100644 --- a/.github/workflows/functional-imageservice.yaml +++ b/.github/workflows/functional-imageservice.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml index 8d72e06a60..a1b5a4ed19 100644 --- a/.github/workflows/functional-keymanager.yaml +++ b/.github/workflows/functional-keymanager.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml index 9af476b3a5..fa2a3e9493 100644 --- a/.github/workflows/functional-loadbalancer.yaml +++ b/.github/workflows/functional-loadbalancer.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml index 0fcf3c0c35..200ed18887 100644 --- a/.github/workflows/functional-messaging.yaml +++ b/.github/workflows/functional-messaging.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index 0a33e5787c..4691455e9e 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -12,6 +12,9 @@ jobs: - name: "master" openstack_version: "master" ubuntu_version: "22.04" + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml index bf7e4f5b6f..c5ac5bd4a1 100644 --- a/.github/workflows/functional-objectstorage.yaml +++ b/.github/workflows/functional-objectstorage.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml index 5f81b3e733..0d035f6be0 100644 --- a/.github/workflows/functional-orchestration.yaml +++ b/.github/workflows/functional-orchestration.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml index a7efecdd24..66d3849a98 100644 --- a/.github/workflows/functional-placement.yaml +++ b/.github/workflows/functional-placement.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml index 48acec333e..eb42329634 100644 --- a/.github/workflows/functional-sharedfilesystems.yaml +++ b/.github/workflows/functional-sharedfilesystems.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "bobcat" + openstack_version: "stable/2023.2" + ubuntu_version: "22.04" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" From c71fc9d7c2b95b8de308f34f2927203a7eac1e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Mon, 16 Oct 2023 14:11:27 +0200 Subject: [PATCH 049/118] Make fixtures part of tests By renaming the fixtures to fixtures_test, we mark them as test, and no longer part of the public API. Some files were left out as they were included in other tests: $ grep "/testing" -R openstack | cut -d " " -f 2 | sort | uniq "github.com/gophercloud/gophercloud/openstack/common/extensions/testing" "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/testing" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/testing" "github.com/gophercloud/gophercloud/openstack/networking/v2/networks/testing" "github.com/gophercloud/gophercloud/openstack/networking/v2/ports/testing" "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts/testing" "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/testing" This should prevent go-apidiff from complaining when modifying fixtures. This commit mirrors 7f1d07519ffc99fdc74e1dafc92d56be52624989 that merged in master. --- .../.template/testing/{fixtures.go => fixtures_test.go} | 0 .../apiversions/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/allocations/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/conductors/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/drivers/testing/{fixtures.go => fixtures_test.go} | 0 .../baremetal/v1/nodes/testing/{fixtures.go => fixtures_test.go} | 0 .../baremetal/v1/ports/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/introspection/testing/{fixtures.go => fixtures_test.go} | 0 .../apiversions/testing/{fixtures.go => fixtures_test.go} | 0 .../availabilityzones/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/backups/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/limits/testing/{fixtures.go => fixtures_test.go} | 0 .../quotasets/testing/{fixtures.go => fixtures_test.go} | 0 .../schedulerstats/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/services/testing/{fixtures.go => fixtures_test.go} | 0 .../volumeactions/testing/{fixtures.go => fixtures_test.go} | 0 .../volumetransfers/testing/{fixtures.go => fixtures_test.go} | 0 .../blockstorage/noauth/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/apiversions/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/snapshots/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/volumes/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/volumetypes/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/snapshots/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/volumes/testing/{fixtures.go => fixtures_test.go} | 0 .../v3/attachments/testing/{fixtures.go => fixtures_test.go} | 0 .../blockstorage/v3/qos/testing/{fixtures.go => fixtures_test.go} | 0 .../v3/snapshots/testing/{fixtures.go => fixtures_test.go} | 0 .../v3/volumes/testing/{fixtures.go => fixtures_test.go} | 0 .../v3/volumetypes/testing/{fixtures.go => fixtures_test.go} | 0 openstack/cdn/v1/base/testing/{fixtures.go => fixtures_test.go} | 0 .../cdn/v1/flavors/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/serviceassets/testing/{fixtures.go => fixtures_test.go} | 0 .../cdn/v1/services/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/actions/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/clusters/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/events/testing/{fixtures.go => fixtures_test.go} | 0 .../clustering/v1/nodes/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/policies/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/policytypes/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/profiles/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/profiletypes/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/receivers/testing/{fixtures.go => fixtures_test.go} | 0 .../compute/apiversions/testing/{fixtures.go => fixtures_test.go} | 0 .../aggregates/testing/{fixtures.go => fixtures_test.go} | 0 .../attachinterfaces/testing/{fixtures.go => fixtures_test.go} | 0 .../availabilityzones/testing/{fixtures.go => fixtures_test.go} | 0 .../bootfromvolume/testing/{fixtures.go => fixtures_test.go} | 0 .../defsecrules/testing/{fixtures.go => fixtures_test.go} | 0 .../diagnostics/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/evacuate/testing/{fixtures.go => fixtures_test.go} | 0 .../testing/{fixtures.go => fixtures_test.go} | 0 .../floatingips/testing/{fixtures.go => fixtures_test.go} | 0 .../hypervisors/testing/{fixtures.go => fixtures_test.go} | 0 .../injectnetworkinfo/testing/{fixtures.go => fixtures_test.go} | 0 .../instanceactions/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/keypairs/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/limits/testing/{fixtures.go => fixtures_test.go} | 0 .../lockunlock/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/migrate/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/networks/testing/{fixtures.go => fixtures_test.go} | 0 .../pauseunpause/testing/{fixtures.go => fixtures_test.go} | 0 .../quotasets/testing/{fixtures.go => fixtures_test.go} | 0 .../remoteconsoles/testing/{fixtures.go => fixtures_test.go} | 0 .../rescueunrescue/testing/{fixtures.go => fixtures_test.go} | 0 .../resetnetwork/testing/{fixtures.go => fixtures_test.go} | 0 .../resetstate/testing/{fixtures.go => fixtures_test.go} | 0 .../secgroups/testing/{fixtures.go => fixtures_test.go} | 0 .../servergroups/testing/{fixtures.go => fixtures_test.go} | 0 .../serverusage/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/services/testing/{fixtures.go => fixtures_test.go} | 0 .../shelveunshelve/testing/{fixtures.go => fixtures_test.go} | 0 .../startstop/testing/{fixtures.go => fixtures_test.go} | 0 .../suspendresume/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/extensions/tags/testing/{fixtures.go => fixtures_test.go} | 0 .../tenantnetworks/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/extensions/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/extensions/usage/testing/{fixtures.go => fixtures_test.go} | 0 .../volumeattach/testing/{fixtures.go => fixtures_test.go} | 0 .../compute/v2/flavors/testing/{fixtures.go => fixtures_test.go} | 0 .../compute/v2/servers/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/capsules/testing/{fixtures.go => fixtures_test.go} | 0 .../apiversions/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/certificates/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/clusters/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/clustertemplates/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/nodegroups/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/quotas/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/configurations/testing/{fixtures.go => fixtures_test.go} | 0 .../db/v1/databases/testing/{fixtures.go => fixtures_test.go} | 0 .../db/v1/datastores/testing/{fixtures.go => fixtures_test.go} | 0 openstack/db/v1/flavors/testing/{fixtures.go => fixtures_test.go} | 0 .../db/v1/instances/testing/{fixtures.go => fixtures_test.go} | 0 openstack/db/v1/users/testing/{fixtures.go => fixtures_test.go} | 0 .../dns/v2/recordsets/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/transfer/accept/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/transfer/request/testing/{fixtures.go => fixtures_test.go} | 0 openstack/dns/v2/zones/testing/{fixtures.go => fixtures_test.go} | 0 .../admin/roles/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/extensions/testing/{fixtures.go => fixtures_test.go} | 0 .../identity/v2/tenants/testing/{fixtures.go => fixtures_test.go} | 0 .../identity/v2/tokens/testing/{fixtures.go => fixtures_test.go} | 0 .../identity/v2/users/testing/{fixtures.go => fixtures_test.go} | 0 .../testing/{fixtures.go => fixtures_test.go} | 0 .../identity/v3/catalog/testing/{fixtures.go => fixtures_test.go} | 0 .../v3/credentials/testing/{fixtures.go => fixtures_test.go} | 0 .../identity/v3/domains/testing/{fixtures.go => fixtures_test.go} | 0 .../ec2credentials/testing/{fixtures.go => fixtures_test.go} | 0 .../federation/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/oauth1/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/trusts/testing/{fixtures.go => fixtures_test.go} | 0 .../identity/v3/groups/testing/{fixtures.go => fixtures_test.go} | 0 .../identity/v3/limits/testing/{fixtures.go => fixtures_test.go} | 0 .../v3/osinherit/testing/{fixtures.go => fixtures_test.go} | 0 .../v3/policies/testing/{fixtures.go => fixtures_test.go} | 0 .../v3/projects/testing/{fixtures.go => fixtures_test.go} | 0 .../identity/v3/regions/testing/{fixtures.go => fixtures_test.go} | 0 .../v3/registeredlimits/testing/{fixtures.go => fixtures_test.go} | 0 .../identity/v3/roles/testing/{fixtures.go => fixtures_test.go} | 0 .../v3/services/testing/{fixtures.go => fixtures_test.go} | 0 .../identity/v3/users/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/imagedata/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/imageimport/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/images/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/members/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/tasks/testing/{fixtures.go => fixtures_test.go} | 0 .../keymanager/v1/acls/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/containers/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/orders/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/secrets/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/amphorae/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/l7policies/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/listeners/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/loadbalancers/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/monitors/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/pools/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/providers/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/quotas/testing/{fixtures.go => fixtures_test.go} | 0 .../messaging/v2/claims/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/messages/testing/{fixtures.go => fixtures_test.go} | 0 .../messaging/v2/queues/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/agents/testing/{fixtures.go => fixtures_test.go} | 0 .../attributestags/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/extensions/dns/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/external/testing/{fixtures.go => fixtures_test.go} | 0 .../addressscopes/testing/{fixtures.go => fixtures_test.go} | 0 .../portforwarding/testing/{fixtures.go => fixtures_test.go} | 0 .../lbaas_v2/l7policies/testing/{fixtures.go => fixtures_test.go} | 0 .../lbaas_v2/listeners/testing/{fixtures.go => fixtures_test.go} | 0 .../loadbalancers/testing/{fixtures.go => fixtures_test.go} | 0 .../lbaas_v2/monitors/testing/{fixtures.go => fixtures_test.go} | 0 .../lbaas_v2/pools/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/extensions/mtu/testing/{fixtures.go => fixtures_test.go} | 0 .../testing/{fixtures.go => fixtures_test.go} | 0 .../portsbinding/testing/{fixtures.go => fixtures_test.go} | 0 .../qos/policies/testing/{fixtures.go => fixtures_test.go} | 0 .../qos/rules/testing/{fixtures.go => fixtures_test.go} | 0 .../qos/ruletypes/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/quotas/testing/{fixtures.go => fixtures_test.go} | 0 .../rbacpolicies/testing/{fixtures.go => fixtures_test.go} | 0 .../security/groups/testing/{fixtures.go => fixtures_test.go} | 0 .../subnetpools/testing/{fixtures.go => fixtures_test.go} | 0 .../trunk_details/testing/{fixtures.go => fixtures_test.go} | 0 .../extensions/trunks/testing/{fixtures.go => fixtures_test.go} | 0 .../vlantransparent/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/subnets/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/objects/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/swauth/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/buildinfo/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/resourcetypes/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/stackevents/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/stackresources/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/stacks/testing/{fixtures.go => fixtures_test.go} | 0 .../v1/stacktemplates/testing/{fixtures.go => fixtures_test.go} | 0 .../resourceproviders/testing/{fixtures.go => fixtures_test.go} | 0 .../apiversions/testing/{fixtures.go => fixtures_test.go} | 0 .../availabilityzones/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/errors/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/messages/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/replicas/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/schedulerstats/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/securityservices/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/services/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/shareaccessrules/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/sharenetworks/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/shares/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/sharetransfers/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/sharetypes/testing/{fixtures.go => fixtures_test.go} | 0 .../v2/snapshots/testing/{fixtures.go => fixtures_test.go} | 0 188 files changed, 0 insertions(+), 0 deletions(-) rename docs/contributor-tutorial/.template/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/baremetal/apiversions/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/baremetal/v1/allocations/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/baremetal/v1/conductors/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/baremetal/v1/drivers/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/baremetal/v1/nodes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/baremetal/v1/ports/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/baremetalintrospection/v1/introspection/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/apiversions/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/extensions/availabilityzones/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/extensions/backups/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/extensions/limits/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/extensions/quotasets/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/extensions/schedulerstats/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/extensions/services/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/extensions/volumeactions/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/extensions/volumetransfers/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/noauth/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/v1/apiversions/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/v1/snapshots/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/v1/volumes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/v1/volumetypes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/v2/snapshots/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/v2/volumes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/v3/attachments/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/v3/qos/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/v3/snapshots/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/v3/volumes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/blockstorage/v3/volumetypes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/cdn/v1/base/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/cdn/v1/flavors/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/cdn/v1/serviceassets/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/cdn/v1/services/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/clustering/v1/actions/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/clustering/v1/clusters/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/clustering/v1/events/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/clustering/v1/nodes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/clustering/v1/policies/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/clustering/v1/policytypes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/clustering/v1/profiles/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/clustering/v1/profiletypes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/clustering/v1/receivers/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/apiversions/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/aggregates/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/attachinterfaces/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/availabilityzones/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/bootfromvolume/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/defsecrules/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/diagnostics/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/evacuate/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/extendedserverattributes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/floatingips/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/hypervisors/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/injectnetworkinfo/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/instanceactions/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/keypairs/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/limits/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/lockunlock/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/migrate/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/networks/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/pauseunpause/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/quotasets/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/remoteconsoles/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/rescueunrescue/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/resetnetwork/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/resetstate/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/secgroups/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/servergroups/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/serverusage/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/services/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/shelveunshelve/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/startstop/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/suspendresume/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/tags/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/tenantnetworks/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/usage/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/extensions/volumeattach/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/flavors/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/compute/v2/servers/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/container/v1/capsules/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/containerinfra/apiversions/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/containerinfra/v1/certificates/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/containerinfra/v1/clusters/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/containerinfra/v1/clustertemplates/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/containerinfra/v1/nodegroups/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/containerinfra/v1/quotas/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/db/v1/configurations/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/db/v1/databases/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/db/v1/datastores/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/db/v1/flavors/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/db/v1/instances/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/db/v1/users/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/dns/v2/recordsets/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/dns/v2/transfer/accept/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/dns/v2/transfer/request/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/dns/v2/zones/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v2/extensions/admin/roles/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v2/extensions/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v2/tenants/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v2/tokens/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v2/users/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/applicationcredentials/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/catalog/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/credentials/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/domains/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/extensions/ec2credentials/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/extensions/federation/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/extensions/oauth1/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/extensions/trusts/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/groups/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/limits/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/osinherit/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/policies/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/projects/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/regions/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/registeredlimits/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/roles/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/services/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/identity/v3/users/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/imageservice/v2/imagedata/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/imageservice/v2/imageimport/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/imageservice/v2/images/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/imageservice/v2/members/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/imageservice/v2/tasks/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/keymanager/v1/acls/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/keymanager/v1/containers/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/keymanager/v1/orders/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/keymanager/v1/secrets/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/loadbalancer/v2/amphorae/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/loadbalancer/v2/l7policies/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/loadbalancer/v2/listeners/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/loadbalancer/v2/loadbalancers/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/loadbalancer/v2/monitors/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/loadbalancer/v2/pools/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/loadbalancer/v2/providers/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/loadbalancer/v2/quotas/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/messaging/v2/claims/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/messaging/v2/messages/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/messaging/v2/queues/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/agents/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/attributestags/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/dns/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/external/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/layer3/addressscopes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/layer3/portforwarding/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/lbaas_v2/l7policies/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/lbaas_v2/listeners/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/lbaas_v2/loadbalancers/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/lbaas_v2/monitors/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/lbaas_v2/pools/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/mtu/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/networkipavailabilities/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/portsbinding/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/qos/policies/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/qos/rules/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/qos/ruletypes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/quotas/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/rbacpolicies/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/security/groups/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/subnetpools/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/trunk_details/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/trunks/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/extensions/vlantransparent/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/networking/v2/subnets/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/objectstorage/v1/objects/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/objectstorage/v1/swauth/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/orchestration/v1/buildinfo/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/orchestration/v1/resourcetypes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/orchestration/v1/stackevents/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/orchestration/v1/stackresources/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/orchestration/v1/stacks/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/orchestration/v1/stacktemplates/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/placement/v1/resourceproviders/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/apiversions/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/availabilityzones/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/errors/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/messages/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/replicas/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/schedulerstats/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/securityservices/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/services/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/shareaccessrules/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/sharenetworks/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/shares/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/sharetransfers/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/sharetypes/testing/{fixtures.go => fixtures_test.go} (100%) rename openstack/sharedfilesystems/v2/snapshots/testing/{fixtures.go => fixtures_test.go} (100%) diff --git a/docs/contributor-tutorial/.template/testing/fixtures.go b/docs/contributor-tutorial/.template/testing/fixtures_test.go similarity index 100% rename from docs/contributor-tutorial/.template/testing/fixtures.go rename to docs/contributor-tutorial/.template/testing/fixtures_test.go diff --git a/openstack/baremetal/apiversions/testing/fixtures.go b/openstack/baremetal/apiversions/testing/fixtures_test.go similarity index 100% rename from openstack/baremetal/apiversions/testing/fixtures.go rename to openstack/baremetal/apiversions/testing/fixtures_test.go diff --git a/openstack/baremetal/v1/allocations/testing/fixtures.go b/openstack/baremetal/v1/allocations/testing/fixtures_test.go similarity index 100% rename from openstack/baremetal/v1/allocations/testing/fixtures.go rename to openstack/baremetal/v1/allocations/testing/fixtures_test.go diff --git a/openstack/baremetal/v1/conductors/testing/fixtures.go b/openstack/baremetal/v1/conductors/testing/fixtures_test.go similarity index 100% rename from openstack/baremetal/v1/conductors/testing/fixtures.go rename to openstack/baremetal/v1/conductors/testing/fixtures_test.go diff --git a/openstack/baremetal/v1/drivers/testing/fixtures.go b/openstack/baremetal/v1/drivers/testing/fixtures_test.go similarity index 100% rename from openstack/baremetal/v1/drivers/testing/fixtures.go rename to openstack/baremetal/v1/drivers/testing/fixtures_test.go diff --git a/openstack/baremetal/v1/nodes/testing/fixtures.go b/openstack/baremetal/v1/nodes/testing/fixtures_test.go similarity index 100% rename from openstack/baremetal/v1/nodes/testing/fixtures.go rename to openstack/baremetal/v1/nodes/testing/fixtures_test.go diff --git a/openstack/baremetal/v1/ports/testing/fixtures.go b/openstack/baremetal/v1/ports/testing/fixtures_test.go similarity index 100% rename from openstack/baremetal/v1/ports/testing/fixtures.go rename to openstack/baremetal/v1/ports/testing/fixtures_test.go diff --git a/openstack/baremetalintrospection/v1/introspection/testing/fixtures.go b/openstack/baremetalintrospection/v1/introspection/testing/fixtures_test.go similarity index 100% rename from openstack/baremetalintrospection/v1/introspection/testing/fixtures.go rename to openstack/baremetalintrospection/v1/introspection/testing/fixtures_test.go diff --git a/openstack/blockstorage/apiversions/testing/fixtures.go b/openstack/blockstorage/apiversions/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/apiversions/testing/fixtures.go rename to openstack/blockstorage/apiversions/testing/fixtures_test.go diff --git a/openstack/blockstorage/extensions/availabilityzones/testing/fixtures.go b/openstack/blockstorage/extensions/availabilityzones/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/extensions/availabilityzones/testing/fixtures.go rename to openstack/blockstorage/extensions/availabilityzones/testing/fixtures_test.go diff --git a/openstack/blockstorage/extensions/backups/testing/fixtures.go b/openstack/blockstorage/extensions/backups/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/extensions/backups/testing/fixtures.go rename to openstack/blockstorage/extensions/backups/testing/fixtures_test.go diff --git a/openstack/blockstorage/extensions/limits/testing/fixtures.go b/openstack/blockstorage/extensions/limits/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/extensions/limits/testing/fixtures.go rename to openstack/blockstorage/extensions/limits/testing/fixtures_test.go diff --git a/openstack/blockstorage/extensions/quotasets/testing/fixtures.go b/openstack/blockstorage/extensions/quotasets/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/extensions/quotasets/testing/fixtures.go rename to openstack/blockstorage/extensions/quotasets/testing/fixtures_test.go diff --git a/openstack/blockstorage/extensions/schedulerstats/testing/fixtures.go b/openstack/blockstorage/extensions/schedulerstats/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/extensions/schedulerstats/testing/fixtures.go rename to openstack/blockstorage/extensions/schedulerstats/testing/fixtures_test.go diff --git a/openstack/blockstorage/extensions/services/testing/fixtures.go b/openstack/blockstorage/extensions/services/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/extensions/services/testing/fixtures.go rename to openstack/blockstorage/extensions/services/testing/fixtures_test.go diff --git a/openstack/blockstorage/extensions/volumeactions/testing/fixtures.go b/openstack/blockstorage/extensions/volumeactions/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/extensions/volumeactions/testing/fixtures.go rename to openstack/blockstorage/extensions/volumeactions/testing/fixtures_test.go diff --git a/openstack/blockstorage/extensions/volumetransfers/testing/fixtures.go b/openstack/blockstorage/extensions/volumetransfers/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/extensions/volumetransfers/testing/fixtures.go rename to openstack/blockstorage/extensions/volumetransfers/testing/fixtures_test.go diff --git a/openstack/blockstorage/noauth/testing/fixtures.go b/openstack/blockstorage/noauth/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/noauth/testing/fixtures.go rename to openstack/blockstorage/noauth/testing/fixtures_test.go diff --git a/openstack/blockstorage/v1/apiversions/testing/fixtures.go b/openstack/blockstorage/v1/apiversions/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/v1/apiversions/testing/fixtures.go rename to openstack/blockstorage/v1/apiversions/testing/fixtures_test.go diff --git a/openstack/blockstorage/v1/snapshots/testing/fixtures.go b/openstack/blockstorage/v1/snapshots/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/v1/snapshots/testing/fixtures.go rename to openstack/blockstorage/v1/snapshots/testing/fixtures_test.go diff --git a/openstack/blockstorage/v1/volumes/testing/fixtures.go b/openstack/blockstorage/v1/volumes/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/v1/volumes/testing/fixtures.go rename to openstack/blockstorage/v1/volumes/testing/fixtures_test.go diff --git a/openstack/blockstorage/v1/volumetypes/testing/fixtures.go b/openstack/blockstorage/v1/volumetypes/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/v1/volumetypes/testing/fixtures.go rename to openstack/blockstorage/v1/volumetypes/testing/fixtures_test.go diff --git a/openstack/blockstorage/v2/snapshots/testing/fixtures.go b/openstack/blockstorage/v2/snapshots/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/v2/snapshots/testing/fixtures.go rename to openstack/blockstorage/v2/snapshots/testing/fixtures_test.go diff --git a/openstack/blockstorage/v2/volumes/testing/fixtures.go b/openstack/blockstorage/v2/volumes/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/v2/volumes/testing/fixtures.go rename to openstack/blockstorage/v2/volumes/testing/fixtures_test.go diff --git a/openstack/blockstorage/v3/attachments/testing/fixtures.go b/openstack/blockstorage/v3/attachments/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/v3/attachments/testing/fixtures.go rename to openstack/blockstorage/v3/attachments/testing/fixtures_test.go diff --git a/openstack/blockstorage/v3/qos/testing/fixtures.go b/openstack/blockstorage/v3/qos/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/v3/qos/testing/fixtures.go rename to openstack/blockstorage/v3/qos/testing/fixtures_test.go diff --git a/openstack/blockstorage/v3/snapshots/testing/fixtures.go b/openstack/blockstorage/v3/snapshots/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/v3/snapshots/testing/fixtures.go rename to openstack/blockstorage/v3/snapshots/testing/fixtures_test.go diff --git a/openstack/blockstorage/v3/volumes/testing/fixtures.go b/openstack/blockstorage/v3/volumes/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/v3/volumes/testing/fixtures.go rename to openstack/blockstorage/v3/volumes/testing/fixtures_test.go diff --git a/openstack/blockstorage/v3/volumetypes/testing/fixtures.go b/openstack/blockstorage/v3/volumetypes/testing/fixtures_test.go similarity index 100% rename from openstack/blockstorage/v3/volumetypes/testing/fixtures.go rename to openstack/blockstorage/v3/volumetypes/testing/fixtures_test.go diff --git a/openstack/cdn/v1/base/testing/fixtures.go b/openstack/cdn/v1/base/testing/fixtures_test.go similarity index 100% rename from openstack/cdn/v1/base/testing/fixtures.go rename to openstack/cdn/v1/base/testing/fixtures_test.go diff --git a/openstack/cdn/v1/flavors/testing/fixtures.go b/openstack/cdn/v1/flavors/testing/fixtures_test.go similarity index 100% rename from openstack/cdn/v1/flavors/testing/fixtures.go rename to openstack/cdn/v1/flavors/testing/fixtures_test.go diff --git a/openstack/cdn/v1/serviceassets/testing/fixtures.go b/openstack/cdn/v1/serviceassets/testing/fixtures_test.go similarity index 100% rename from openstack/cdn/v1/serviceassets/testing/fixtures.go rename to openstack/cdn/v1/serviceassets/testing/fixtures_test.go diff --git a/openstack/cdn/v1/services/testing/fixtures.go b/openstack/cdn/v1/services/testing/fixtures_test.go similarity index 100% rename from openstack/cdn/v1/services/testing/fixtures.go rename to openstack/cdn/v1/services/testing/fixtures_test.go diff --git a/openstack/clustering/v1/actions/testing/fixtures.go b/openstack/clustering/v1/actions/testing/fixtures_test.go similarity index 100% rename from openstack/clustering/v1/actions/testing/fixtures.go rename to openstack/clustering/v1/actions/testing/fixtures_test.go diff --git a/openstack/clustering/v1/clusters/testing/fixtures.go b/openstack/clustering/v1/clusters/testing/fixtures_test.go similarity index 100% rename from openstack/clustering/v1/clusters/testing/fixtures.go rename to openstack/clustering/v1/clusters/testing/fixtures_test.go diff --git a/openstack/clustering/v1/events/testing/fixtures.go b/openstack/clustering/v1/events/testing/fixtures_test.go similarity index 100% rename from openstack/clustering/v1/events/testing/fixtures.go rename to openstack/clustering/v1/events/testing/fixtures_test.go diff --git a/openstack/clustering/v1/nodes/testing/fixtures.go b/openstack/clustering/v1/nodes/testing/fixtures_test.go similarity index 100% rename from openstack/clustering/v1/nodes/testing/fixtures.go rename to openstack/clustering/v1/nodes/testing/fixtures_test.go diff --git a/openstack/clustering/v1/policies/testing/fixtures.go b/openstack/clustering/v1/policies/testing/fixtures_test.go similarity index 100% rename from openstack/clustering/v1/policies/testing/fixtures.go rename to openstack/clustering/v1/policies/testing/fixtures_test.go diff --git a/openstack/clustering/v1/policytypes/testing/fixtures.go b/openstack/clustering/v1/policytypes/testing/fixtures_test.go similarity index 100% rename from openstack/clustering/v1/policytypes/testing/fixtures.go rename to openstack/clustering/v1/policytypes/testing/fixtures_test.go diff --git a/openstack/clustering/v1/profiles/testing/fixtures.go b/openstack/clustering/v1/profiles/testing/fixtures_test.go similarity index 100% rename from openstack/clustering/v1/profiles/testing/fixtures.go rename to openstack/clustering/v1/profiles/testing/fixtures_test.go diff --git a/openstack/clustering/v1/profiletypes/testing/fixtures.go b/openstack/clustering/v1/profiletypes/testing/fixtures_test.go similarity index 100% rename from openstack/clustering/v1/profiletypes/testing/fixtures.go rename to openstack/clustering/v1/profiletypes/testing/fixtures_test.go diff --git a/openstack/clustering/v1/receivers/testing/fixtures.go b/openstack/clustering/v1/receivers/testing/fixtures_test.go similarity index 100% rename from openstack/clustering/v1/receivers/testing/fixtures.go rename to openstack/clustering/v1/receivers/testing/fixtures_test.go diff --git a/openstack/compute/apiversions/testing/fixtures.go b/openstack/compute/apiversions/testing/fixtures_test.go similarity index 100% rename from openstack/compute/apiversions/testing/fixtures.go rename to openstack/compute/apiversions/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/aggregates/testing/fixtures.go b/openstack/compute/v2/extensions/aggregates/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/aggregates/testing/fixtures.go rename to openstack/compute/v2/extensions/aggregates/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/attachinterfaces/testing/fixtures.go b/openstack/compute/v2/extensions/attachinterfaces/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/attachinterfaces/testing/fixtures.go rename to openstack/compute/v2/extensions/attachinterfaces/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/availabilityzones/testing/fixtures.go b/openstack/compute/v2/extensions/availabilityzones/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/availabilityzones/testing/fixtures.go rename to openstack/compute/v2/extensions/availabilityzones/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/bootfromvolume/testing/fixtures.go b/openstack/compute/v2/extensions/bootfromvolume/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/bootfromvolume/testing/fixtures.go rename to openstack/compute/v2/extensions/bootfromvolume/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/defsecrules/testing/fixtures.go b/openstack/compute/v2/extensions/defsecrules/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/defsecrules/testing/fixtures.go rename to openstack/compute/v2/extensions/defsecrules/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/diagnostics/testing/fixtures.go b/openstack/compute/v2/extensions/diagnostics/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/diagnostics/testing/fixtures.go rename to openstack/compute/v2/extensions/diagnostics/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/evacuate/testing/fixtures.go b/openstack/compute/v2/extensions/evacuate/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/evacuate/testing/fixtures.go rename to openstack/compute/v2/extensions/evacuate/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/extendedserverattributes/testing/fixtures.go b/openstack/compute/v2/extensions/extendedserverattributes/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/extendedserverattributes/testing/fixtures.go rename to openstack/compute/v2/extensions/extendedserverattributes/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/floatingips/testing/fixtures.go b/openstack/compute/v2/extensions/floatingips/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/floatingips/testing/fixtures.go rename to openstack/compute/v2/extensions/floatingips/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/hypervisors/testing/fixtures.go b/openstack/compute/v2/extensions/hypervisors/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/hypervisors/testing/fixtures.go rename to openstack/compute/v2/extensions/hypervisors/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/injectnetworkinfo/testing/fixtures.go b/openstack/compute/v2/extensions/injectnetworkinfo/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/injectnetworkinfo/testing/fixtures.go rename to openstack/compute/v2/extensions/injectnetworkinfo/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/instanceactions/testing/fixtures.go b/openstack/compute/v2/extensions/instanceactions/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/instanceactions/testing/fixtures.go rename to openstack/compute/v2/extensions/instanceactions/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/keypairs/testing/fixtures.go b/openstack/compute/v2/extensions/keypairs/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/keypairs/testing/fixtures.go rename to openstack/compute/v2/extensions/keypairs/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/limits/testing/fixtures.go b/openstack/compute/v2/extensions/limits/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/limits/testing/fixtures.go rename to openstack/compute/v2/extensions/limits/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/lockunlock/testing/fixtures.go b/openstack/compute/v2/extensions/lockunlock/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/lockunlock/testing/fixtures.go rename to openstack/compute/v2/extensions/lockunlock/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/migrate/testing/fixtures.go b/openstack/compute/v2/extensions/migrate/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/migrate/testing/fixtures.go rename to openstack/compute/v2/extensions/migrate/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/networks/testing/fixtures.go b/openstack/compute/v2/extensions/networks/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/networks/testing/fixtures.go rename to openstack/compute/v2/extensions/networks/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/pauseunpause/testing/fixtures.go b/openstack/compute/v2/extensions/pauseunpause/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/pauseunpause/testing/fixtures.go rename to openstack/compute/v2/extensions/pauseunpause/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/quotasets/testing/fixtures.go b/openstack/compute/v2/extensions/quotasets/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/quotasets/testing/fixtures.go rename to openstack/compute/v2/extensions/quotasets/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/remoteconsoles/testing/fixtures.go b/openstack/compute/v2/extensions/remoteconsoles/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/remoteconsoles/testing/fixtures.go rename to openstack/compute/v2/extensions/remoteconsoles/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/rescueunrescue/testing/fixtures.go b/openstack/compute/v2/extensions/rescueunrescue/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/rescueunrescue/testing/fixtures.go rename to openstack/compute/v2/extensions/rescueunrescue/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/resetnetwork/testing/fixtures.go b/openstack/compute/v2/extensions/resetnetwork/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/resetnetwork/testing/fixtures.go rename to openstack/compute/v2/extensions/resetnetwork/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/resetstate/testing/fixtures.go b/openstack/compute/v2/extensions/resetstate/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/resetstate/testing/fixtures.go rename to openstack/compute/v2/extensions/resetstate/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/secgroups/testing/fixtures.go b/openstack/compute/v2/extensions/secgroups/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/secgroups/testing/fixtures.go rename to openstack/compute/v2/extensions/secgroups/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/servergroups/testing/fixtures.go b/openstack/compute/v2/extensions/servergroups/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/servergroups/testing/fixtures.go rename to openstack/compute/v2/extensions/servergroups/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/serverusage/testing/fixtures.go b/openstack/compute/v2/extensions/serverusage/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/serverusage/testing/fixtures.go rename to openstack/compute/v2/extensions/serverusage/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/services/testing/fixtures.go b/openstack/compute/v2/extensions/services/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/services/testing/fixtures.go rename to openstack/compute/v2/extensions/services/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/shelveunshelve/testing/fixtures.go b/openstack/compute/v2/extensions/shelveunshelve/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/shelveunshelve/testing/fixtures.go rename to openstack/compute/v2/extensions/shelveunshelve/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/startstop/testing/fixtures.go b/openstack/compute/v2/extensions/startstop/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/startstop/testing/fixtures.go rename to openstack/compute/v2/extensions/startstop/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/suspendresume/testing/fixtures.go b/openstack/compute/v2/extensions/suspendresume/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/suspendresume/testing/fixtures.go rename to openstack/compute/v2/extensions/suspendresume/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/tags/testing/fixtures.go b/openstack/compute/v2/extensions/tags/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/tags/testing/fixtures.go rename to openstack/compute/v2/extensions/tags/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/tenantnetworks/testing/fixtures.go b/openstack/compute/v2/extensions/tenantnetworks/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/tenantnetworks/testing/fixtures.go rename to openstack/compute/v2/extensions/tenantnetworks/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/testing/fixtures.go b/openstack/compute/v2/extensions/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/testing/fixtures.go rename to openstack/compute/v2/extensions/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/usage/testing/fixtures.go b/openstack/compute/v2/extensions/usage/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/usage/testing/fixtures.go rename to openstack/compute/v2/extensions/usage/testing/fixtures_test.go diff --git a/openstack/compute/v2/extensions/volumeattach/testing/fixtures.go b/openstack/compute/v2/extensions/volumeattach/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/extensions/volumeattach/testing/fixtures.go rename to openstack/compute/v2/extensions/volumeattach/testing/fixtures_test.go diff --git a/openstack/compute/v2/flavors/testing/fixtures.go b/openstack/compute/v2/flavors/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/flavors/testing/fixtures.go rename to openstack/compute/v2/flavors/testing/fixtures_test.go diff --git a/openstack/compute/v2/servers/testing/fixtures.go b/openstack/compute/v2/servers/testing/fixtures_test.go similarity index 100% rename from openstack/compute/v2/servers/testing/fixtures.go rename to openstack/compute/v2/servers/testing/fixtures_test.go diff --git a/openstack/container/v1/capsules/testing/fixtures.go b/openstack/container/v1/capsules/testing/fixtures_test.go similarity index 100% rename from openstack/container/v1/capsules/testing/fixtures.go rename to openstack/container/v1/capsules/testing/fixtures_test.go diff --git a/openstack/containerinfra/apiversions/testing/fixtures.go b/openstack/containerinfra/apiversions/testing/fixtures_test.go similarity index 100% rename from openstack/containerinfra/apiversions/testing/fixtures.go rename to openstack/containerinfra/apiversions/testing/fixtures_test.go diff --git a/openstack/containerinfra/v1/certificates/testing/fixtures.go b/openstack/containerinfra/v1/certificates/testing/fixtures_test.go similarity index 100% rename from openstack/containerinfra/v1/certificates/testing/fixtures.go rename to openstack/containerinfra/v1/certificates/testing/fixtures_test.go diff --git a/openstack/containerinfra/v1/clusters/testing/fixtures.go b/openstack/containerinfra/v1/clusters/testing/fixtures_test.go similarity index 100% rename from openstack/containerinfra/v1/clusters/testing/fixtures.go rename to openstack/containerinfra/v1/clusters/testing/fixtures_test.go diff --git a/openstack/containerinfra/v1/clustertemplates/testing/fixtures.go b/openstack/containerinfra/v1/clustertemplates/testing/fixtures_test.go similarity index 100% rename from openstack/containerinfra/v1/clustertemplates/testing/fixtures.go rename to openstack/containerinfra/v1/clustertemplates/testing/fixtures_test.go diff --git a/openstack/containerinfra/v1/nodegroups/testing/fixtures.go b/openstack/containerinfra/v1/nodegroups/testing/fixtures_test.go similarity index 100% rename from openstack/containerinfra/v1/nodegroups/testing/fixtures.go rename to openstack/containerinfra/v1/nodegroups/testing/fixtures_test.go diff --git a/openstack/containerinfra/v1/quotas/testing/fixtures.go b/openstack/containerinfra/v1/quotas/testing/fixtures_test.go similarity index 100% rename from openstack/containerinfra/v1/quotas/testing/fixtures.go rename to openstack/containerinfra/v1/quotas/testing/fixtures_test.go diff --git a/openstack/db/v1/configurations/testing/fixtures.go b/openstack/db/v1/configurations/testing/fixtures_test.go similarity index 100% rename from openstack/db/v1/configurations/testing/fixtures.go rename to openstack/db/v1/configurations/testing/fixtures_test.go diff --git a/openstack/db/v1/databases/testing/fixtures.go b/openstack/db/v1/databases/testing/fixtures_test.go similarity index 100% rename from openstack/db/v1/databases/testing/fixtures.go rename to openstack/db/v1/databases/testing/fixtures_test.go diff --git a/openstack/db/v1/datastores/testing/fixtures.go b/openstack/db/v1/datastores/testing/fixtures_test.go similarity index 100% rename from openstack/db/v1/datastores/testing/fixtures.go rename to openstack/db/v1/datastores/testing/fixtures_test.go diff --git a/openstack/db/v1/flavors/testing/fixtures.go b/openstack/db/v1/flavors/testing/fixtures_test.go similarity index 100% rename from openstack/db/v1/flavors/testing/fixtures.go rename to openstack/db/v1/flavors/testing/fixtures_test.go diff --git a/openstack/db/v1/instances/testing/fixtures.go b/openstack/db/v1/instances/testing/fixtures_test.go similarity index 100% rename from openstack/db/v1/instances/testing/fixtures.go rename to openstack/db/v1/instances/testing/fixtures_test.go diff --git a/openstack/db/v1/users/testing/fixtures.go b/openstack/db/v1/users/testing/fixtures_test.go similarity index 100% rename from openstack/db/v1/users/testing/fixtures.go rename to openstack/db/v1/users/testing/fixtures_test.go diff --git a/openstack/dns/v2/recordsets/testing/fixtures.go b/openstack/dns/v2/recordsets/testing/fixtures_test.go similarity index 100% rename from openstack/dns/v2/recordsets/testing/fixtures.go rename to openstack/dns/v2/recordsets/testing/fixtures_test.go diff --git a/openstack/dns/v2/transfer/accept/testing/fixtures.go b/openstack/dns/v2/transfer/accept/testing/fixtures_test.go similarity index 100% rename from openstack/dns/v2/transfer/accept/testing/fixtures.go rename to openstack/dns/v2/transfer/accept/testing/fixtures_test.go diff --git a/openstack/dns/v2/transfer/request/testing/fixtures.go b/openstack/dns/v2/transfer/request/testing/fixtures_test.go similarity index 100% rename from openstack/dns/v2/transfer/request/testing/fixtures.go rename to openstack/dns/v2/transfer/request/testing/fixtures_test.go diff --git a/openstack/dns/v2/zones/testing/fixtures.go b/openstack/dns/v2/zones/testing/fixtures_test.go similarity index 100% rename from openstack/dns/v2/zones/testing/fixtures.go rename to openstack/dns/v2/zones/testing/fixtures_test.go diff --git a/openstack/identity/v2/extensions/admin/roles/testing/fixtures.go b/openstack/identity/v2/extensions/admin/roles/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v2/extensions/admin/roles/testing/fixtures.go rename to openstack/identity/v2/extensions/admin/roles/testing/fixtures_test.go diff --git a/openstack/identity/v2/extensions/testing/fixtures.go b/openstack/identity/v2/extensions/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v2/extensions/testing/fixtures.go rename to openstack/identity/v2/extensions/testing/fixtures_test.go diff --git a/openstack/identity/v2/tenants/testing/fixtures.go b/openstack/identity/v2/tenants/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v2/tenants/testing/fixtures.go rename to openstack/identity/v2/tenants/testing/fixtures_test.go diff --git a/openstack/identity/v2/tokens/testing/fixtures.go b/openstack/identity/v2/tokens/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v2/tokens/testing/fixtures.go rename to openstack/identity/v2/tokens/testing/fixtures_test.go diff --git a/openstack/identity/v2/users/testing/fixtures.go b/openstack/identity/v2/users/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v2/users/testing/fixtures.go rename to openstack/identity/v2/users/testing/fixtures_test.go diff --git a/openstack/identity/v3/applicationcredentials/testing/fixtures.go b/openstack/identity/v3/applicationcredentials/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/applicationcredentials/testing/fixtures.go rename to openstack/identity/v3/applicationcredentials/testing/fixtures_test.go diff --git a/openstack/identity/v3/catalog/testing/fixtures.go b/openstack/identity/v3/catalog/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/catalog/testing/fixtures.go rename to openstack/identity/v3/catalog/testing/fixtures_test.go diff --git a/openstack/identity/v3/credentials/testing/fixtures.go b/openstack/identity/v3/credentials/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/credentials/testing/fixtures.go rename to openstack/identity/v3/credentials/testing/fixtures_test.go diff --git a/openstack/identity/v3/domains/testing/fixtures.go b/openstack/identity/v3/domains/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/domains/testing/fixtures.go rename to openstack/identity/v3/domains/testing/fixtures_test.go diff --git a/openstack/identity/v3/extensions/ec2credentials/testing/fixtures.go b/openstack/identity/v3/extensions/ec2credentials/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/extensions/ec2credentials/testing/fixtures.go rename to openstack/identity/v3/extensions/ec2credentials/testing/fixtures_test.go diff --git a/openstack/identity/v3/extensions/federation/testing/fixtures.go b/openstack/identity/v3/extensions/federation/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/extensions/federation/testing/fixtures.go rename to openstack/identity/v3/extensions/federation/testing/fixtures_test.go diff --git a/openstack/identity/v3/extensions/oauth1/testing/fixtures.go b/openstack/identity/v3/extensions/oauth1/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/extensions/oauth1/testing/fixtures.go rename to openstack/identity/v3/extensions/oauth1/testing/fixtures_test.go diff --git a/openstack/identity/v3/extensions/trusts/testing/fixtures.go b/openstack/identity/v3/extensions/trusts/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/extensions/trusts/testing/fixtures.go rename to openstack/identity/v3/extensions/trusts/testing/fixtures_test.go diff --git a/openstack/identity/v3/groups/testing/fixtures.go b/openstack/identity/v3/groups/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/groups/testing/fixtures.go rename to openstack/identity/v3/groups/testing/fixtures_test.go diff --git a/openstack/identity/v3/limits/testing/fixtures.go b/openstack/identity/v3/limits/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/limits/testing/fixtures.go rename to openstack/identity/v3/limits/testing/fixtures_test.go diff --git a/openstack/identity/v3/osinherit/testing/fixtures.go b/openstack/identity/v3/osinherit/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/osinherit/testing/fixtures.go rename to openstack/identity/v3/osinherit/testing/fixtures_test.go diff --git a/openstack/identity/v3/policies/testing/fixtures.go b/openstack/identity/v3/policies/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/policies/testing/fixtures.go rename to openstack/identity/v3/policies/testing/fixtures_test.go diff --git a/openstack/identity/v3/projects/testing/fixtures.go b/openstack/identity/v3/projects/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/projects/testing/fixtures.go rename to openstack/identity/v3/projects/testing/fixtures_test.go diff --git a/openstack/identity/v3/regions/testing/fixtures.go b/openstack/identity/v3/regions/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/regions/testing/fixtures.go rename to openstack/identity/v3/regions/testing/fixtures_test.go diff --git a/openstack/identity/v3/registeredlimits/testing/fixtures.go b/openstack/identity/v3/registeredlimits/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/registeredlimits/testing/fixtures.go rename to openstack/identity/v3/registeredlimits/testing/fixtures_test.go diff --git a/openstack/identity/v3/roles/testing/fixtures.go b/openstack/identity/v3/roles/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/roles/testing/fixtures.go rename to openstack/identity/v3/roles/testing/fixtures_test.go diff --git a/openstack/identity/v3/services/testing/fixtures.go b/openstack/identity/v3/services/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/services/testing/fixtures.go rename to openstack/identity/v3/services/testing/fixtures_test.go diff --git a/openstack/identity/v3/users/testing/fixtures.go b/openstack/identity/v3/users/testing/fixtures_test.go similarity index 100% rename from openstack/identity/v3/users/testing/fixtures.go rename to openstack/identity/v3/users/testing/fixtures_test.go diff --git a/openstack/imageservice/v2/imagedata/testing/fixtures.go b/openstack/imageservice/v2/imagedata/testing/fixtures_test.go similarity index 100% rename from openstack/imageservice/v2/imagedata/testing/fixtures.go rename to openstack/imageservice/v2/imagedata/testing/fixtures_test.go diff --git a/openstack/imageservice/v2/imageimport/testing/fixtures.go b/openstack/imageservice/v2/imageimport/testing/fixtures_test.go similarity index 100% rename from openstack/imageservice/v2/imageimport/testing/fixtures.go rename to openstack/imageservice/v2/imageimport/testing/fixtures_test.go diff --git a/openstack/imageservice/v2/images/testing/fixtures.go b/openstack/imageservice/v2/images/testing/fixtures_test.go similarity index 100% rename from openstack/imageservice/v2/images/testing/fixtures.go rename to openstack/imageservice/v2/images/testing/fixtures_test.go diff --git a/openstack/imageservice/v2/members/testing/fixtures.go b/openstack/imageservice/v2/members/testing/fixtures_test.go similarity index 100% rename from openstack/imageservice/v2/members/testing/fixtures.go rename to openstack/imageservice/v2/members/testing/fixtures_test.go diff --git a/openstack/imageservice/v2/tasks/testing/fixtures.go b/openstack/imageservice/v2/tasks/testing/fixtures_test.go similarity index 100% rename from openstack/imageservice/v2/tasks/testing/fixtures.go rename to openstack/imageservice/v2/tasks/testing/fixtures_test.go diff --git a/openstack/keymanager/v1/acls/testing/fixtures.go b/openstack/keymanager/v1/acls/testing/fixtures_test.go similarity index 100% rename from openstack/keymanager/v1/acls/testing/fixtures.go rename to openstack/keymanager/v1/acls/testing/fixtures_test.go diff --git a/openstack/keymanager/v1/containers/testing/fixtures.go b/openstack/keymanager/v1/containers/testing/fixtures_test.go similarity index 100% rename from openstack/keymanager/v1/containers/testing/fixtures.go rename to openstack/keymanager/v1/containers/testing/fixtures_test.go diff --git a/openstack/keymanager/v1/orders/testing/fixtures.go b/openstack/keymanager/v1/orders/testing/fixtures_test.go similarity index 100% rename from openstack/keymanager/v1/orders/testing/fixtures.go rename to openstack/keymanager/v1/orders/testing/fixtures_test.go diff --git a/openstack/keymanager/v1/secrets/testing/fixtures.go b/openstack/keymanager/v1/secrets/testing/fixtures_test.go similarity index 100% rename from openstack/keymanager/v1/secrets/testing/fixtures.go rename to openstack/keymanager/v1/secrets/testing/fixtures_test.go diff --git a/openstack/loadbalancer/v2/amphorae/testing/fixtures.go b/openstack/loadbalancer/v2/amphorae/testing/fixtures_test.go similarity index 100% rename from openstack/loadbalancer/v2/amphorae/testing/fixtures.go rename to openstack/loadbalancer/v2/amphorae/testing/fixtures_test.go diff --git a/openstack/loadbalancer/v2/l7policies/testing/fixtures.go b/openstack/loadbalancer/v2/l7policies/testing/fixtures_test.go similarity index 100% rename from openstack/loadbalancer/v2/l7policies/testing/fixtures.go rename to openstack/loadbalancer/v2/l7policies/testing/fixtures_test.go diff --git a/openstack/loadbalancer/v2/listeners/testing/fixtures.go b/openstack/loadbalancer/v2/listeners/testing/fixtures_test.go similarity index 100% rename from openstack/loadbalancer/v2/listeners/testing/fixtures.go rename to openstack/loadbalancer/v2/listeners/testing/fixtures_test.go diff --git a/openstack/loadbalancer/v2/loadbalancers/testing/fixtures.go b/openstack/loadbalancer/v2/loadbalancers/testing/fixtures_test.go similarity index 100% rename from openstack/loadbalancer/v2/loadbalancers/testing/fixtures.go rename to openstack/loadbalancer/v2/loadbalancers/testing/fixtures_test.go diff --git a/openstack/loadbalancer/v2/monitors/testing/fixtures.go b/openstack/loadbalancer/v2/monitors/testing/fixtures_test.go similarity index 100% rename from openstack/loadbalancer/v2/monitors/testing/fixtures.go rename to openstack/loadbalancer/v2/monitors/testing/fixtures_test.go diff --git a/openstack/loadbalancer/v2/pools/testing/fixtures.go b/openstack/loadbalancer/v2/pools/testing/fixtures_test.go similarity index 100% rename from openstack/loadbalancer/v2/pools/testing/fixtures.go rename to openstack/loadbalancer/v2/pools/testing/fixtures_test.go diff --git a/openstack/loadbalancer/v2/providers/testing/fixtures.go b/openstack/loadbalancer/v2/providers/testing/fixtures_test.go similarity index 100% rename from openstack/loadbalancer/v2/providers/testing/fixtures.go rename to openstack/loadbalancer/v2/providers/testing/fixtures_test.go diff --git a/openstack/loadbalancer/v2/quotas/testing/fixtures.go b/openstack/loadbalancer/v2/quotas/testing/fixtures_test.go similarity index 100% rename from openstack/loadbalancer/v2/quotas/testing/fixtures.go rename to openstack/loadbalancer/v2/quotas/testing/fixtures_test.go diff --git a/openstack/messaging/v2/claims/testing/fixtures.go b/openstack/messaging/v2/claims/testing/fixtures_test.go similarity index 100% rename from openstack/messaging/v2/claims/testing/fixtures.go rename to openstack/messaging/v2/claims/testing/fixtures_test.go diff --git a/openstack/messaging/v2/messages/testing/fixtures.go b/openstack/messaging/v2/messages/testing/fixtures_test.go similarity index 100% rename from openstack/messaging/v2/messages/testing/fixtures.go rename to openstack/messaging/v2/messages/testing/fixtures_test.go diff --git a/openstack/messaging/v2/queues/testing/fixtures.go b/openstack/messaging/v2/queues/testing/fixtures_test.go similarity index 100% rename from openstack/messaging/v2/queues/testing/fixtures.go rename to openstack/messaging/v2/queues/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/agents/testing/fixtures.go b/openstack/networking/v2/extensions/agents/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/agents/testing/fixtures.go rename to openstack/networking/v2/extensions/agents/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/attributestags/testing/fixtures.go b/openstack/networking/v2/extensions/attributestags/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/attributestags/testing/fixtures.go rename to openstack/networking/v2/extensions/attributestags/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/dns/testing/fixtures.go b/openstack/networking/v2/extensions/dns/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/dns/testing/fixtures.go rename to openstack/networking/v2/extensions/dns/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/external/testing/fixtures.go b/openstack/networking/v2/extensions/external/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/external/testing/fixtures.go rename to openstack/networking/v2/extensions/external/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/layer3/addressscopes/testing/fixtures.go b/openstack/networking/v2/extensions/layer3/addressscopes/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/layer3/addressscopes/testing/fixtures.go rename to openstack/networking/v2/extensions/layer3/addressscopes/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/layer3/portforwarding/testing/fixtures.go b/openstack/networking/v2/extensions/layer3/portforwarding/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/layer3/portforwarding/testing/fixtures.go rename to openstack/networking/v2/extensions/layer3/portforwarding/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/lbaas_v2/l7policies/testing/fixtures.go b/openstack/networking/v2/extensions/lbaas_v2/l7policies/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/lbaas_v2/l7policies/testing/fixtures.go rename to openstack/networking/v2/extensions/lbaas_v2/l7policies/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/lbaas_v2/listeners/testing/fixtures.go b/openstack/networking/v2/extensions/lbaas_v2/listeners/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/lbaas_v2/listeners/testing/fixtures.go rename to openstack/networking/v2/extensions/lbaas_v2/listeners/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/lbaas_v2/loadbalancers/testing/fixtures.go b/openstack/networking/v2/extensions/lbaas_v2/loadbalancers/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/lbaas_v2/loadbalancers/testing/fixtures.go rename to openstack/networking/v2/extensions/lbaas_v2/loadbalancers/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/lbaas_v2/monitors/testing/fixtures.go b/openstack/networking/v2/extensions/lbaas_v2/monitors/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/lbaas_v2/monitors/testing/fixtures.go rename to openstack/networking/v2/extensions/lbaas_v2/monitors/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/lbaas_v2/pools/testing/fixtures.go b/openstack/networking/v2/extensions/lbaas_v2/pools/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/lbaas_v2/pools/testing/fixtures.go rename to openstack/networking/v2/extensions/lbaas_v2/pools/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/mtu/testing/fixtures.go b/openstack/networking/v2/extensions/mtu/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/mtu/testing/fixtures.go rename to openstack/networking/v2/extensions/mtu/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/networkipavailabilities/testing/fixtures.go b/openstack/networking/v2/extensions/networkipavailabilities/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/networkipavailabilities/testing/fixtures.go rename to openstack/networking/v2/extensions/networkipavailabilities/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/portsbinding/testing/fixtures.go b/openstack/networking/v2/extensions/portsbinding/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/portsbinding/testing/fixtures.go rename to openstack/networking/v2/extensions/portsbinding/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/qos/policies/testing/fixtures.go b/openstack/networking/v2/extensions/qos/policies/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/qos/policies/testing/fixtures.go rename to openstack/networking/v2/extensions/qos/policies/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/qos/rules/testing/fixtures.go b/openstack/networking/v2/extensions/qos/rules/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/qos/rules/testing/fixtures.go rename to openstack/networking/v2/extensions/qos/rules/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/qos/ruletypes/testing/fixtures.go b/openstack/networking/v2/extensions/qos/ruletypes/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/qos/ruletypes/testing/fixtures.go rename to openstack/networking/v2/extensions/qos/ruletypes/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/quotas/testing/fixtures.go b/openstack/networking/v2/extensions/quotas/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/quotas/testing/fixtures.go rename to openstack/networking/v2/extensions/quotas/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/rbacpolicies/testing/fixtures.go b/openstack/networking/v2/extensions/rbacpolicies/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/rbacpolicies/testing/fixtures.go rename to openstack/networking/v2/extensions/rbacpolicies/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/security/groups/testing/fixtures.go b/openstack/networking/v2/extensions/security/groups/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/security/groups/testing/fixtures.go rename to openstack/networking/v2/extensions/security/groups/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/subnetpools/testing/fixtures.go b/openstack/networking/v2/extensions/subnetpools/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/subnetpools/testing/fixtures.go rename to openstack/networking/v2/extensions/subnetpools/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/trunk_details/testing/fixtures.go b/openstack/networking/v2/extensions/trunk_details/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/trunk_details/testing/fixtures.go rename to openstack/networking/v2/extensions/trunk_details/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/trunks/testing/fixtures.go b/openstack/networking/v2/extensions/trunks/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/trunks/testing/fixtures.go rename to openstack/networking/v2/extensions/trunks/testing/fixtures_test.go diff --git a/openstack/networking/v2/extensions/vlantransparent/testing/fixtures.go b/openstack/networking/v2/extensions/vlantransparent/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/extensions/vlantransparent/testing/fixtures.go rename to openstack/networking/v2/extensions/vlantransparent/testing/fixtures_test.go diff --git a/openstack/networking/v2/subnets/testing/fixtures.go b/openstack/networking/v2/subnets/testing/fixtures_test.go similarity index 100% rename from openstack/networking/v2/subnets/testing/fixtures.go rename to openstack/networking/v2/subnets/testing/fixtures_test.go diff --git a/openstack/objectstorage/v1/objects/testing/fixtures.go b/openstack/objectstorage/v1/objects/testing/fixtures_test.go similarity index 100% rename from openstack/objectstorage/v1/objects/testing/fixtures.go rename to openstack/objectstorage/v1/objects/testing/fixtures_test.go diff --git a/openstack/objectstorage/v1/swauth/testing/fixtures.go b/openstack/objectstorage/v1/swauth/testing/fixtures_test.go similarity index 100% rename from openstack/objectstorage/v1/swauth/testing/fixtures.go rename to openstack/objectstorage/v1/swauth/testing/fixtures_test.go diff --git a/openstack/orchestration/v1/buildinfo/testing/fixtures.go b/openstack/orchestration/v1/buildinfo/testing/fixtures_test.go similarity index 100% rename from openstack/orchestration/v1/buildinfo/testing/fixtures.go rename to openstack/orchestration/v1/buildinfo/testing/fixtures_test.go diff --git a/openstack/orchestration/v1/resourcetypes/testing/fixtures.go b/openstack/orchestration/v1/resourcetypes/testing/fixtures_test.go similarity index 100% rename from openstack/orchestration/v1/resourcetypes/testing/fixtures.go rename to openstack/orchestration/v1/resourcetypes/testing/fixtures_test.go diff --git a/openstack/orchestration/v1/stackevents/testing/fixtures.go b/openstack/orchestration/v1/stackevents/testing/fixtures_test.go similarity index 100% rename from openstack/orchestration/v1/stackevents/testing/fixtures.go rename to openstack/orchestration/v1/stackevents/testing/fixtures_test.go diff --git a/openstack/orchestration/v1/stackresources/testing/fixtures.go b/openstack/orchestration/v1/stackresources/testing/fixtures_test.go similarity index 100% rename from openstack/orchestration/v1/stackresources/testing/fixtures.go rename to openstack/orchestration/v1/stackresources/testing/fixtures_test.go diff --git a/openstack/orchestration/v1/stacks/testing/fixtures.go b/openstack/orchestration/v1/stacks/testing/fixtures_test.go similarity index 100% rename from openstack/orchestration/v1/stacks/testing/fixtures.go rename to openstack/orchestration/v1/stacks/testing/fixtures_test.go diff --git a/openstack/orchestration/v1/stacktemplates/testing/fixtures.go b/openstack/orchestration/v1/stacktemplates/testing/fixtures_test.go similarity index 100% rename from openstack/orchestration/v1/stacktemplates/testing/fixtures.go rename to openstack/orchestration/v1/stacktemplates/testing/fixtures_test.go diff --git a/openstack/placement/v1/resourceproviders/testing/fixtures.go b/openstack/placement/v1/resourceproviders/testing/fixtures_test.go similarity index 100% rename from openstack/placement/v1/resourceproviders/testing/fixtures.go rename to openstack/placement/v1/resourceproviders/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/apiversions/testing/fixtures.go b/openstack/sharedfilesystems/apiversions/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/apiversions/testing/fixtures.go rename to openstack/sharedfilesystems/apiversions/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/availabilityzones/testing/fixtures.go b/openstack/sharedfilesystems/v2/availabilityzones/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/availabilityzones/testing/fixtures.go rename to openstack/sharedfilesystems/v2/availabilityzones/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/errors/testing/fixtures.go b/openstack/sharedfilesystems/v2/errors/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/errors/testing/fixtures.go rename to openstack/sharedfilesystems/v2/errors/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/messages/testing/fixtures.go b/openstack/sharedfilesystems/v2/messages/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/messages/testing/fixtures.go rename to openstack/sharedfilesystems/v2/messages/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/replicas/testing/fixtures.go b/openstack/sharedfilesystems/v2/replicas/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/replicas/testing/fixtures.go rename to openstack/sharedfilesystems/v2/replicas/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/schedulerstats/testing/fixtures.go b/openstack/sharedfilesystems/v2/schedulerstats/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/schedulerstats/testing/fixtures.go rename to openstack/sharedfilesystems/v2/schedulerstats/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/securityservices/testing/fixtures.go b/openstack/sharedfilesystems/v2/securityservices/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/securityservices/testing/fixtures.go rename to openstack/sharedfilesystems/v2/securityservices/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/services/testing/fixtures.go b/openstack/sharedfilesystems/v2/services/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/services/testing/fixtures.go rename to openstack/sharedfilesystems/v2/services/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/shareaccessrules/testing/fixtures.go b/openstack/sharedfilesystems/v2/shareaccessrules/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/shareaccessrules/testing/fixtures.go rename to openstack/sharedfilesystems/v2/shareaccessrules/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/sharenetworks/testing/fixtures.go b/openstack/sharedfilesystems/v2/sharenetworks/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/sharenetworks/testing/fixtures.go rename to openstack/sharedfilesystems/v2/sharenetworks/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/shares/testing/fixtures.go b/openstack/sharedfilesystems/v2/shares/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/shares/testing/fixtures.go rename to openstack/sharedfilesystems/v2/shares/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/sharetransfers/testing/fixtures.go b/openstack/sharedfilesystems/v2/sharetransfers/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/sharetransfers/testing/fixtures.go rename to openstack/sharedfilesystems/v2/sharetransfers/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/sharetypes/testing/fixtures.go b/openstack/sharedfilesystems/v2/sharetypes/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/sharetypes/testing/fixtures.go rename to openstack/sharedfilesystems/v2/sharetypes/testing/fixtures_test.go diff --git a/openstack/sharedfilesystems/v2/snapshots/testing/fixtures.go b/openstack/sharedfilesystems/v2/snapshots/testing/fixtures_test.go similarity index 100% rename from openstack/sharedfilesystems/v2/snapshots/testing/fixtures.go rename to openstack/sharedfilesystems/v2/snapshots/testing/fixtures_test.go From fc46027be8dd1e15fab6782d863017c74e8a9bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Fri, 20 Oct 2023 14:27:29 +0200 Subject: [PATCH 050/118] Test files alongside code Prior to this patch, all test files sitting alongside the code, outside of a `testing` directory were ignored by the CI scripts. --- script/coverage | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/script/coverage b/script/coverage index 3efa81ba5a..6b76a1be7b 100755 --- a/script/coverage +++ b/script/coverage @@ -5,8 +5,17 @@ set -e n=1 for testpkg in $(go list ./testing ./.../testing); do covpkg="${testpkg/"/testing"/}" - go test -covermode count -coverprofile "testing_"$n.coverprofile -coverpkg $covpkg $testpkg 2>/dev/null + go test -covermode count -coverprofile "testing_"$n.coverprofile -coverpkg "$covpkg" "$testpkg" 2>/dev/null n=$((n+1)) done + +base_pkg=$(go list) +# Look for additional test files +for path in $(find . -path '*/testing' -prune -o -path '*/internal' -prune -o -name '*_test.go' -exec dirname {} \; | uniq); do + pkg="${base_pkg}${path:1}" + go test -covermode count -coverprofile "testing_"$n.coverprofile -coverpkg "$pkg" "$pkg" 2>/dev/null + n=$((n+1)) +done + gocovmerge `ls *.coverprofile` > cover.out -rm *.coverprofile +rm ./*.coverprofile From 04f05f1f666d972082c077a0bb0772a8463b78a0 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Tue, 24 Oct 2023 11:31:43 -0400 Subject: [PATCH 051/118] Add more godoc to GuestFormat I recently found out that when not providing the GuestFormat to a block device mapping, the device will be formated to `vfat` anyway. https://opendev.org/openstack/nova/src/commit/d0b459423dd81644e8d9382b6c87fabaa4f03ad4/nova/privsep/fs.py#L257 I think it's valuable that we document that so the users know what to expect. --- openstack/compute/v2/extensions/bootfromvolume/requests.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openstack/compute/v2/extensions/bootfromvolume/requests.go b/openstack/compute/v2/extensions/bootfromvolume/requests.go index 17f11b3849..05f45aeceb 100644 --- a/openstack/compute/v2/extensions/bootfromvolume/requests.go +++ b/openstack/compute/v2/extensions/bootfromvolume/requests.go @@ -62,6 +62,9 @@ type BlockDevice struct { DestinationType DestinationType `json:"destination_type,omitempty"` // GuestFormat specifies the format of the block device. + // Not specifying this will cause the device to be formatted to the default in Nova + // which is currently vfat. + // https://opendev.org/openstack/nova/src/commit/d0b459423dd81644e8d9382b6c87fabaa4f03ad4/nova/privsep/fs.py#L257 GuestFormat string `json:"guest_format,omitempty"` // VolumeSize is the size of the volume to create (in gigabytes). This can be From 3df6ee567b4c5c1e645883afd042503d9ae424b1 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Thu, 26 Oct 2023 00:57:59 +0200 Subject: [PATCH 052/118] Allow objects.CreateTempURL with names containing '/v1/' Before this patch, if an object's name or container name contained the string `/v1/`, it was not possible to create a TempURL for it. This was due to a bug in how the URL was split between the base part, and the object-path part. With this patch, container names or object names containing `/v1/` can have a TempURL created successfully. --- .../acceptance/openstack/objectstorage/v1/objects_test.go | 4 +++- openstack/objectstorage/v1/objects/requests.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/acceptance/openstack/objectstorage/v1/objects_test.go b/internal/acceptance/openstack/objectstorage/v1/objects_test.go index e60fba9178..86db2c6575 100644 --- a/internal/acceptance/openstack/objectstorage/v1/objects_test.go +++ b/internal/acceptance/openstack/objectstorage/v1/objects_test.go @@ -22,6 +22,7 @@ import ( var numObjects = 2 func TestObjects(t *testing.T) { + numObjects := numObjects + 1 client, err := clients.NewObjectStorageV1Client() if err != nil { t.Fatalf("Unable to create client: %v", err) @@ -29,9 +30,10 @@ func TestObjects(t *testing.T) { // Make a slice of length numObjects to hold the random object names. oNames := make([]string, numObjects) - for i := 0; i < len(oNames); i++ { + for i := 0; i < len(oNames)-1; i++ { oNames[i] = tools.RandomString("test-object-", 8) } + oNames[len(oNames)-1] = "test-object-with-/v1/-in-the-name" // Create a container to hold the test objects. cName := tools.RandomString("test-container-", 8) diff --git a/openstack/objectstorage/v1/objects/requests.go b/openstack/objectstorage/v1/objects/requests.go index c03a27fce5..ed9bd180f9 100644 --- a/openstack/objectstorage/v1/objects/requests.go +++ b/openstack/objectstorage/v1/objects/requests.go @@ -612,7 +612,7 @@ func CreateTempURL(c *gophercloud.ServiceClient, containerName, objectName strin } secretKey := []byte(tempURLKey) - splitPath := strings.Split(url, opts.Split) + splitPath := strings.SplitN(url, opts.Split, 2) baseURL, objectPath := splitPath[0], splitPath[1] objectPath = opts.Split + objectPath body := fmt.Sprintf("%s\n%d\n%s", opts.Method, expiry, objectPath) From ccfa81e1fdd5b411b3586417f2d946a66577e53e Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Thu, 30 Nov 2023 10:26:02 +0100 Subject: [PATCH 053/118] unit tests: Fix the installation of tools Install Go tools with new newest Go version before switching to the target version of Go to run the unit tests. This commit fixes an issue where the Go tools we use in unit tests can't be compiled with Go v1.14 any more. --- .github/workflows/unit.yml | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index b438f33a4b..4a81289df4 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -20,22 +20,23 @@ jobs: GO111MODULE: "on" steps: - - name: Setup Go ${{ matrix.go-version }} + - uses: actions/checkout@v3 + + - name: Setup Go v1 uses: actions/setup-go@v4 with: - go-version: ${{ matrix.go-version }} - - - uses: actions/checkout@v3 + go-version: 1 - - name: Setup environment + - name: Install tools run: | - # Changing into a different directory to avoid polluting go.sum with "go get" - cd "$(mktemp -d)" - go mod init unit_tests + go install github.com/wadey/gocovmerge@master + go install golang.org/x/tools/cmd/goimports@latest - # we use "go get" for Go v1.14 - go install github.com/wadey/gocovmerge@master || go get github.com/wadey/gocovmerge - go install golang.org/x/tools/cmd/goimports@latest || go get golang.org/x/tools/cmd/goimports@v0.8.0 + - if: ${{ matrix.go-version != '1' }} + name: Setup Go ${{ matrix.go-version }} + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go-version }} - name: Run go vet run: | @@ -43,6 +44,7 @@ jobs: - name: Run unit tests run: | + go version ./script/coverage ./script/format ./script/unittest -v From 796aba14dc71b3c5e3a4486178789c8dcca8c7b2 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Thu, 30 Nov 2023 10:10:11 +0100 Subject: [PATCH 054/118] Prepare the v1.8.0 release --- CHANGELOG.md | 16 ++++++++++++++++ provider_client.go | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b470df398b..e13f9e17ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## v1.8.0 (2023-11-30) + +New features and improvements: + +* [GH-2800](https://github.com/gophercloud/gophercloud/pull/2800) [v1] Fix options initialization in ServiceClient.Request (fixes #2798) +* [GH-2823](https://github.com/gophercloud/gophercloud/pull/2823) [v1] Add more godoc to GuestFormat +* [GH-2826](https://github.com/gophercloud/gophercloud/pull/2826) Allow objects.CreateTempURL with names containing /v1/ + +CI changes: + +* [GH-2802](https://github.com/gophercloud/gophercloud/pull/2802) [v1] Add job for bobcat stable/2023.2 +* [GH-2819](https://github.com/gophercloud/gophercloud/pull/2819) [v1] Test files alongside code +* [GH-2814](https://github.com/gophercloud/gophercloud/pull/2814) Make fixtures part of tests +* [GH-2796](https://github.com/gophercloud/gophercloud/pull/2796) [v1] ci/unit: switch to coverallsapp/github-action +* [GH-2840](https://github.com/gophercloud/gophercloud/pull/2840) unit tests: Fix the installation of tools + ## v1.7.0 (2023-09-22) New features and improvements: diff --git a/provider_client.go b/provider_client.go index e53b713cd4..ce291a3ab3 100644 --- a/provider_client.go +++ b/provider_client.go @@ -14,7 +14,7 @@ import ( // DefaultUserAgent is the default User-Agent string set in the request header. const ( - DefaultUserAgent = "gophercloud/v1.7.0" + DefaultUserAgent = "gophercloud/v1.8.0" DefaultMaxBackoffRetries = 60 ) From 95a9036231ef715fe96cf3221e5fc75a90aba9c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Mon, 1 Jan 2024 14:38:16 +0100 Subject: [PATCH 055/118] Fix devstack install on EOL magnum branches The stable victoria, wallaby, and xena branches are no longer available upstream for magnum. We need to use their respective `-eol` tag to keep using them in our CI jobs. --- .../workflows/functional-containerinfra.yaml | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index 2c7b4a3480..52ba96883e 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -12,27 +12,51 @@ jobs: - name: "master" openstack_version: "master" ubuntu_version: "22.04" + devstack_conf_overrides: | + enable_plugin magnum https://github.com/openstack/magnum master + MAGNUMCLIENT_BRANCH=master - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" + devstack_conf_overrides: | + enable_plugin magnum https://github.com/openstack/magnum stable/2023.2 + MAGNUMCLIENT_BRANCH=stable/2023.2 - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" + devstack_conf_overrides: | + enable_plugin magnum https://github.com/openstack/magnum stable/2023.1 + MAGNUMCLIENT_BRANCH=stable/2023.1 - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" + devstack_conf_overrides: | + enable_plugin magnum https://github.com/openstack/magnum stable/zed + MAGNUMCLIENT_BRANCH=stable/zed - name: "yoga" openstack_version: "stable/yoga" ubuntu_version: "20.04" + devstack_conf_overrides: | + enable_plugin magnum https://github.com/openstack/magnum stable/yoga + MAGNUMCLIENT_BRANCH=stable/yoga - name: "xena" openstack_version: "stable/xena" ubuntu_version: "20.04" + devstack_conf_overrides: | + enable_plugin magnum https://github.com/openstack/magnum xena-eol + MAGNUMCLIENT_BRANCH=xena-eol - name: "wallaby" openstack_version: "stable/wallaby" ubuntu_version: "20.04" + devstack_conf_overrides: | + enable_plugin magnum https://github.com/openstack/magnum wallaby-eol + MAGNUMCLIENT_BRANCH=wallaby-eol - name: "victoria" openstack_version: "stable/victoria" ubuntu_version: "20.04" + devstack_conf_overrides: | + enable_plugin magnum https://github.com/openstack/magnum victoria-eol + MAGNUMCLIENT_BRANCH=victoria-em runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Magnum and run containerinfra acceptance tests steps: @@ -43,13 +67,12 @@ jobs: with: branch: ${{ matrix.openstack_version }} conf_overrides: | - enable_plugin magnum https://github.com/openstack/magnum ${{ matrix.openstack_version }} enable_plugin barbican https://github.com/openstack/barbican ${{ matrix.openstack_version }} enable_plugin heat https://github.com/openstack/heat ${{ matrix.openstack_version }} GLANCE_LIMIT_IMAGE_SIZE_TOTAL=5000 SWIFT_MAX_FILE_SIZE=5368709122 KEYSTONE_ADMIN_ENDPOINT=true - MAGNUMCLIENT_BRANCH=${{ matrix.openstack_version }} + ${{ matrix.devstack_conf_overrides }} enabled_services: 'h-eng,h-api,h-api-cfn,h-api-cw' - name: Checkout go uses: actions/setup-go@v4 From 3c68a0fa27cbb5666baa99566080363f64591d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Mon, 1 Jan 2024 14:07:01 +0100 Subject: [PATCH 056/118] Fix networking acceptance tests Since https://review.opendev.org/c/openstack/neutron/+/892815 it is no longer possible to update the vnic type of a bound port. These doesn't seem to be an API to unbind the port other than deleting the port, so instead we're dropping the `VNICType` attribute from the update request in the `TestPortsbindingCRUD` test. --- .../networking/v2/extensions/portsbinding/portsbinding_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go b/internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go index 50f5e8c99a..56f4d6530f 100644 --- a/internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go @@ -59,7 +59,6 @@ func TestPortsbindingCRUD(t *testing.T) { finalUpdateOpts = portsbinding.UpdateOptsExt{ UpdateOptsBuilder: updateOpts, HostID: &newHostID, - VNICType: "baremetal", Profile: newProfile, } @@ -76,6 +75,6 @@ func TestPortsbindingCRUD(t *testing.T) { th.AssertEquals(t, newPort.Description, newPortName) th.AssertEquals(t, newPort.Description, newPortDescription) th.AssertEquals(t, newPort.HostID, newHostID) - th.AssertEquals(t, newPort.VNICType, "baremetal") + th.AssertEquals(t, newPort.VNICType, "normal") th.AssertDeepEquals(t, newPort.Profile, newProfile) } From e707ba8798c92552ef494cb048a4aeada94a70c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Mon, 1 Jan 2024 14:48:11 +0100 Subject: [PATCH 057/118] TestPortsbindingCRUD: Fix order of arguments in equal assertions The correct order is `expected`, `actual`. Having this right helps debugging since the values are printed in a log message. --- .../extensions/portsbinding/portsbinding_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go b/internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go index 56f4d6530f..e4e851fe28 100644 --- a/internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go @@ -40,9 +40,9 @@ func TestPortsbindingCRUD(t *testing.T) { defer networking.DeletePort(t, client, port.ID) tools.PrintResource(t, port) - th.AssertEquals(t, port.HostID, hostID) - th.AssertEquals(t, port.VNICType, "normal") - th.AssertDeepEquals(t, port.Profile, profile) + th.AssertEquals(t, hostID, port.HostID) + th.AssertEquals(t, "normal", port.VNICType) + th.AssertDeepEquals(t, profile, port.Profile) // Update port newPortName := "" @@ -72,9 +72,9 @@ func TestPortsbindingCRUD(t *testing.T) { th.AssertNoErr(t, err) tools.PrintResource(t, newPort) - th.AssertEquals(t, newPort.Description, newPortName) - th.AssertEquals(t, newPort.Description, newPortDescription) - th.AssertEquals(t, newPort.HostID, newHostID) - th.AssertEquals(t, newPort.VNICType, "normal") - th.AssertDeepEquals(t, newPort.Profile, newProfile) + th.AssertEquals(t, newPortName, newPort.Description) + th.AssertEquals(t, newPortDescription, newPort.Description) + th.AssertEquals(t, newHostID, newPort.HostID) + th.AssertEquals(t, "normal", newPort.VNICType) + th.AssertDeepEquals(t, newProfile, newPort.Profile) } From 5e7274381f13980c6d90ddc35a2b6021cfcf7c9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 09:46:36 +0000 Subject: [PATCH 058/118] build(deps): bump actions/upload-artifact from 3 to 4 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/functional-baremetal.yaml | 2 +- .github/workflows/functional-basic.yaml | 2 +- .github/workflows/functional-blockstorage.yaml | 2 +- .github/workflows/functional-clustering.yaml | 2 +- .github/workflows/functional-compute.yaml | 2 +- .github/workflows/functional-containerinfra.yaml | 2 +- .github/workflows/functional-dns.yaml | 2 +- .github/workflows/functional-fwaas_v2.yaml | 2 +- .github/workflows/functional-identity.yaml | 2 +- .github/workflows/functional-imageservice.yaml | 2 +- .github/workflows/functional-keymanager.yaml | 2 +- .github/workflows/functional-loadbalancer.yaml | 2 +- .github/workflows/functional-messaging.yaml | 2 +- .github/workflows/functional-networking.yaml | 2 +- .github/workflows/functional-objectstorage.yaml | 2 +- .github/workflows/functional-orchestration.yaml | 2 +- .github/workflows/functional-placement.yaml | 2 +- .github/workflows/functional-sharedfilesystems.yaml | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index 6a8eb98fcf..f66da92a26 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -92,7 +92,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-baremetal-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index 879bd678ad..a679a0f27e 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -61,7 +61,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-basic-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index e34f2c3de8..b0b5f759ec 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -60,7 +60,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-blockstorage-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-clustering.yaml b/.github/workflows/functional-clustering.yaml index 6d86dc6880..c7d7a53c65 100644 --- a/.github/workflows/functional-clustering.yaml +++ b/.github/workflows/functional-clustering.yaml @@ -61,7 +61,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-clustering-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index cdc789793f..6cf62990ff 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -59,7 +59,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-compute-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index 52ba96883e..9ed76d8026 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -89,7 +89,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-containerinfra-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index 427832a95a..43177088c7 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -61,7 +61,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-dns-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml index 17dd723f29..020163ce27 100644 --- a/.github/workflows/functional-fwaas_v2.yaml +++ b/.github/workflows/functional-fwaas_v2.yaml @@ -53,7 +53,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-fwaas_v2-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml index 43e638381f..a62ddacf78 100644 --- a/.github/workflows/functional-identity.yaml +++ b/.github/workflows/functional-identity.yaml @@ -57,7 +57,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-identity-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-imageservice.yaml b/.github/workflows/functional-imageservice.yaml index a85e6621e2..9dec83dd54 100644 --- a/.github/workflows/functional-imageservice.yaml +++ b/.github/workflows/functional-imageservice.yaml @@ -57,7 +57,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-imageservice-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml index a1b5a4ed19..e0fb3db115 100644 --- a/.github/workflows/functional-keymanager.yaml +++ b/.github/workflows/functional-keymanager.yaml @@ -60,7 +60,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-keymanager-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml index fa2a3e9493..8dc42208cf 100644 --- a/.github/workflows/functional-loadbalancer.yaml +++ b/.github/workflows/functional-loadbalancer.yaml @@ -61,7 +61,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-loadbalancer-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml index 200ed18887..2355cfed85 100644 --- a/.github/workflows/functional-messaging.yaml +++ b/.github/workflows/functional-messaging.yaml @@ -60,7 +60,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-messaging-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index 4691455e9e..8539acc80c 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -62,7 +62,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-networking-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml index c5ac5bd4a1..60cd27e9f2 100644 --- a/.github/workflows/functional-objectstorage.yaml +++ b/.github/workflows/functional-objectstorage.yaml @@ -64,7 +64,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-objectstorage-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml index 0d035f6be0..73d461aac6 100644 --- a/.github/workflows/functional-orchestration.yaml +++ b/.github/workflows/functional-orchestration.yaml @@ -60,7 +60,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-orchestration-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml index 66d3849a98..016157562d 100644 --- a/.github/workflows/functional-placement.yaml +++ b/.github/workflows/functional-placement.yaml @@ -57,7 +57,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-placement-${{ matrix.name }} path: /tmp/devstack-logs/* diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml index eb42329634..6924d001fe 100644 --- a/.github/workflows/functional-sharedfilesystems.yaml +++ b/.github/workflows/functional-sharedfilesystems.yaml @@ -73,7 +73,7 @@ jobs: if: failure() - name: Upload logs artifacts on failure if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: functional-sharedfilesystems-${{ matrix.name }} path: /tmp/devstack-logs/* From f361ee3486ab447c06e13e803ab66ff0b62a4253 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Dec 2023 09:25:59 +0000 Subject: [PATCH 059/118] build(deps): bump github/codeql-action from 2 to 3 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v2...v3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 38cf2bfb08..f423c1f7f4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -21,12 +21,12 @@ jobs: uses: actions/checkout@v3 - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 From 9cfe594545858b86632eca695cd3302f24d43ca7 Mon Sep 17 00:00:00 2001 From: Eugene Zuev Date: Thu, 18 Jan 2024 19:24:11 +0000 Subject: [PATCH 060/118] feat: add AvailabilityZone for db/v1/instance fix: alignments fix: alignments added: AvailabilityZone for db/v1/instance --- openstack/db/v1/instances/requests.go | 6 ++++++ openstack/db/v1/instances/testing/fixtures_test.go | 1 + openstack/db/v1/instances/testing/requests_test.go | 10 ++++++---- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/openstack/db/v1/instances/requests.go b/openstack/db/v1/instances/requests.go index 73c7acc74e..26638157ca 100644 --- a/openstack/db/v1/instances/requests.go +++ b/openstack/db/v1/instances/requests.go @@ -47,6 +47,8 @@ func (opts NetworkOpts) ToMap() (map[string]interface{}, error) { // CreateOpts is the struct responsible for configuring a new database instance. type CreateOpts struct { + // The availability zone of the instance. + AvailabilityZone string `json:"availability_zone,omitempty"` // Either the integer UUID (in string form) of the flavor, or its URI // reference as specified in the response from the List() call. Required. FlavorRef string @@ -87,6 +89,10 @@ func (opts CreateOpts) ToInstanceCreateMap() (map[string]interface{}, error) { "flavorRef": opts.FlavorRef, } + if opts.AvailabilityZone != "" { + instance["availability_zone"] = opts.AvailabilityZone + } + if opts.Name != "" { instance["name"] = opts.Name } diff --git a/openstack/db/v1/instances/testing/fixtures_test.go b/openstack/db/v1/instances/testing/fixtures_test.go index 782c048dc3..7abd42e3e7 100644 --- a/openstack/db/v1/instances/testing/fixtures_test.go +++ b/openstack/db/v1/instances/testing/fixtures_test.go @@ -104,6 +104,7 @@ var instanceGet = ` var createReq = ` { "instance": { + "availability_zone": "us-east1", "databases": [ { "character_set": "utf8", diff --git a/openstack/db/v1/instances/testing/requests_test.go b/openstack/db/v1/instances/testing/requests_test.go index a1575a4bb1..62d615d7a9 100644 --- a/openstack/db/v1/instances/testing/requests_test.go +++ b/openstack/db/v1/instances/testing/requests_test.go @@ -17,8 +17,9 @@ func TestCreate(t *testing.T) { HandleCreate(t) opts := instances.CreateOpts{ - Name: "json_rack_instance", - FlavorRef: "1", + AvailabilityZone: "us-east1", + Name: "json_rack_instance", + FlavorRef: "1", Databases: db.BatchCreateOpts{ {CharSet: "utf8", Collate: "utf8_general_ci", Name: "sampledb"}, {Name: "nextround"}, @@ -48,8 +49,9 @@ func TestCreateWithFault(t *testing.T) { HandleCreateWithFault(t) opts := instances.CreateOpts{ - Name: "json_rack_instance", - FlavorRef: "1", + AvailabilityZone: "us-east1", + Name: "json_rack_instance", + FlavorRef: "1", Databases: db.BatchCreateOpts{ {CharSet: "utf8", Collate: "utf8_general_ci", Name: "sampledb"}, {Name: "nextround"}, From ef06ea2bef3b883355e3d109bbf4c48c4f40e8e0 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 31 Jan 2024 13:03:58 +0100 Subject: [PATCH 061/118] Context-aware methods to ProviderClient and ServiceClient Provide new methods to leverage per-call `context.Context`. This patch, suitable to be merged to `v1`, vendors the context package from the v1.21 standard library, to make `AfterFunc` available. --- internal/ctxt/context.go | 739 ++++++++++++++++++++++++++++++++++++ internal/ctxt/merge.go | 52 +++ internal/ctxt/merge_test.go | 133 +++++++ provider_client.go | 45 ++- service_client.go | 76 +++- 5 files changed, 1008 insertions(+), 37 deletions(-) create mode 100644 internal/ctxt/context.go create mode 100644 internal/ctxt/merge.go create mode 100644 internal/ctxt/merge_test.go diff --git a/internal/ctxt/context.go b/internal/ctxt/context.go new file mode 100644 index 0000000000..2352583714 --- /dev/null +++ b/internal/ctxt/context.go @@ -0,0 +1,739 @@ +package ctxt + +// This file is package context of the standard library that ships with Go +// v1.21.6. It has been vendored to import AfterFunc. +// +// Changes made to the original file: +// * replace "internal/reflectlite" with "reflect" in the imports +// * replace "any" with "interface{}" +// * remove the atomic.Int32 type that only exists for testing and is not +// compatible with Go v1.14. +// +// https://cs.opensource.google/go/go/+/refs/tags/go1.21.6:src/context/context.go + +import ( + "errors" + reflectlite "reflect" + "sync" + "sync/atomic" + "time" +) + +// A Context carries a deadline, a cancellation signal, and other values across +// API boundaries. +// +// Context's methods may be called by multiple goroutines simultaneously. +type Context interface { + // Deadline returns the time when work done on behalf of this context + // should be canceled. Deadline returns ok==false when no deadline is + // set. Successive calls to Deadline return the same results. + Deadline() (deadline time.Time, ok bool) + + // Done returns a channel that's closed when work done on behalf of this + // context should be canceled. Done may return nil if this context can + // never be canceled. Successive calls to Done return the same value. + // The close of the Done channel may happen asynchronously, + // after the cancel function returns. + // + // WithCancel arranges for Done to be closed when cancel is called; + // WithDeadline arranges for Done to be closed when the deadline + // expires; WithTimeout arranges for Done to be closed when the timeout + // elapses. + // + // Done is provided for use in select statements: + // + // // Stream generates values with DoSomething and sends them to out + // // until DoSomething returns an error or ctx.Done is closed. + // func Stream(ctx context.Context, out chan<- Value) error { + // for { + // v, err := DoSomething(ctx) + // if err != nil { + // return err + // } + // select { + // case <-ctx.Done(): + // return ctx.Err() + // case out <- v: + // } + // } + // } + // + // See https://blog.golang.org/pipelines for more examples of how to use + // a Done channel for cancellation. + Done() <-chan struct{} + + // If Done is not yet closed, Err returns nil. + // If Done is closed, Err returns a non-nil error explaining why: + // Canceled if the context was canceled + // or DeadlineExceeded if the context's deadline passed. + // After Err returns a non-nil error, successive calls to Err return the same error. + Err() error + + // Value returns the value associated with this context for key, or nil + // if no value is associated with key. Successive calls to Value with + // the same key returns the same result. + // + // Use context values only for request-scoped data that transits + // processes and API boundaries, not for passing optional parameters to + // functions. + // + // A key identifies a specific value in a Context. Functions that wish + // to store values in Context typically allocate a key in a global + // variable then use that key as the argument to context.WithValue and + // Context.Value. A key can be any type that supports equality; + // packages should define keys as an unexported type to avoid + // collisions. + // + // Packages that define a Context key should provide type-safe accessors + // for the values stored using that key: + // + // // Package user defines a User type that's stored in Contexts. + // package user + // + // import "context" + // + // // User is the type of value stored in the Contexts. + // type User struct {...} + // + // // key is an unexported type for keys defined in this package. + // // This prevents collisions with keys defined in other packages. + // type key int + // + // // userKey is the key for user.User values in Contexts. It is + // // unexported; clients use user.NewContext and user.FromContext + // // instead of using this key directly. + // var userKey key + // + // // NewContext returns a new Context that carries value u. + // func NewContext(ctx context.Context, u *User) context.Context { + // return context.WithValue(ctx, userKey, u) + // } + // + // // FromContext returns the User value stored in ctx, if any. + // func FromContext(ctx context.Context) (*User, bool) { + // u, ok := ctx.Value(userKey).(*User) + // return u, ok + // } + Value(key interface{}) interface{} +} + +// Canceled is the error returned by [Context.Err] when the context is canceled. +var Canceled = errors.New("context canceled") + +// DeadlineExceeded is the error returned by [Context.Err] when the context's +// deadline passes. +var DeadlineExceeded error = deadlineExceededError{} + +type deadlineExceededError struct{} + +func (deadlineExceededError) Error() string { return "context deadline exceeded" } +func (deadlineExceededError) Timeout() bool { return true } +func (deadlineExceededError) Temporary() bool { return true } + +// An emptyCtx is never canceled, has no values, and has no deadline. +// It is the common base of backgroundCtx and todoCtx. +type emptyCtx struct{} + +func (emptyCtx) Deadline() (deadline time.Time, ok bool) { + return +} + +func (emptyCtx) Done() <-chan struct{} { + return nil +} + +func (emptyCtx) Err() error { + return nil +} + +func (emptyCtx) Value(key interface{}) interface{} { + return nil +} + +type backgroundCtx struct{ emptyCtx } + +func (backgroundCtx) String() string { + return "context.Background" +} + +type todoCtx struct{ emptyCtx } + +func (todoCtx) String() string { + return "context.TODO" +} + +// Background returns a non-nil, empty [Context]. It is never canceled, has no +// values, and has no deadline. It is typically used by the main function, +// initialization, and tests, and as the top-level Context for incoming +// requests. +func Background() Context { + return backgroundCtx{} +} + +// TODO returns a non-nil, empty [Context]. Code should use context.TODO when +// it's unclear which Context to use or it is not yet available (because the +// surrounding function has not yet been extended to accept a Context +// parameter). +func TODO() Context { + return todoCtx{} +} + +// A CancelFunc tells an operation to abandon its work. +// A CancelFunc does not wait for the work to stop. +// A CancelFunc may be called by multiple goroutines simultaneously. +// After the first call, subsequent calls to a CancelFunc do nothing. +type CancelFunc func() + +// WithCancel returns a copy of parent with a new Done channel. The returned +// context's Done channel is closed when the returned cancel function is called +// or when the parent context's Done channel is closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { + c := withCancel(parent) + return c, func() { c.cancel(true, Canceled, nil) } +} + +// A CancelCauseFunc behaves like a [CancelFunc] but additionally sets the cancellation cause. +// This cause can be retrieved by calling [Cause] on the canceled Context or on +// any of its derived Contexts. +// +// If the context has already been canceled, CancelCauseFunc does not set the cause. +// For example, if childContext is derived from parentContext: +// - if parentContext is canceled with cause1 before childContext is canceled with cause2, +// then Cause(parentContext) == Cause(childContext) == cause1 +// - if childContext is canceled with cause2 before parentContext is canceled with cause1, +// then Cause(parentContext) == cause1 and Cause(childContext) == cause2 +type CancelCauseFunc func(cause error) + +// WithCancelCause behaves like [WithCancel] but returns a [CancelCauseFunc] instead of a [CancelFunc]. +// Calling cancel with a non-nil error (the "cause") records that error in ctx; +// it can then be retrieved using Cause(ctx). +// Calling cancel with nil sets the cause to Canceled. +// +// Example use: +// +// ctx, cancel := context.WithCancelCause(parent) +// cancel(myError) +// ctx.Err() // returns context.Canceled +// context.Cause(ctx) // returns myError +func WithCancelCause(parent Context) (ctx Context, cancel CancelCauseFunc) { + c := withCancel(parent) + return c, func(cause error) { c.cancel(true, Canceled, cause) } +} + +func withCancel(parent Context) *cancelCtx { + if parent == nil { + panic("cannot create context from nil parent") + } + c := &cancelCtx{} + c.propagateCancel(parent, c) + return c +} + +// Cause returns a non-nil error explaining why c was canceled. +// The first cancellation of c or one of its parents sets the cause. +// If that cancellation happened via a call to CancelCauseFunc(err), +// then [Cause] returns err. +// Otherwise Cause(c) returns the same value as c.Err(). +// Cause returns nil if c has not been canceled yet. +func Cause(c Context) error { + if cc, ok := c.Value(&cancelCtxKey).(*cancelCtx); ok { + cc.mu.Lock() + defer cc.mu.Unlock() + return cc.cause + } + return nil +} + +// AfterFunc arranges to call f in its own goroutine after ctx is done +// (cancelled or timed out). +// If ctx is already done, AfterFunc calls f immediately in its own goroutine. +// +// Multiple calls to AfterFunc on a context operate independently; +// one does not replace another. +// +// Calling the returned stop function stops the association of ctx with f. +// It returns true if the call stopped f from being run. +// If stop returns false, +// either the context is done and f has been started in its own goroutine; +// or f was already stopped. +// The stop function does not wait for f to complete before returning. +// If the caller needs to know whether f is completed, +// it must coordinate with f explicitly. +// +// If ctx has a "AfterFunc(func()) func() bool" method, +// AfterFunc will use it to schedule the call. +func AfterFunc(ctx Context, f func()) (stop func() bool) { + a := &afterFuncCtx{ + f: f, + } + a.cancelCtx.propagateCancel(ctx, a) + return func() bool { + stopped := false + a.once.Do(func() { + stopped = true + }) + if stopped { + a.cancel(true, Canceled, nil) + } + return stopped + } +} + +type afterFuncer interface { + AfterFunc(func()) func() bool +} + +type afterFuncCtx struct { + cancelCtx + once sync.Once // either starts running f or stops f from running + f func() +} + +func (a *afterFuncCtx) cancel(removeFromParent bool, err, cause error) { + a.cancelCtx.cancel(false, err, cause) + if removeFromParent { + removeChild(a.Context, a) + } + a.once.Do(func() { + go a.f() + }) +} + +// A stopCtx is used as the parent context of a cancelCtx when +// an AfterFunc has been registered with the parent. +// It holds the stop function used to unregister the AfterFunc. +type stopCtx struct { + Context + stop func() bool +} + +// &cancelCtxKey is the key that a cancelCtx returns itself for. +var cancelCtxKey int + +// parentCancelCtx returns the underlying *cancelCtx for parent. +// It does this by looking up parent.Value(&cancelCtxKey) to find +// the innermost enclosing *cancelCtx and then checking whether +// parent.Done() matches that *cancelCtx. (If not, the *cancelCtx +// has been wrapped in a custom implementation providing a +// different done channel, in which case we should not bypass it.) +func parentCancelCtx(parent Context) (*cancelCtx, bool) { + done := parent.Done() + if done == closedchan || done == nil { + return nil, false + } + p, ok := parent.Value(&cancelCtxKey).(*cancelCtx) + if !ok { + return nil, false + } + pdone, _ := p.done.Load().(chan struct{}) + if pdone != done { + return nil, false + } + return p, true +} + +// removeChild removes a context from its parent. +func removeChild(parent Context, child canceler) { + if s, ok := parent.(stopCtx); ok { + s.stop() + return + } + p, ok := parentCancelCtx(parent) + if !ok { + return + } + p.mu.Lock() + if p.children != nil { + delete(p.children, child) + } + p.mu.Unlock() +} + +// A canceler is a context type that can be canceled directly. The +// implementations are *cancelCtx and *timerCtx. +type canceler interface { + cancel(removeFromParent bool, err, cause error) + Done() <-chan struct{} +} + +// closedchan is a reusable closed channel. +var closedchan = make(chan struct{}) + +func init() { + close(closedchan) +} + +// A cancelCtx can be canceled. When canceled, it also cancels any children +// that implement canceler. +type cancelCtx struct { + Context + + mu sync.Mutex // protects following fields + done atomic.Value // of chan struct{}, created lazily, closed by first cancel call + children map[canceler]struct{} // set to nil by the first cancel call + err error // set to non-nil by the first cancel call + cause error // set to non-nil by the first cancel call +} + +func (c *cancelCtx) Value(key interface{}) interface{} { + if key == &cancelCtxKey { + return c + } + return value(c.Context, key) +} + +func (c *cancelCtx) Done() <-chan struct{} { + d := c.done.Load() + if d != nil { + return d.(chan struct{}) + } + c.mu.Lock() + defer c.mu.Unlock() + d = c.done.Load() + if d == nil { + d = make(chan struct{}) + c.done.Store(d) + } + return d.(chan struct{}) +} + +func (c *cancelCtx) Err() error { + c.mu.Lock() + err := c.err + c.mu.Unlock() + return err +} + +// propagateCancel arranges for child to be canceled when parent is. +// It sets the parent context of cancelCtx. +func (c *cancelCtx) propagateCancel(parent Context, child canceler) { + c.Context = parent + + done := parent.Done() + if done == nil { + return // parent is never canceled + } + + select { + case <-done: + // parent is already canceled + child.cancel(false, parent.Err(), Cause(parent)) + return + default: + } + + if p, ok := parentCancelCtx(parent); ok { + // parent is a *cancelCtx, or derives from one. + p.mu.Lock() + if p.err != nil { + // parent has already been canceled + child.cancel(false, p.err, p.cause) + } else { + if p.children == nil { + p.children = make(map[canceler]struct{}) + } + p.children[child] = struct{}{} + } + p.mu.Unlock() + return + } + + if a, ok := parent.(afterFuncer); ok { + // parent implements an AfterFunc method. + c.mu.Lock() + stop := a.AfterFunc(func() { + child.cancel(false, parent.Err(), Cause(parent)) + }) + c.Context = stopCtx{ + Context: parent, + stop: stop, + } + c.mu.Unlock() + return + } + + go func() { + select { + case <-parent.Done(): + child.cancel(false, parent.Err(), Cause(parent)) + case <-child.Done(): + } + }() +} + +type stringer interface { + String() string +} + +func contextName(c Context) string { + if s, ok := c.(stringer); ok { + return s.String() + } + return reflectlite.TypeOf(c).String() +} + +func (c *cancelCtx) String() string { + return contextName(c.Context) + ".WithCancel" +} + +// cancel closes c.done, cancels each of c's children, and, if +// removeFromParent is true, removes c from its parent's children. +// cancel sets c.cause to cause if this is the first time c is canceled. +func (c *cancelCtx) cancel(removeFromParent bool, err, cause error) { + if err == nil { + panic("context: internal error: missing cancel error") + } + if cause == nil { + cause = err + } + c.mu.Lock() + if c.err != nil { + c.mu.Unlock() + return // already canceled + } + c.err = err + c.cause = cause + d, _ := c.done.Load().(chan struct{}) + if d == nil { + c.done.Store(closedchan) + } else { + close(d) + } + for child := range c.children { + // NOTE: acquiring the child's lock while holding parent's lock. + child.cancel(false, err, cause) + } + c.children = nil + c.mu.Unlock() + + if removeFromParent { + removeChild(c.Context, c) + } +} + +// WithoutCancel returns a copy of parent that is not canceled when parent is canceled. +// The returned context returns no Deadline or Err, and its Done channel is nil. +// Calling [Cause] on the returned context returns nil. +func WithoutCancel(parent Context) Context { + if parent == nil { + panic("cannot create context from nil parent") + } + return withoutCancelCtx{parent} +} + +type withoutCancelCtx struct { + c Context +} + +func (withoutCancelCtx) Deadline() (deadline time.Time, ok bool) { + return +} + +func (withoutCancelCtx) Done() <-chan struct{} { + return nil +} + +func (withoutCancelCtx) Err() error { + return nil +} + +func (c withoutCancelCtx) Value(key interface{}) interface{} { + return value(c, key) +} + +func (c withoutCancelCtx) String() string { + return contextName(c.c) + ".WithoutCancel" +} + +// WithDeadline returns a copy of the parent context with the deadline adjusted +// to be no later than d. If the parent's deadline is already earlier than d, +// WithDeadline(parent, d) is semantically equivalent to parent. The returned +// [Context.Done] channel is closed when the deadline expires, when the returned +// cancel function is called, or when the parent context's Done channel is +// closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this [Context] complete. +func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) { + return WithDeadlineCause(parent, d, nil) +} + +// WithDeadlineCause behaves like [WithDeadline] but also sets the cause of the +// returned Context when the deadline is exceeded. The returned [CancelFunc] does +// not set the cause. +func WithDeadlineCause(parent Context, d time.Time, cause error) (Context, CancelFunc) { + if parent == nil { + panic("cannot create context from nil parent") + } + if cur, ok := parent.Deadline(); ok && cur.Before(d) { + // The current deadline is already sooner than the new one. + return WithCancel(parent) + } + c := &timerCtx{ + deadline: d, + } + c.cancelCtx.propagateCancel(parent, c) + dur := time.Until(d) + if dur <= 0 { + c.cancel(true, DeadlineExceeded, cause) // deadline has already passed + return c, func() { c.cancel(false, Canceled, nil) } + } + c.mu.Lock() + defer c.mu.Unlock() + if c.err == nil { + c.timer = time.AfterFunc(dur, func() { + c.cancel(true, DeadlineExceeded, cause) + }) + } + return c, func() { c.cancel(true, Canceled, nil) } +} + +// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to +// implement Done and Err. It implements cancel by stopping its timer then +// delegating to cancelCtx.cancel. +type timerCtx struct { + cancelCtx + timer *time.Timer // Under cancelCtx.mu. + + deadline time.Time +} + +func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { + return c.deadline, true +} + +func (c *timerCtx) String() string { + return contextName(c.cancelCtx.Context) + ".WithDeadline(" + + c.deadline.String() + " [" + + time.Until(c.deadline).String() + "])" +} + +func (c *timerCtx) cancel(removeFromParent bool, err, cause error) { + c.cancelCtx.cancel(false, err, cause) + if removeFromParent { + // Remove this timerCtx from its parent cancelCtx's children. + removeChild(c.cancelCtx.Context, c) + } + c.mu.Lock() + if c.timer != nil { + c.timer.Stop() + c.timer = nil + } + c.mu.Unlock() +} + +// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this [Context] complete: +// +// func slowOperationWithTimeout(ctx context.Context) (Result, error) { +// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) +// defer cancel() // releases resources if slowOperation completes before timeout elapses +// return slowOperation(ctx) +// } +func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { + return WithDeadline(parent, time.Now().Add(timeout)) +} + +// WithTimeoutCause behaves like [WithTimeout] but also sets the cause of the +// returned Context when the timeout expires. The returned [CancelFunc] does +// not set the cause. +func WithTimeoutCause(parent Context, timeout time.Duration, cause error) (Context, CancelFunc) { + return WithDeadlineCause(parent, time.Now().Add(timeout), cause) +} + +// WithValue returns a copy of parent in which the value associated with key is +// val. +// +// Use context Values only for request-scoped data that transits processes and +// APIs, not for passing optional parameters to functions. +// +// The provided key must be comparable and should not be of type +// string or any other built-in type to avoid collisions between +// packages using context. Users of WithValue should define their own +// types for keys. To avoid allocating when assigning to an +// interface{}, context keys often have concrete type +// struct{}. Alternatively, exported context key variables' static +// type should be a pointer or interface. +func WithValue(parent Context, key, val interface{}) Context { + if parent == nil { + panic("cannot create context from nil parent") + } + if key == nil { + panic("nil key") + } + if !reflectlite.TypeOf(key).Comparable() { + panic("key is not comparable") + } + return &valueCtx{parent, key, val} +} + +// A valueCtx carries a key-value pair. It implements Value for that key and +// delegates all other calls to the embedded Context. +type valueCtx struct { + Context + key, val interface{} +} + +// stringify tries a bit to stringify v, without using fmt, since we don't +// want context depending on the unicode tables. This is only used by +// *valueCtx.String(). +func stringify(v interface{}) string { + switch s := v.(type) { + case stringer: + return s.String() + case string: + return s + } + return "" +} + +func (c *valueCtx) String() string { + return contextName(c.Context) + ".WithValue(type " + + reflectlite.TypeOf(c.key).String() + + ", val " + stringify(c.val) + ")" +} + +func (c *valueCtx) Value(key interface{}) interface{} { + if c.key == key { + return c.val + } + return value(c.Context, key) +} + +func value(c Context, key interface{}) interface{} { + for { + switch ctx := c.(type) { + case *valueCtx: + if key == ctx.key { + return ctx.val + } + c = ctx.Context + case *cancelCtx: + if key == &cancelCtxKey { + return c + } + c = ctx.Context + case withoutCancelCtx: + if key == &cancelCtxKey { + // This implements Cause(ctx) == nil + // when ctx is created using WithoutCancel. + return nil + } + c = ctx.c + case *timerCtx: + if key == &cancelCtxKey { + return &ctx.cancelCtx + } + c = ctx.Context + case backgroundCtx, todoCtx: + return nil + default: + return c.Value(key) + } + } +} diff --git a/internal/ctxt/merge.go b/internal/ctxt/merge.go new file mode 100644 index 0000000000..7604c78e6e --- /dev/null +++ b/internal/ctxt/merge.go @@ -0,0 +1,52 @@ +// package ctxt implements context merging. +package ctxt + +import ( + "context" + "time" +) + +type mergeContext struct { + context.Context + ctx2 context.Context +} + +// Merge returns a context that is cancelled when at least one of the parents +// is cancelled. The returned context also returns the values of ctx1, or ctx2 +// if nil. +func Merge(ctx1, ctx2 context.Context) (context.Context, context.CancelFunc) { + ctx, cancel := WithCancelCause(ctx1) + stop := AfterFunc(ctx2, func() { + cancel(Cause(ctx2)) + }) + + return &mergeContext{ + Context: ctx, + ctx2: ctx2, + }, func() { + stop() + cancel(context.Canceled) + } +} + +// Value returns ctx2's value if ctx's is nil. +func (ctx *mergeContext) Value(key interface{}) interface{} { + if v := ctx.Context.Value(key); v != nil { + return v + } + return ctx.ctx2.Value(key) +} + +// Deadline returns the earlier deadline of the two parents of ctx. +func (ctx *mergeContext) Deadline() (time.Time, bool) { + if d1, ok := ctx.Context.Deadline(); ok { + if d2, ok := ctx.ctx2.Deadline(); ok { + if d1.Before(d2) { + return d1, true + } + return d2, true + } + return d1, ok + } + return ctx.ctx2.Deadline() +} diff --git a/internal/ctxt/merge_test.go b/internal/ctxt/merge_test.go new file mode 100644 index 0000000000..c111ae7a09 --- /dev/null +++ b/internal/ctxt/merge_test.go @@ -0,0 +1,133 @@ +package ctxt_test + +import ( + "context" + "testing" + "time" + + "github.com/gophercloud/gophercloud/internal/ctxt" +) + +func TestMerge(t *testing.T) { + t.Run("returns values from both parents", func(t *testing.T) { + ctx1 := context.WithValue(context.Background(), + "key1", "value1") + + ctx2 := context.WithValue(context.WithValue(context.Background(), + "key1", "this value should be overridden"), + "key2", "value2") + + ctx, cancel := ctxt.Merge(ctx1, ctx2) + defer cancel() + + if v1 := ctx.Value("key1"); v1 != nil { + if s1, ok := v1.(string); ok { + if s1 != "value1" { + t.Errorf("found value for key1 %q, expected %q", s1, "value1") + } + } else { + t.Errorf("key1 is not the expected type string") + } + } else { + t.Errorf("key1 returned nil") + } + + if v2 := ctx.Value("key2"); v2 != nil { + if s2, ok := v2.(string); ok { + if s2 != "value2" { + t.Errorf("found value for key2 %q, expected %q", s2, "value2") + } + } else { + t.Errorf("key2 is not the expected type string") + } + } else { + t.Errorf("key2 returned nil") + } + }) + + t.Run("first parent cancels", func(t *testing.T) { + ctx1, cancel1 := context.WithCancel(context.Background()) + ctx2, cancel2 := context.WithCancel(context.Background()) + defer cancel2() + + ctx, cancel := ctxt.Merge(ctx1, ctx2) + defer cancel() + + if err := ctx.Err(); err != nil { + t.Errorf("context unexpectedly done: %v", err) + } + + cancel1() + time.Sleep(1 * time.Millisecond) + if err := ctx.Err(); err == nil { + t.Errorf("context not done despite parent1 cancelled") + } + }) + + t.Run("second parent cancels", func(t *testing.T) { + ctx1, cancel1 := context.WithCancel(context.Background()) + ctx2, cancel2 := context.WithCancel(context.Background()) + defer cancel1() + + ctx, cancel := ctxt.Merge(ctx1, ctx2) + defer cancel() + + if err := ctx.Err(); err != nil { + t.Errorf("context unexpectedly done: %v", err) + } + + cancel2() + time.Sleep(1 * time.Millisecond) + if err := ctx.Err(); err == nil { + t.Errorf("context not done despite parent2 cancelled") + } + }) + + t.Run("inherits deadline from first parent", func(t *testing.T) { + now := time.Now() + t1 := now.Add(time.Hour) + t2 := t1.Add(time.Second) + + ctx1, cancel1 := context.WithDeadline(context.Background(), t1) + ctx2, cancel2 := context.WithDeadline(context.Background(), t2) + defer cancel1() + defer cancel2() + + ctx, cancel := ctxt.Merge(ctx1, ctx2) + defer cancel() + + if err := ctx.Err(); err != nil { + t.Errorf("context unexpectedly done: %v", err) + } + + if deadline, ok := ctx.Deadline(); ok { + if deadline != t1 { + t.Errorf("expected deadline to be %v, found %v", t1, deadline) + } + } + }) + + t.Run("inherits deadline from second parent", func(t *testing.T) { + now := time.Now() + t2 := now.Add(time.Hour) + t1 := t2.Add(time.Second) + + ctx1, cancel1 := context.WithDeadline(context.Background(), t1) + ctx2, cancel2 := context.WithDeadline(context.Background(), t2) + defer cancel1() + defer cancel2() + + ctx, cancel := ctxt.Merge(ctx1, ctx2) + defer cancel() + + if err := ctx.Err(); err != nil { + t.Errorf("context unexpectedly done: %v", err) + } + + if deadline, ok := ctx.Deadline(); ok { + if deadline != t2 { + t.Errorf("expected deadline to be %v, found %v", t2, deadline) + } + } + }) +} diff --git a/provider_client.go b/provider_client.go index ce291a3ab3..bf43099e0b 100644 --- a/provider_client.go +++ b/provider_client.go @@ -10,6 +10,8 @@ import ( "net/http" "strings" "sync" + + "github.com/gophercloud/gophercloud/internal/ctxt" ) // DefaultUserAgent is the default User-Agent string set in the request header. @@ -88,7 +90,9 @@ type ProviderClient struct { // with the token and reauth func zeroed. Such client can be used to perform reauthorization. Throwaway bool - // Context is the context passed to the HTTP request. + // Context is the context passed to the HTTP request. Values set on the + // per-call context, when available, override values set on this + // context. Context context.Context // Retry backoff func is called when rate limited. @@ -352,15 +356,20 @@ type requestState struct { var applicationJSON = "application/json" -// Request performs an HTTP request using the ProviderClient's current HTTPClient. An authentication -// header will automatically be provided. -func (client *ProviderClient) Request(method, url string, options *RequestOpts) (*http.Response, error) { - return client.doRequest(method, url, options, &requestState{ +// RequestWithContext performs an HTTP request using the ProviderClient's +// current HTTPClient. An authentication header will automatically be provided. +func (client *ProviderClient) RequestWithContext(ctx context.Context, method, url string, options *RequestOpts) (*http.Response, error) { + return client.doRequest(ctx, method, url, options, &requestState{ hasReauthenticated: false, }) } -func (client *ProviderClient) doRequest(method, url string, options *RequestOpts, state *requestState) (*http.Response, error) { +// Request is a compatibility wrapper for Request. +func (client *ProviderClient) Request(method, url string, options *RequestOpts) (*http.Response, error) { + return client.RequestWithContext(context.Background(), method, url, options) +} + +func (client *ProviderClient) doRequest(ctx context.Context, method, url string, options *RequestOpts, state *requestState) (*http.Response, error) { var body io.Reader var contentType *string @@ -389,14 +398,16 @@ func (client *ProviderClient) doRequest(method, url string, options *RequestOpts body = options.RawBody } - // Construct the http.Request. - req, err := http.NewRequest(method, url, body) + if client.Context != nil { + var cancel context.CancelFunc + ctx, cancel = ctxt.Merge(ctx, client.Context) + defer cancel() + } + + req, err := http.NewRequestWithContext(ctx, method, url, body) if err != nil { return nil, err } - if client.Context != nil { - req = req.WithContext(client.Context) - } // Populate the request headers. // Apply options.MoreHeaders and options.OmitHeaders, to give the caller the chance to @@ -432,12 +443,12 @@ func (client *ProviderClient) doRequest(method, url string, options *RequestOpts if client.RetryFunc != nil { var e error state.retries = state.retries + 1 - e = client.RetryFunc(client.Context, method, url, options, err, state.retries) + e = client.RetryFunc(ctx, method, url, options, err, state.retries) if e != nil { return nil, e } - return client.doRequest(method, url, options, state) + return client.doRequest(ctx, method, url, options, state) } return nil, err } @@ -491,7 +502,7 @@ func (client *ProviderClient) doRequest(method, url string, options *RequestOpts } } state.hasReauthenticated = true - resp, err = client.doRequest(method, url, options, state) + resp, err = client.doRequest(ctx, method, url, options, state) if err != nil { switch err.(type) { case *ErrUnexpectedResponseCode: @@ -556,7 +567,7 @@ func (client *ProviderClient) doRequest(method, url string, options *RequestOpts return resp, e } - return client.doRequest(method, url, options, state) + return client.doRequest(ctx, method, url, options, state) } case http.StatusInternalServerError: err = ErrDefault500{respErr} @@ -592,7 +603,7 @@ func (client *ProviderClient) doRequest(method, url string, options *RequestOpts return resp, e } - return client.doRequest(method, url, options, state) + return client.doRequest(ctx, method, url, options, state) } return resp, err @@ -616,7 +627,7 @@ func (client *ProviderClient) doRequest(method, url string, options *RequestOpts return resp, e } - return client.doRequest(method, url, options, state) + return client.doRequest(ctx, method, url, options, state) } return nil, err } diff --git a/service_client.go b/service_client.go index 94a161e340..b8e6fd1a38 100644 --- a/service_client.go +++ b/service_client.go @@ -1,6 +1,7 @@ package gophercloud import ( + "context" "io" "net/http" "strings" @@ -59,58 +60,88 @@ func (client *ServiceClient) initReqOpts(JSONBody interface{}, JSONResponse inte } } -// Get calls `Request` with the "GET" HTTP verb. -func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { +// GetWithContext calls `Request` with the "GET" HTTP verb. +func (client *ServiceClient) GetWithContext(ctx context.Context, url string, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = new(RequestOpts) } client.initReqOpts(nil, JSONResponse, opts) - return client.Request("GET", url, opts) + return client.RequestWithContext(ctx, "GET", url, opts) } -// Post calls `Request` with the "POST" HTTP verb. -func (client *ServiceClient) Post(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { +// Get is a compatibility wrapper for GetWithContext. +func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { + return client.GetWithContext(context.Background(), url, JSONResponse, opts) +} + +// PostWithContext calls `Request` with the "POST" HTTP verb. +func (client *ServiceClient) PostWithContext(ctx context.Context, url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = new(RequestOpts) } client.initReqOpts(JSONBody, JSONResponse, opts) - return client.Request("POST", url, opts) + return client.RequestWithContext(ctx, "POST", url, opts) } -// Put calls `Request` with the "PUT" HTTP verb. -func (client *ServiceClient) Put(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { +// Post is a compatibility wrapper for PostWithContext. +func (client *ServiceClient) Post(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { + return client.PostWithContext(context.Background(), url, JSONBody, JSONResponse, opts) +} + +// PutWithContext calls `Request` with the "PUT" HTTP verb. +func (client *ServiceClient) PutWithContext(ctx context.Context, url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = new(RequestOpts) } client.initReqOpts(JSONBody, JSONResponse, opts) - return client.Request("PUT", url, opts) + return client.RequestWithContext(ctx, "PUT", url, opts) } -// Patch calls `Request` with the "PATCH" HTTP verb. -func (client *ServiceClient) Patch(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { +// Put is a compatibility wrapper for PurWithContext. +func (client *ServiceClient) Put(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { + return client.PutWithContext(context.Background(), url, JSONBody, JSONResponse, opts) +} + +// PatchWithContext calls `Request` with the "PATCH" HTTP verb. +func (client *ServiceClient) PatchWithContext(ctx context.Context, url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = new(RequestOpts) } client.initReqOpts(JSONBody, JSONResponse, opts) - return client.Request("PATCH", url, opts) + return client.RequestWithContext(ctx, "PATCH", url, opts) } -// Delete calls `Request` with the "DELETE" HTTP verb. -func (client *ServiceClient) Delete(url string, opts *RequestOpts) (*http.Response, error) { +// Patch is a compatibility wrapper for PatchWithContext. +func (client *ServiceClient) Patch(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { + return client.PatchWithContext(context.Background(), url, JSONBody, JSONResponse, opts) +} + +// DeleteWithContext calls `Request` with the "DELETE" HTTP verb. +func (client *ServiceClient) DeleteWithContext(ctx context.Context, url string, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = new(RequestOpts) } client.initReqOpts(nil, nil, opts) - return client.Request("DELETE", url, opts) + return client.RequestWithContext(ctx, "DELETE", url, opts) } -// Head calls `Request` with the "HEAD" HTTP verb. -func (client *ServiceClient) Head(url string, opts *RequestOpts) (*http.Response, error) { +// Delete is a compatibility wrapper for DeleteWithContext. +func (client *ServiceClient) Delete(url string, opts *RequestOpts) (*http.Response, error) { + return client.DeleteWithContext(context.Background(), url, opts) +} + +// HeadWithContext calls `Request` with the "HEAD" HTTP verb. +func (client *ServiceClient) HeadWithContext(ctx context.Context, url string, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = new(RequestOpts) } client.initReqOpts(nil, nil, opts) - return client.Request("HEAD", url, opts) + return client.RequestWithContext(ctx, "HEAD", url, opts) +} + +// Head is a compatibility wrapper for HeadWithContext. +func (client *ServiceClient) Head(url string, opts *RequestOpts) (*http.Response, error) { + return client.HeadWithContext(context.Background(), url, opts) } func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) { @@ -133,7 +164,7 @@ func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) { } // Request carries out the HTTP operation for the service client -func (client *ServiceClient) Request(method, url string, options *RequestOpts) (*http.Response, error) { +func (client *ServiceClient) RequestWithContext(ctx context.Context, method, url string, options *RequestOpts) (*http.Response, error) { if options.MoreHeaders == nil { options.MoreHeaders = make(map[string]string) } @@ -151,7 +182,12 @@ func (client *ServiceClient) Request(method, url string, options *RequestOpts) ( options.MoreHeaders[k] = v } } - return client.ProviderClient.Request(method, url, options) + return client.ProviderClient.RequestWithContext(ctx, method, url, options) +} + +// Request is a compatibility wrapper for RequestWithContext. +func (client *ServiceClient) Request(method, url string, options *RequestOpts) (*http.Response, error) { + return client.RequestWithContext(context.Background(), method, url, options) } // ParseResponse is a helper function to parse http.Response to constituents. From 84073f4050bcb12a55c397de0ffe7b8d405abdd5 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Jourel Date: Tue, 28 Feb 2023 02:40:23 -0500 Subject: [PATCH 062/118] Add support of Flavor for Octavia --- openstack/loadbalancer/v2/flavors/doc.go | 58 ++++++ openstack/loadbalancer/v2/flavors/requests.go | 112 ++++++++++++ openstack/loadbalancer/v2/flavors/results.go | 79 +++++++++ .../loadbalancer/v2/flavors/testing/doc.go | 1 + .../v2/flavors/testing/fixutres.go | 166 ++++++++++++++++++ .../v2/flavors/testing/requests_test.go | 118 +++++++++++++ openstack/loadbalancer/v2/flavors/urls.go | 16 ++ 7 files changed, 550 insertions(+) create mode 100644 openstack/loadbalancer/v2/flavors/doc.go create mode 100644 openstack/loadbalancer/v2/flavors/requests.go create mode 100644 openstack/loadbalancer/v2/flavors/results.go create mode 100644 openstack/loadbalancer/v2/flavors/testing/doc.go create mode 100644 openstack/loadbalancer/v2/flavors/testing/fixutres.go create mode 100644 openstack/loadbalancer/v2/flavors/testing/requests_test.go create mode 100644 openstack/loadbalancer/v2/flavors/urls.go diff --git a/openstack/loadbalancer/v2/flavors/doc.go b/openstack/loadbalancer/v2/flavors/doc.go new file mode 100644 index 0000000000..cbdd127f55 --- /dev/null +++ b/openstack/loadbalancer/v2/flavors/doc.go @@ -0,0 +1,58 @@ +/* +Package flavors provides information and interaction with Flavors +for the OpenStack Load-balancing service. + +Example to List Flavors + + listOpts := flavors.ListOpts{} + + allPages, err := flavors.List(octaviaClient, listOpts).AllPages() + if err != nil { + panic(err) + } + + allFlavors, err := flavors.ExtractFlavors(allPages) + if err != nil { + panic(err) + } + + for _, flavor := range allFlavors { + fmt.Printf("%+v\n", flavor) + } + +Example to Create a Flavor + + createOpts := flavors.CreateOpts{ + Name: "Flavor name", + Description: "My flavor description", + Enable: true, + FlavorProfileId: "9daa2768-74e7-4d13-bf5d-1b8e0dc239e1", + } + + flavor, err := flavors.Create(octaviaClient, createOpts).Extract() + if err != nil { + panic(err) + } + +Example to Update a Flavor + + flavorID := "d67d56a6-4a86-4688-a282-f46444705c64" + + updateOpts := flavors.UpdateOpts{ + Name: "New name", + } + + flavor, err := flavors.Update(octaviaClient, flavorID, updateOpts).Extract() + if err != nil { + panic(err) + } + +Example to Delete a Flavor + + flavorID := "d67d56a6-4a86-4688-a282-f46444705c64" + err := flavors.Delete(octaviaClient, flavorID).ExtractErr() + if err != nil { + panic(err) + } +*/ +package flavors diff --git a/openstack/loadbalancer/v2/flavors/requests.go b/openstack/loadbalancer/v2/flavors/requests.go new file mode 100644 index 0000000000..77c816a517 --- /dev/null +++ b/openstack/loadbalancer/v2/flavors/requests.go @@ -0,0 +1,112 @@ +package flavors + +import ( + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +// LIST + +type ListOptsBuilder interface { + ToFlavorListQuery() (string, error) +} + +type ListOpts struct { + ID string `q:"id"` + Name string `q:"name"` +} + +func (opts ListOpts) ToFlavorListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + return q.String(), err +} + +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := rootURL(c) + if opts != nil { + query, err := opts.ToFlavorListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + return FlavorPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// CREATE + +type CreateOptsBuilder interface { + ToFlavorCreateMap() (map[string]interface{}, error) +} + +type CreateOpts struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + FlavorProfileId string `json:"flavor_profile_id,required:"true""` + Enabled bool `json:"enabled,default:"true""` +} + +func (opts CreateOpts) ToFlavorCreateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "flavor") +} + +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { + b, err := opts.ToFlavorCreateMap() + if err != nil { + r.Err = err + return + } + resp, err := c.Post(rootURL(c), b, &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// GET + +func Get(c *gophercloud.ServiceClient, id string) (r GetResult) { + resp, err := c.Get(resourceURL(c, id), &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// UPDATE + +type UpdateOptsBuilder interface { + ToFlavorUpdateMap() (map[string]interface{}, error) +} + +type UpdateOpts struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Enabled bool `json:"enabled" default:"true"` +} + +func (opts UpdateOpts) ToFlavorUpdateMap() (map[string]interface{}, error) { + b, err := gophercloud.BuildRequestBody(opts, "flavor") + if err != nil { + return nil, err + } + + return b, nil +} + +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) (r UpdateResult) { + b, err := opts.ToFlavorUpdateMap() + if err != nil { + r.Err = err + return + } + resp, err := c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 202}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) { + resp, err := c.Delete(resourceURL(c, id), nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} diff --git a/openstack/loadbalancer/v2/flavors/results.go b/openstack/loadbalancer/v2/flavors/results.go new file mode 100644 index 0000000000..46eb171c1a --- /dev/null +++ b/openstack/loadbalancer/v2/flavors/results.go @@ -0,0 +1,79 @@ +package flavors + +import ( + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +type Flavor struct { + // The unique ID for the Flavor + ID string `json:"id"` + + // Human-readable name for the Flavor. Does not have to be unique. + Name string `json:"name"` + + // Human-readable description for the Flavor. + Description string `json:"description"` + + // Status of the Flavor. + Enabled bool `json:"enabled"` + + // Flavor Profile apply to this Flavor. + FlavorProfileId string `json:"flavor_profile_id"` +} + +type FlavorPage struct { + pagination.LinkedPageBase +} + +func (r FlavorPage) NextPageURL() (string, error) { + var s struct { + Links []gophercloud.Link `json:"flavors_links"` + } + err := r.ExtractInto(&s) + if err != nil { + return "", err + } + return gophercloud.ExtractNextURL(s.Links) +} + +func (r FlavorPage) IsEmpty() (bool, error) { + is, err := ExtractFlavors(r) + return len(is) == 0, err +} + +func ExtractFlavors(r pagination.Page) ([]Flavor, error) { + var s struct { + Flavors []Flavor `json:"flavors"` + } + err := (r.(FlavorPage)).ExtractInto(&s) + return s.Flavors, err +} + +type commonResult struct { + gophercloud.Result +} + +func (r commonResult) Extract() (*Flavor, error) { + var s struct { + Flavor *Flavor `json:"flavor"` + } + err := r.ExtractInto(&s) + return s.Flavor, err +} + +type CreateResult struct { + commonResult +} + +type GetResult struct { + commonResult +} + +type UpdateResult struct { + commonResult +} + +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/openstack/loadbalancer/v2/flavors/testing/doc.go b/openstack/loadbalancer/v2/flavors/testing/doc.go new file mode 100644 index 0000000000..7603f836a0 --- /dev/null +++ b/openstack/loadbalancer/v2/flavors/testing/doc.go @@ -0,0 +1 @@ +package testing diff --git a/openstack/loadbalancer/v2/flavors/testing/fixutres.go b/openstack/loadbalancer/v2/flavors/testing/fixutres.go new file mode 100644 index 0000000000..65ac9bf8ea --- /dev/null +++ b/openstack/loadbalancer/v2/flavors/testing/fixutres.go @@ -0,0 +1,166 @@ +package testing + +import ( + "fmt" + "net/http" + "testing" + + "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/flavors" + + th "github.com/gophercloud/gophercloud/testhelper" + "github.com/gophercloud/gophercloud/testhelper/client" +) + +const FlavorsListBody = ` +{ + "flavors": [ + { + "id": "4c82a610-8c7f-4a72-8cca-42f584e3f6d1", + "name": "Basic", + "description": "A basic standalone Octavia load balancer.", + "enabled": true, + "flavor_profile_id": "bdba88c7-beab-4fc9-a5dd-3635de59185b" + }, + { + "id": "0af3b9cc-9284-44c2-9494-0ec337fa31bb", + "name": "Advance", + "description": "A advance standalone Octavia load balancer.", + "enabled": false, + "flavor_profile_id": "c221abc6-a845-45a0-925c-27110c9d7bdc" + } + ] +} +` + +const SingleFlavorBody = ` +{ + "flavor": { + "id": "5548c807-e6e8-43d7-9ea4-b38d34dd74a0", + "name": "Basic", + "description": "A basic standalone Octavia load balancer.", + "enabled": true, + "flavor_profile_id": "9daa2768-74e7-4d13-bf5d-1b8e0dc239e1" + } +} +` + +const PostUpdateFlavorBody = ` +{ + "flavor": { + "id": "5548c807-e6e8-43d7-9ea4-b38d34dd74a0", + "name": "Basic v2", + "description": "Rename flavor", + "enabled": false, + "flavor_profile_id": "9daa2768-74e7-4d13-bf5d-1b8e0dc239e1" + } +} +` + +var ( + FlavorBasic = flavors.Flavor{ + ID: "4c82a610-8c7f-4a72-8cca-42f584e3f6d1", + Name: "Basic", + Description: "A basic standalone Octavia load balancer.", + Enabled: true, + FlavorProfileId: "bdba88c7-beab-4fc9-a5dd-3635de59185b", + } + + FlavorAdvance = flavors.Flavor{ + ID: "0af3b9cc-9284-44c2-9494-0ec337fa31bb", + Name: "Advance", + Description: "A advance standalone Octavia load balancer.", + Enabled: false, + FlavorProfileId: "c221abc6-a845-45a0-925c-27110c9d7bdc", + } + + FlavorDb = flavors.Flavor{ + ID: "5548c807-e6e8-43d7-9ea4-b38d34dd74a0", + Name: "Basic", + Description: "A basic standalone Octavia load balancer.", + Enabled: true, + FlavorProfileId: "9daa2768-74e7-4d13-bf5d-1b8e0dc239e1", + } + + FlavorUpdated = flavors.Flavor{ + ID: "5548c807-e6e8-43d7-9ea4-b38d34dd74a0", + Name: "Basic v2", + Description: "Rename flavor", + Enabled: false, + FlavorProfileId: "9daa2768-74e7-4d13-bf5d-1b8e0dc239e1", + } +) + +func HandleFlavorListSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/v2.0/lbaas/flavors", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + r.ParseForm() + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, FlavorsListBody) + case "3a0d060b-fcec-4250-9ab6-940b806a12dd": + fmt.Fprintf(w, `{ "flavors": [] }`) + default: + t.Fatalf("/v2.0/lbaas/flavors invoked with unexpected marker=[%s]", marker) + } + }) +} + +func HandleFlavorCreationSuccessfully(t *testing.T, response string) { + th.Mux.HandleFunc("/v2.0/lbaas/flavors", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, `{ + "flavor": { + "name": "Basic", + "description": "A basic standalone Octavia load balancer.", + "enabled": true, + "flavor_profile_id": "9daa2768-74e7-4d13-bf5d-1b8e0dc239e1" + } + }`) + + w.WriteHeader(http.StatusAccepted) + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, response) + }) +} + +func HandleFlavorGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/v2.0/lbaas/flavors/5548c807-e6e8-43d7-9ea4-b38d34dd74a0", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + fmt.Fprintf(w, SingleFlavorBody) + }) +} + +func HandleFlavorDeletionSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/v2.0/lbaas/flavors/5548c807-e6e8-43d7-9ea4-b38d34dd74a0", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.WriteHeader(http.StatusNoContent) + }) +} + +func HandleFlavorUpdateSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/v2.0/lbaas/flavors/5548c807-e6e8-43d7-9ea4-b38d34dd74a0", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestJSONRequest(t, r, `{ + "flavor": { + "name": "Basic v2", + "description": "Rename flavor", + "enabled": false + } + }`) + + fmt.Fprintf(w, PostUpdateFlavorBody) + }) +} diff --git a/openstack/loadbalancer/v2/flavors/testing/requests_test.go b/openstack/loadbalancer/v2/flavors/testing/requests_test.go new file mode 100644 index 0000000000..12e6fa94f2 --- /dev/null +++ b/openstack/loadbalancer/v2/flavors/testing/requests_test.go @@ -0,0 +1,118 @@ +package testing + +import ( + "testing" + + "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/flavors" + "github.com/gophercloud/gophercloud/pagination" + + fake "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/testhelper" + th "github.com/gophercloud/gophercloud/testhelper" +) + +func TestListFlavors(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleFlavorListSuccessfully(t) + + pages := 0 + err := flavors.List(fake.ServiceClient(), flavors.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { + pages++ + + actual, err := flavors.ExtractFlavors(page) + if err != nil { + return false, err + } + + if len(actual) != 2 { + t.Fatalf("Expected 2 flavors, got %d", len(actual)) + } + th.CheckDeepEquals(t, FlavorBasic, actual[0]) + th.CheckDeepEquals(t, FlavorAdvance, actual[1]) + + return true, nil + }) + + th.AssertNoErr(t, err) + + if pages != 1 { + t.Errorf("Expected 1 page, saw %d", pages) + } +} + +func TestListAllFlavors(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleFlavorListSuccessfully(t) + + allPages, err := flavors.List(fake.ServiceClient(), flavors.ListOpts{}).AllPages() + th.AssertNoErr(t, err) + actual, err := flavors.ExtractFlavors(allPages) + th.AssertNoErr(t, err) + th.CheckDeepEquals(t, FlavorBasic, actual[0]) + th.CheckDeepEquals(t, FlavorAdvance, actual[1]) +} + +func TestCreateFlavor(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleFlavorCreationSuccessfully(t, SingleFlavorBody) + + actual, err := flavors.Create(fake.ServiceClient(), flavors.CreateOpts{ + Name: "Basic", + Description: "A basic standalone Octavia load balancer.", + Enabled: true, + FlavorProfileId: "9daa2768-74e7-4d13-bf5d-1b8e0dc239e1", + }).Extract() + th.AssertNoErr(t, err) + + th.CheckDeepEquals(t, FlavorDb, *actual) +} + +func TestRequiredCreateOpts(t *testing.T) { + res := flavors.Create(fake.ServiceClient(), flavors.CreateOpts{}) + if res.Err == nil { + t.Fatalf("Expected error, got none") + } +} + +func TestGetFlavor(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleFlavorGetSuccessfully(t) + + client := fake.ServiceClient() + actual, err := flavors.Get(client, "5548c807-e6e8-43d7-9ea4-b38d34dd74a0").Extract() + if err != nil { + t.Fatalf("Unexpected Get error: %v", err) + } + + th.CheckDeepEquals(t, FlavorDb, *actual) +} + +func TestDeleteFlavor(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleFlavorDeletionSuccessfully(t) + + res := flavors.Delete(fake.ServiceClient(), "5548c807-e6e8-43d7-9ea4-b38d34dd74a0") + th.AssertNoErr(t, res.Err) +} + +func TestUpdateFlavor(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleFlavorUpdateSuccessfully(t) + + client := fake.ServiceClient() + actual, err := flavors.Update(client, "5548c807-e6e8-43d7-9ea4-b38d34dd74a0", flavors.UpdateOpts{ + Name: "Basic v2", + Description: "Rename flavor", + Enabled: false, + }).Extract() + if err != nil { + t.Fatalf("Unexpected Update error: %v", err) + } + + th.CheckDeepEquals(t, FlavorUpdated, *actual) +} diff --git a/openstack/loadbalancer/v2/flavors/urls.go b/openstack/loadbalancer/v2/flavors/urls.go new file mode 100644 index 0000000000..5d9a84b1ff --- /dev/null +++ b/openstack/loadbalancer/v2/flavors/urls.go @@ -0,0 +1,16 @@ +package flavors + +import "github.com/gophercloud/gophercloud" + +const ( + rootPath = "lbaas" + resourcePath = "flavors" +) + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rootPath, resourcePath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id) +} From 7dd55c38c5367bae7e1484cff560010ad3ab9227 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Jourel Date: Tue, 28 Feb 2023 14:44:00 -0500 Subject: [PATCH 063/118] Add support of FlavorProfile for Octavia --- .../loadbalancer/v2/flavorprofiles_test.go | 53 ++++++ .../openstack/loadbalancer/v2/flavors_test.go | 66 ++++++++ .../openstack/loadbalancer/v2/loadbalancer.go | 71 ++++++++ .../loadbalancer/v2/flavorprofiles/doc.go | 57 +++++++ .../v2/flavorprofiles/requests.go | 137 +++++++++++++++ .../loadbalancer/v2/flavorprofiles/results.go | 95 +++++++++++ .../v2/flavorprofiles/testing/doc.go | 1 + .../v2/flavorprofiles/testing/fixtures.go | 157 ++++++++++++++++++ .../flavorprofiles/testing/requests_test.go | 117 +++++++++++++ .../loadbalancer/v2/flavorprofiles/urls.go | 16 ++ openstack/loadbalancer/v2/flavors/requests.go | 63 +++++-- openstack/loadbalancer/v2/flavors/results.go | 19 +++ .../testing/{fixutres.go => fixtures.go} | 2 +- .../v2/flavors/testing/requests_test.go | 2 +- 14 files changed, 837 insertions(+), 19 deletions(-) create mode 100644 internal/acceptance/openstack/loadbalancer/v2/flavorprofiles_test.go create mode 100644 internal/acceptance/openstack/loadbalancer/v2/flavors_test.go create mode 100644 openstack/loadbalancer/v2/flavorprofiles/doc.go create mode 100644 openstack/loadbalancer/v2/flavorprofiles/requests.go create mode 100644 openstack/loadbalancer/v2/flavorprofiles/results.go create mode 100644 openstack/loadbalancer/v2/flavorprofiles/testing/doc.go create mode 100644 openstack/loadbalancer/v2/flavorprofiles/testing/fixtures.go create mode 100644 openstack/loadbalancer/v2/flavorprofiles/testing/requests_test.go create mode 100644 openstack/loadbalancer/v2/flavorprofiles/urls.go rename openstack/loadbalancer/v2/flavors/testing/{fixutres.go => fixtures.go} (99%) diff --git a/internal/acceptance/openstack/loadbalancer/v2/flavorprofiles_test.go b/internal/acceptance/openstack/loadbalancer/v2/flavorprofiles_test.go new file mode 100644 index 0000000000..bde7dbec77 --- /dev/null +++ b/internal/acceptance/openstack/loadbalancer/v2/flavorprofiles_test.go @@ -0,0 +1,53 @@ +//go:build acceptance || networking || loadbalancer || flavorprofiles +// +build acceptance networking loadbalancer flavorprofiles + +package v2 + +import ( + "testing" + + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" + "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/flavorprofiles" + + th "github.com/gophercloud/gophercloud/testhelper" +) + +func TestFlavorProfilesList(t *testing.T) { + client, err := clients.NewLoadBalancerV2Client() + th.AssertNoErr(t, err) + + allPages, err := flavorprofiles.List(client, nil).AllPages() + th.AssertNoErr(t, err) + + allFlavorProfiles, err := flavorprofiles.ExtractFlavorProfiles(allPages) + th.AssertNoErr(t, err) + + for _, flavorprofile := range allFlavorProfiles { + tools.PrintResource(t, flavorprofile) + } +} + +func TestFlavorProfilesCRUD(t *testing.T) { + lbClient, err := clients.NewLoadBalancerV2Client() + th.AssertNoErr(t, err) + + flavorProfile, err := CreateFlavorProfile(t, lbClient) + th.AssertNoErr(t, err) + defer DeleteFlavorProfile(t, lbClient, flavorProfile) + + tools.PrintResource(t, flavorProfile) + + th.AssertEquals(t, "amphora", flavorProfile.ProviderName) + + flavorProfileUpdateOpts := flavorprofiles.UpdateOpts{ + Name: tools.RandomString("TESTACCTUP-", 8), + } + + flavorProfileUpdated, err := flavorprofiles.Update(lbClient, flavorProfile.ID, flavorProfileUpdateOpts).Extract() + th.AssertNoErr(t, err) + + th.AssertEquals(t, flavorProfileUpdateOpts.Name, flavorProfileUpdated.Name) + + t.Logf("Successfully updated flavorprofile %s", flavorProfileUpdated.Name) +} diff --git a/internal/acceptance/openstack/loadbalancer/v2/flavors_test.go b/internal/acceptance/openstack/loadbalancer/v2/flavors_test.go new file mode 100644 index 0000000000..f45b4c20a6 --- /dev/null +++ b/internal/acceptance/openstack/loadbalancer/v2/flavors_test.go @@ -0,0 +1,66 @@ +//go:build acceptance || networking || loadbalancer || flavors +// +build acceptance networking loadbalancer flavors + +package v2 + +import ( + "testing" + + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" + "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/flavors" + th "github.com/gophercloud/gophercloud/testhelper" +) + +func TestFlavorsList(t *testing.T) { + client, err := clients.NewLoadBalancerV2Client() + if err != nil { + t.Fatalf("Unable to create a loadbalancer client: %v", err) + } + + allPages, err := flavors.List(client, nil).AllPages() + if err != nil { + t.Fatalf("Unable to list flavors: %v", err) + } + + allFlavors, err := flavors.ExtractFlavors(allPages) + if err != nil { + t.Fatalf("Unable to extract flavors: %v", err) + } + + for _, flavor := range allFlavors { + tools.PrintResource(t, flavor) + } +} + +func TestFlavorsCRUD(t *testing.T) { + lbClient, err := clients.NewLoadBalancerV2Client() + th.AssertNoErr(t, err) + + flavorProfile, err := CreateFlavorProfile(t, lbClient) + th.AssertNoErr(t, err) + defer DeleteFlavorProfile(t, lbClient, flavorProfile) + + tools.PrintResource(t, flavorProfile) + + th.AssertEquals(t, "amphora", flavorProfile.ProviderName) + + flavor, err := CreateFlavor(t, lbClient, flavorProfile) + th.AssertNoErr(t, err) + defer DeleteFlavor(t, lbClient, flavor) + + tools.PrintResource(t, flavor) + + th.AssertEquals(t, flavor.FlavorProfileId, flavorProfile.ID) + + flavorUpdateOpts := flavors.UpdateOpts{ + Name: tools.RandomString("TESTACCTUP-", 8), + } + + flavorUpdated, err := flavors.Update(lbClient, flavor.ID, flavorUpdateOpts).Extract() + th.AssertNoErr(t, err) + + th.AssertEquals(t, flavorUpdateOpts.Name, flavorUpdated.Name) + + t.Logf("Successfully updated flavor %s", flavorUpdated.Name) +} diff --git a/internal/acceptance/openstack/loadbalancer/v2/loadbalancer.go b/internal/acceptance/openstack/loadbalancer/v2/loadbalancer.go index 72bd638ad0..b5eda52e18 100644 --- a/internal/acceptance/openstack/loadbalancer/v2/loadbalancer.go +++ b/internal/acceptance/openstack/loadbalancer/v2/loadbalancer.go @@ -8,6 +8,8 @@ import ( "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/internal/acceptance/clients" "github.com/gophercloud/gophercloud/internal/acceptance/tools" + "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/flavorprofiles" + "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/flavors" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers" @@ -676,3 +678,72 @@ func WaitForLoadBalancerState(client *gophercloud.ServiceClient, lbID, status st return false, nil }) } + +func CreateFlavorProfile(t *testing.T, client *gophercloud.ServiceClient) (*flavorprofiles.FlavorProfile, error) { + flavorProfileName := tools.RandomString("TESTACCT-", 8) + flavorProfileDriver := "amphora" + flavorProfileData := "{\"loadbalancer_topology\": \"SINGLE\"}" + + createOpts := flavorprofiles.CreateOpts{ + Name: flavorProfileName, + ProviderName: flavorProfileDriver, + FlavorData: flavorProfileData, + } + + flavorProfile, err := flavorprofiles.Create(client, createOpts).Extract() + if err != nil { + return flavorProfile, err + } + + t.Logf("Successfully created flavorprofile %s", flavorProfileName) + + th.AssertEquals(t, flavorProfileName, flavorProfile.Name) + th.AssertEquals(t, flavorProfileDriver, flavorProfile.ProviderName) + th.AssertEquals(t, flavorProfileData, flavorProfile.FlavorData) + + return flavorProfile, nil +} + +func DeleteFlavorProfile(t *testing.T, client *gophercloud.ServiceClient, flavorProfile *flavorprofiles.FlavorProfile) { + err := flavorprofiles.Delete(client, flavorProfile.ID).ExtractErr() + if err != nil { + t.Fatalf("Unable to delete flavorprofile: %v", err) + } + + t.Logf("Successfully deleted flavorprofile %s", flavorProfile.Name) +} + +func CreateFlavor(t *testing.T, client *gophercloud.ServiceClient, flavorProfile *flavorprofiles.FlavorProfile) (*flavors.Flavor, error) { + flavorName := tools.RandomString("TESTACCT-", 8) + description := tools.RandomString("TESTACCT-desc-", 32) + + createOpts := flavors.CreateOpts{ + Name: flavorName, + Description: description, + FlavorProfileId: flavorProfile.ID, + Enabled: true, + } + + flavor, err := flavors.Create(client, createOpts).Extract() + if err != nil { + return flavor, err + } + + t.Logf("Successfully created flavor %s with flavorprofile %s", flavor.Name, flavorProfile.Name) + + th.AssertEquals(t, flavorName, flavor.Name) + th.AssertEquals(t, description, flavor.Description) + th.AssertEquals(t, flavorProfile.ID, flavor.FlavorProfileId) + th.AssertEquals(t, true, flavor.Enabled) + + return flavor, nil +} + +func DeleteFlavor(t *testing.T, client *gophercloud.ServiceClient, flavor *flavors.Flavor) { + err := flavors.Delete(client, flavor.ID).ExtractErr() + if err != nil { + t.Fatalf("Unable to delete flavor: %v", err) + } + + t.Logf("Successfully deleted flavor %s", flavor.Name) +} diff --git a/openstack/loadbalancer/v2/flavorprofiles/doc.go b/openstack/loadbalancer/v2/flavorprofiles/doc.go new file mode 100644 index 0000000000..fcf846f3c3 --- /dev/null +++ b/openstack/loadbalancer/v2/flavorprofiles/doc.go @@ -0,0 +1,57 @@ +/* +Package flavorprofiles provides information and interaction +with FlavorProfiles for the OpenStack Load-balancing service. + +Example to List FlavorProfiles + + listOpts := flavorprofiles.ListOpts{} + + allPages, err := flavorprofiles.List(octaviaClient, listOpts).AllPages() + if err != nil { + panic(err) + } + + allFlavorProfiles, err := flavorprofiles.ExtractFlavorProfiles(allPages) + if err != nil { + panic(err) + } + + for _, flavorProfile := range allFlavorProfiles { + fmt.Printf("%+v\n", flavorProfile) + } + +Example to Create a FlavorProfile + + createOpts := flavorprofiles.CreateOpts{ + Name: "amphora-single", + ProviderName: "amphora", + FlavorData: "{\"loadbalancer_topology\": \"SINGLE\"}", + } + + flavorProfile, err := flavorprofiles.Create(octaviaClient, createOpts).Extract() + if err != nil { + panic(err) + } + +Example to Update a FlavorProfile + + flavorProfileID := "dd6a26af-8085-4047-a62b-3080f4c76521" + + updateOpts := flavorprofiles.UpdateOpts{ + Name: "amphora-single-updated", + } + + flavorProfile, err := flavorprofiles.Update(octaviaClient, flavorProfileID, updateOpts).Extract() + if err != nil { + panic(err) + } + +Example to Delete a FlavorProfile + + flavorProfileID := "dd6a26af-8085-4047-a62b-3080f4c76521" + err := flavorprofiles.Delete(octaviaClient, flavorProfileID).ExtractErr() + if err != nil { + panic(err) + } +*/ +package flavorprofiles diff --git a/openstack/loadbalancer/v2/flavorprofiles/requests.go b/openstack/loadbalancer/v2/flavorprofiles/requests.go new file mode 100644 index 0000000000..886fb5450d --- /dev/null +++ b/openstack/loadbalancer/v2/flavorprofiles/requests.go @@ -0,0 +1,137 @@ +package flavorprofiles + +import ( + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToFlavorProfileListQuery() (string, error) +} + +// ListOpts allows to manage the output of the request. +type ListOpts struct { + // The fields that you want the server to return + Fields []string `q:"fields"` +} + +// ToFlavorProfileListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToFlavorProfileListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + return q.String(), err +} + +// List returns a Pager which allows you to iterate over a collection of +// FlavorProfiles. It accepts a ListOpts struct, which allows you to filter +// and sort the returned collection for greater efficiency. +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := rootURL(c) + if opts != nil { + query, err := opts.ToFlavorProfileListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + return FlavorProfilePage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. +type CreateOptsBuilder interface { + ToFlavorProfileCreateMap() (map[string]interface{}, error) +} + +// CreateOpts is the common options struct used in this package's Create +// operation. +type CreateOpts struct { + // Human-readable name for the Loadbalancer. Does not have to be unique. + Name string `json:"name" required:"true"` + + // Providing the name of the provider supported by the Octavia installation. + ProviderName string `json:"provider_name" required:"true"` + + // Providing the json string containing the flavor metadata. + FlavorData string `json:"flavor_data" required:"true"` +} + +// ToFlavorProfileCreateMap builds a request body from CreateOpts. +func (opts CreateOpts) ToFlavorProfileCreateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "flavorprofile") +} + +// Create is and operation which add a new FlavorProfile into the database. +// CreateResult will be returned. +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { + b, err := opts.ToFlavorProfileCreateMap() + if err != nil { + r.Err = err + return + } + resp, err := c.Post(rootURL(c), b, &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// Get retrieves a particular FlavorProfile based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) (r GetResult) { + resp, err := c.Get(resourceURL(c, id), &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// UpdateOptsBuilder allows extensions to add additional parameters to the +// Update request. +type UpdateOptsBuilder interface { + ToFlavorProfileUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts is the common options struct used in this package's Update +// operation. +type UpdateOpts struct { + // Human-readable name for the Loadbalancer. Does not have to be unique. + Name string `json:"name,omitempty"` + + // Providing the name of the provider supported by the Octavia installation. + ProviderName string `json:"provider_name,omitempty"` + + // Providing the json string containing the flavor metadata. + FlavorData string `json:"flavor_data,omitempty"` +} + +// ToFlavorProfileUpdateMap builds a request body from UpdateOpts. +func (opts UpdateOpts) ToFlavorProfileUpdateMap() (map[string]interface{}, error) { + b, err := gophercloud.BuildRequestBody(opts, "flavorprofile") + if err != nil { + return nil, err + } + + return b, nil +} + +// Update is an operation which modifies the attributes of the specified +// FlavorProfile. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) (r UpdateResult) { + b, err := opts.ToFlavorProfileUpdateMap() + if err != nil { + r.Err = err + return + } + resp, err := c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 202}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// Delete will permanently delete a particular FlavorProfile based on its +// unique ID. +func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) { + resp, err := c.Delete(resourceURL(c, id), nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} diff --git a/openstack/loadbalancer/v2/flavorprofiles/results.go b/openstack/loadbalancer/v2/flavorprofiles/results.go new file mode 100644 index 0000000000..a4d7c11c19 --- /dev/null +++ b/openstack/loadbalancer/v2/flavorprofiles/results.go @@ -0,0 +1,95 @@ +package flavorprofiles + +import ( + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +// FlavorProfile provide metadata such as provider, toplogy and instance flavor. +type FlavorProfile struct { + // The unique ID for the Flavor + ID string `json:"id"` + + // Human-readable name for the Flavor. Does not have to be unique. + Name string `json:"name"` + + // Name of the provider + ProviderName string `json:"provider_name"` + + // Flavor data + FlavorData string `json:"flavor_data"` +} + +// FlavorProfilePage is the page returned by a pager when traversing over a +// collection of flavor profiles. +type FlavorProfilePage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of flavor profiles has +// reached the end of a page and the pager seeks to traverse over a new one. +// In order to do this, it needs to construct the next page's URL. +func (r FlavorProfilePage) NextPageURL() (string, error) { + var s struct { + Links []gophercloud.Link `json:"flavorprofiles_links"` + } + err := r.ExtractInto(&s) + if err != nil { + return "", err + } + return gophercloud.ExtractNextURL(s.Links) +} + +// IsEmpty checks whether a FlavorProfilePage struct is empty. +func (r FlavorProfilePage) IsEmpty() (bool, error) { + is, err := ExtractFlavorProfiles(r) + return len(is) == 0, err +} + +// ExtractFlavorProfiles accepts a Page struct, specifically a FlavorProfilePage +// struct, and extracts the elements into a slice of FlavorProfile structs. In +// other words, a generic collection is mapped into a relevant slice. +func ExtractFlavorProfiles(r pagination.Page) ([]FlavorProfile, error) { + var s struct { + FlavorProfiles []FlavorProfile `json:"flavorprofiles"` + } + err := (r.(FlavorProfilePage)).ExtractInto(&s) + return s.FlavorProfiles, err +} + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a flavor profile. +func (r commonResult) Extract() (*FlavorProfile, error) { + var s struct { + FlavorProfile *FlavorProfile `json:"flavorprofile"` + } + err := r.ExtractInto(&s) + return s.FlavorProfile, err +} + +// CreateResult represents the result of a create operation. Call its Extract +// method to interpret it as a FlavorProfile. +type CreateResult struct { + commonResult +} + +// GetResult represents the result of a get operation. Call its Extract +// method to interpret it as a FlavorProfile. +type GetResult struct { + commonResult +} + +// UpdateResult represents the result of an update operation. Call its Extract +// method to interpret it as a FlavorProfile. +type UpdateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. Call its +// ExtractErr method to determine if the request succeeded or failed. +type DeleteResult struct { + gophercloud.ErrResult +} diff --git a/openstack/loadbalancer/v2/flavorprofiles/testing/doc.go b/openstack/loadbalancer/v2/flavorprofiles/testing/doc.go new file mode 100644 index 0000000000..7603f836a0 --- /dev/null +++ b/openstack/loadbalancer/v2/flavorprofiles/testing/doc.go @@ -0,0 +1 @@ +package testing diff --git a/openstack/loadbalancer/v2/flavorprofiles/testing/fixtures.go b/openstack/loadbalancer/v2/flavorprofiles/testing/fixtures.go new file mode 100644 index 0000000000..35c341c576 --- /dev/null +++ b/openstack/loadbalancer/v2/flavorprofiles/testing/fixtures.go @@ -0,0 +1,157 @@ +package testing + +import ( + "fmt" + "net/http" + "testing" + + "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/flavorprofiles" + + th "github.com/gophercloud/gophercloud/testhelper" + "github.com/gophercloud/gophercloud/testhelper/client" +) + +const FlavorProfilesListBody = ` +{ + "flavorprofiles": [ + { + "id": "c55d080d-af45-47ee-b48c-4caa5e87724f", + "name": "amphora-single", + "provider_name": "amphora", + "flavor_data": "{\"loadbalancer_topology\": \"SINGLE\"}" + }, + { + "id": "f78d2815-3714-4b6e-91d8-cf821ba01017", + "name": "amphora-act-stdby", + "provider_name": "amphora", + "flavor_data": "{\"loadbalancer_topology\": \"ACTIVE_STANDBY\"}" + } + ] +} +` + +const SingleFlavorProfileBody = ` +{ + "flavorprofile": { + "id": "dcd65be5-f117-4260-ab3d-b32cc5bd1272", + "name": "amphora-test", + "provider_name": "amphora", + "flavor_data": "{\"loadbalancer_topology\": \"ACTIVE_STANDBY\"}" + } +} +` + +const PostUpdateFlavorBody = ` +{ + "flavorprofile": { + "id": "dcd65be5-f117-4260-ab3d-b32cc5bd1272", + "name": "amphora-test-updated", + "provider_name": "amphora", + "flavor_data": "{\"loadbalancer_topology\": \"SINGLE\"}" + } +} +` + +var ( + FlavorProfileSingle = flavorprofiles.FlavorProfile{ + ID: "c55d080d-af45-47ee-b48c-4caa5e87724f", + Name: "amphora-single", + ProviderName: "amphora", + FlavorData: "{\"loadbalancer_topology\": \"SINGLE\"}", + } + + FlavorProfileAct = flavorprofiles.FlavorProfile{ + ID: "f78d2815-3714-4b6e-91d8-cf821ba01017", + Name: "amphora-act-stdby", + ProviderName: "amphora", + FlavorData: "{\"loadbalancer_topology\": \"ACTIVE_STANDBY\"}", + } + + FlavorDb = flavorprofiles.FlavorProfile{ + ID: "dcd65be5-f117-4260-ab3d-b32cc5bd1272", + Name: "amphora-test", + ProviderName: "amphora", + FlavorData: "{\"loadbalancer_topology\": \"ACTIVE_STANDBY\"}", + } + + FlavorUpdated = flavorprofiles.FlavorProfile{ + ID: "dcd65be5-f117-4260-ab3d-b32cc5bd1272", + Name: "amphora-test-updated", + ProviderName: "amphora", + FlavorData: "{\"loadbalancer_topology\": \"SINGLE\"}", + } +) + +func HandleFlavorProfileListSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/v2.0/lbaas/flavorprofiles", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.Header().Add("Content-Type", "application/json") + r.ParseForm() + marker := r.Form.Get("marker") + switch marker { + case "": + fmt.Fprintf(w, FlavorProfilesListBody) + case "3a0d060b-fcec-4250-9ab6-940b806a12dd": + fmt.Fprintf(w, `{ "flavors": [] }`) + default: + t.Fatalf("/v2.0/lbaas/flavors invoked with unexpected marker=[%s]", marker) + } + }) +} + +func HandleFlavorProfileCreationSuccessfully(t *testing.T, response string) { + th.Mux.HandleFunc("/v2.0/lbaas/flavorprofiles", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestJSONRequest(t, r, `{ + "flavorprofile": { + "name": "amphora-test", + "provider_name": "amphora", + "flavor_data": "{\"loadbalancer_topology\": \"ACTIVE_STANDBY\"}" + } + }`) + + w.WriteHeader(http.StatusAccepted) + w.Header().Add("Content-Type", "application/json") + fmt.Fprintf(w, response) + }) +} + +func HandleFlavorProfileGetSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/v2.0/lbaas/flavorprofiles/dcd65be5-f117-4260-ab3d-b32cc5bd1272", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + fmt.Fprintf(w, SingleFlavorProfileBody) + }) +} + +func HandleFlavorProfileDeletionSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/v2.0/lbaas/flavorprofiles/dcd65be5-f117-4260-ab3d-b32cc5bd1272", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + + w.WriteHeader(http.StatusNoContent) + }) +} + +func HandleFlavorProfileUpdateSuccessfully(t *testing.T) { + th.Mux.HandleFunc("/v2.0/lbaas/flavorprofiles/dcd65be5-f117-4260-ab3d-b32cc5bd1272", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestJSONRequest(t, r, `{ + "flavorprofile": { + "name": "amphora-test-updated", + "provider_name": "amphora", + "flavor_data": "{\"loadbalancer_topology\": \"SINGLE\"}" + } + }`) + + fmt.Fprintf(w, PostUpdateFlavorBody) + }) +} diff --git a/openstack/loadbalancer/v2/flavorprofiles/testing/requests_test.go b/openstack/loadbalancer/v2/flavorprofiles/testing/requests_test.go new file mode 100644 index 0000000000..1b30e2ff07 --- /dev/null +++ b/openstack/loadbalancer/v2/flavorprofiles/testing/requests_test.go @@ -0,0 +1,117 @@ +package testing + +import ( + "testing" + + "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/flavorprofiles" + "github.com/gophercloud/gophercloud/pagination" + + fake "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/testhelper" + th "github.com/gophercloud/gophercloud/testhelper" +) + +func TestListFlavorProfiles(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleFlavorProfileListSuccessfully(t) + + pages := 0 + err := flavorprofiles.List(fake.ServiceClient(), flavorprofiles.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) { + pages++ + + actual, err := flavorprofiles.ExtractFlavorProfiles(page) + if err != nil { + return false, err + } + + if len(actual) != 2 { + t.Fatalf("Expected 2 flavors, got %d", len(actual)) + } + th.CheckDeepEquals(t, FlavorProfileSingle, actual[0]) + th.CheckDeepEquals(t, FlavorProfileAct, actual[1]) + + return true, nil + }) + + th.AssertNoErr(t, err) + + if pages != 1 { + t.Errorf("Expected 1 page, saw %d", pages) + } +} + +func TestListAllFlavorProfiles(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleFlavorProfileListSuccessfully(t) + + allPages, err := flavorprofiles.List(fake.ServiceClient(), flavorprofiles.ListOpts{}).AllPages() + th.AssertNoErr(t, err) + actual, err := flavorprofiles.ExtractFlavorProfiles(allPages) + th.AssertNoErr(t, err) + th.CheckDeepEquals(t, FlavorProfileSingle, actual[0]) + th.CheckDeepEquals(t, FlavorProfileAct, actual[1]) +} + +func TestCreateFlavorProfile(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleFlavorProfileCreationSuccessfully(t, SingleFlavorProfileBody) + + actual, err := flavorprofiles.Create(fake.ServiceClient(), flavorprofiles.CreateOpts{ + Name: "amphora-test", + ProviderName: "amphora", + FlavorData: "{\"loadbalancer_topology\": \"ACTIVE_STANDBY\"}", + }).Extract() + th.AssertNoErr(t, err) + + th.CheckDeepEquals(t, FlavorDb, *actual) +} + +func TestRequiredCreateOpts(t *testing.T) { + res := flavorprofiles.Create(fake.ServiceClient(), flavorprofiles.CreateOpts{}) + if res.Err == nil { + t.Fatalf("Expected error, got none") + } +} + +func TestGetFlavorProfiles(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleFlavorProfileGetSuccessfully(t) + + client := fake.ServiceClient() + actual, err := flavorprofiles.Get(client, "dcd65be5-f117-4260-ab3d-b32cc5bd1272").Extract() + if err != nil { + t.Fatalf("Unexpected Get error: %v", err) + } + + th.CheckDeepEquals(t, FlavorDb, *actual) +} + +func TestDeleteFlavorProfile(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleFlavorProfileDeletionSuccessfully(t) + + res := flavorprofiles.Delete(fake.ServiceClient(), "dcd65be5-f117-4260-ab3d-b32cc5bd1272") + th.AssertNoErr(t, res.Err) +} + +func TestUpdateFlavorProfile(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + HandleFlavorProfileUpdateSuccessfully(t) + + client := fake.ServiceClient() + actual, err := flavorprofiles.Update(client, "dcd65be5-f117-4260-ab3d-b32cc5bd1272", flavorprofiles.UpdateOpts{ + Name: "amphora-test-updated", + ProviderName: "amphora", + FlavorData: "{\"loadbalancer_topology\": \"SINGLE\"}", + }).Extract() + if err != nil { + t.Fatalf("Unexpected Update error: %v", err) + } + + th.CheckDeepEquals(t, FlavorUpdated, *actual) +} diff --git a/openstack/loadbalancer/v2/flavorprofiles/urls.go b/openstack/loadbalancer/v2/flavorprofiles/urls.go new file mode 100644 index 0000000000..6125d77923 --- /dev/null +++ b/openstack/loadbalancer/v2/flavorprofiles/urls.go @@ -0,0 +1,16 @@ +package flavorprofiles + +import "github.com/gophercloud/gophercloud" + +const ( + rootPath = "lbaas" + resourcePath = "flavorprofiles" +) + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rootPath, resourcePath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id) +} diff --git a/openstack/loadbalancer/v2/flavors/requests.go b/openstack/loadbalancer/v2/flavors/requests.go index 77c816a517..0b9509c320 100644 --- a/openstack/loadbalancer/v2/flavors/requests.go +++ b/openstack/loadbalancer/v2/flavors/requests.go @@ -5,22 +5,27 @@ import ( "github.com/gophercloud/gophercloud/pagination" ) -// LIST - +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. type ListOptsBuilder interface { ToFlavorListQuery() (string, error) } +// ListOpts allows to manage the output of the request. type ListOpts struct { - ID string `q:"id"` - Name string `q:"name"` + // The fields that you want the server to return + Fields []string `q:"fields"` } +// ToFlavorListQuery formats a ListOpts into a query string. func (opts ListOpts) ToFlavorListQuery() (string, error) { q, err := gophercloud.BuildQueryString(opts) return q.String(), err } +// List returns a Pager which allows you to iterate over a collection of +// Flavor. It accepts a ListOpts struct, which allows you to filter +// and sort the returned collection for greater efficiency. func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { url := rootURL(c) if opts != nil { @@ -35,23 +40,36 @@ func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { }) } -// CREATE - +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. type CreateOptsBuilder interface { ToFlavorCreateMap() (map[string]interface{}, error) } +// CreateOpts is the common options struct used in this package's Create +// operation. type CreateOpts struct { - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - FlavorProfileId string `json:"flavor_profile_id,required:"true""` - Enabled bool `json:"enabled,default:"true""` + // Human-readable name for the Loadbalancer. Does not have to be unique. + Name string `json:"name" required:"true"` + + // Human-readable description for the Flavor. + Description string `json:"description,omitempty"` + + // The ID of the FlavorProfile which give the metadata for the creation of + // a LoadBalancer. + FlavorProfileId string `json:"flavor_profile_id" required:"true"` + + // If the resource is available for use. The default is True. + Enabled bool `json:"enabled,omitempty"` } +// ToFlavorCreateMap builds a request body from CreateOpts. func (opts CreateOpts) ToFlavorCreateMap() (map[string]interface{}, error) { return gophercloud.BuildRequestBody(opts, "flavor") } +// Create is and operation which add a new Flavor into the database. +// CreateResult will be returned. func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { b, err := opts.ToFlavorCreateMap() if err != nil { @@ -63,26 +81,33 @@ func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResul return } -// GET - +// Get retrieves a particular Flavor based on its unique ID. func Get(c *gophercloud.ServiceClient, id string) (r GetResult) { resp, err := c.Get(resourceURL(c, id), &r.Body, nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// UPDATE - +// UpdateOptsBuilder allows extensions to add additional parameters to the +// Update request. type UpdateOptsBuilder interface { ToFlavorUpdateMap() (map[string]interface{}, error) } +// UpdateOpts is the common options struct used in this package's Update +// operation. type UpdateOpts struct { - Name string `json:"name,omitempty"` + // Human-readable name for the Loadbalancer. Does not have to be unique. + Name string `json:"name,omitempty"` + + // Human-readable description for the Flavor. Description string `json:"description,omitempty"` - Enabled bool `json:"enabled" default:"true"` + + // If the resource is available for use. + Enabled bool `json:"enabled,omitempty"` } +// ToFlavorUpdateMap builds a request body from UpdateOpts. func (opts UpdateOpts) ToFlavorUpdateMap() (map[string]interface{}, error) { b, err := gophercloud.BuildRequestBody(opts, "flavor") if err != nil { @@ -92,6 +117,8 @@ func (opts UpdateOpts) ToFlavorUpdateMap() (map[string]interface{}, error) { return b, nil } +// Update is an operation which modifies the attributes of the specified +// Flavor. func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) (r UpdateResult) { b, err := opts.ToFlavorUpdateMap() if err != nil { @@ -99,12 +126,14 @@ func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) (r UpdateR return } resp, err := c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{ - OkCodes: []int{200, 202}, + OkCodes: []int{200}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// Delete will permanently delete a particular Flavor based on its +// unique ID. func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) { resp, err := c.Delete(resourceURL(c, id), nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) diff --git a/openstack/loadbalancer/v2/flavors/results.go b/openstack/loadbalancer/v2/flavors/results.go index 46eb171c1a..21c517154d 100644 --- a/openstack/loadbalancer/v2/flavors/results.go +++ b/openstack/loadbalancer/v2/flavors/results.go @@ -5,6 +5,7 @@ import ( "github.com/gophercloud/gophercloud/pagination" ) +// Flavor provide specs for the creation of a load balancer. type Flavor struct { // The unique ID for the Flavor ID string `json:"id"` @@ -22,10 +23,15 @@ type Flavor struct { FlavorProfileId string `json:"flavor_profile_id"` } +// FlavorPage is the page returned by a pager when traversing over a +// collection of flavors. type FlavorPage struct { pagination.LinkedPageBase } +// NextPageURL is invoked when a paginated collection of flavors has +// reached the end of a page and the pager seeks to traverse over a new one. +// In order to do this, it needs to construct the next page's URL. func (r FlavorPage) NextPageURL() (string, error) { var s struct { Links []gophercloud.Link `json:"flavors_links"` @@ -37,11 +43,15 @@ func (r FlavorPage) NextPageURL() (string, error) { return gophercloud.ExtractNextURL(s.Links) } +// IsEmpty checks whether a FlavorPage struct is empty. func (r FlavorPage) IsEmpty() (bool, error) { is, err := ExtractFlavors(r) return len(is) == 0, err } +// ExtractFlavors accepts a Page struct, specifically a FlavorPage +// struct, and extracts the elements into a slice of Flavor structs. In +// other words, a generic collection is mapped into a relevant slice. func ExtractFlavors(r pagination.Page) ([]Flavor, error) { var s struct { Flavors []Flavor `json:"flavors"` @@ -54,6 +64,7 @@ type commonResult struct { gophercloud.Result } +// Extract is a function that accepts a result and extracts a flavor. func (r commonResult) Extract() (*Flavor, error) { var s struct { Flavor *Flavor `json:"flavor"` @@ -62,18 +73,26 @@ func (r commonResult) Extract() (*Flavor, error) { return s.Flavor, err } +// CreateResult represents the result of a create operation. Call its Extract +// method to interpret it as a Flavor. type CreateResult struct { commonResult } +// GetResult represents the result of a get operation. Call its Extract +// method to interpret it as a Flavor. type GetResult struct { commonResult } +// UpdateResult represents the result of an update operation. Call its Extract +// method to interpret it as a Flavor. type UpdateResult struct { commonResult } +// DeleteResult represents the result of a delete operation. Call its +// ExtractErr method to determine if the request succeeded or failed. type DeleteResult struct { gophercloud.ErrResult } diff --git a/openstack/loadbalancer/v2/flavors/testing/fixutres.go b/openstack/loadbalancer/v2/flavors/testing/fixtures.go similarity index 99% rename from openstack/loadbalancer/v2/flavors/testing/fixutres.go rename to openstack/loadbalancer/v2/flavors/testing/fixtures.go index 65ac9bf8ea..42e2fc96a0 100644 --- a/openstack/loadbalancer/v2/flavors/testing/fixutres.go +++ b/openstack/loadbalancer/v2/flavors/testing/fixtures.go @@ -157,7 +157,7 @@ func HandleFlavorUpdateSuccessfully(t *testing.T) { "flavor": { "name": "Basic v2", "description": "Rename flavor", - "enabled": false + "enabled": true } }`) diff --git a/openstack/loadbalancer/v2/flavors/testing/requests_test.go b/openstack/loadbalancer/v2/flavors/testing/requests_test.go index 12e6fa94f2..b04f3056f8 100644 --- a/openstack/loadbalancer/v2/flavors/testing/requests_test.go +++ b/openstack/loadbalancer/v2/flavors/testing/requests_test.go @@ -108,7 +108,7 @@ func TestUpdateFlavor(t *testing.T) { actual, err := flavors.Update(client, "5548c807-e6e8-43d7-9ea4-b38d34dd74a0", flavors.UpdateOpts{ Name: "Basic v2", Description: "Rename flavor", - Enabled: false, + Enabled: true, }).Extract() if err != nil { t.Fatalf("Unexpected Update error: %v", err) From bb3f61b4f3bb970b691c1bcc33dc369b93130963 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Fri, 2 Feb 2024 09:33:28 -0500 Subject: [PATCH 064/118] Prepare v1.9.0 --- CHANGELOG.md | 15 +++++++++++++++ provider_client.go | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e13f9e17ef..e10078ade6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +## v1.9.0 (2024-02-02) + +New features and improvements: + +* [GH-2884](https://github.com/gophercloud/gophercloud/pull/2884) [v1] Context-aware methods to ProviderClient and ServiceClient +* [GH-2887](https://github.com/gophercloud/gophercloud/pull/2887) [v1] Add support of Flavors and FlavorProfiles for Octavia +* [GH-2875](https://github.com/gophercloud/gophercloud/pull/2875) [v1] [db/v1/instance]: adding support for availability_zone for a db instance + +CI changes: + +* [GH-2856](https://github.com/gophercloud/gophercloud/pull/2856) [v1] Fix devstack install on EOL magnum branches +* [GH-2857](https://github.com/gophercloud/gophercloud/pull/2857) [v1] Fix networking acceptance tests +* [GH-2858](https://github.com/gophercloud/gophercloud/pull/2858) [v1] build(deps): bump actions/upload-artifact from 3 to 4 +* [GH-2859](https://github.com/gophercloud/gophercloud/pull/2859) [v1] build(deps): bump github/codeql-action from 2 to 3 + ## v1.8.0 (2023-11-30) New features and improvements: diff --git a/provider_client.go b/provider_client.go index bf43099e0b..5cb5e150ff 100644 --- a/provider_client.go +++ b/provider_client.go @@ -16,7 +16,7 @@ import ( // DefaultUserAgent is the default User-Agent string set in the request header. const ( - DefaultUserAgent = "gophercloud/v1.8.0" + DefaultUserAgent = "gophercloud/v1.9.0" DefaultMaxBackoffRetries = 60 ) From b0d7555b64cf64871644bdb3e3d8d97b2d65fc6d Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Fri, 2 Feb 2024 16:49:22 +0100 Subject: [PATCH 065/118] tokens: Add WithContext functions --- openstack/identity/v2/tokens/requests.go | 26 +++- .../v3/extensions/ec2tokens/requests.go | 26 +++- .../identity/v3/extensions/oauth1/requests.go | 124 +++++++++++++----- openstack/identity/v3/tokens/requests.go | 50 +++++-- 4 files changed, 166 insertions(+), 60 deletions(-) diff --git a/openstack/identity/v2/tokens/requests.go b/openstack/identity/v2/tokens/requests.go index 84f16c3fc2..67c04fced2 100644 --- a/openstack/identity/v2/tokens/requests.go +++ b/openstack/identity/v2/tokens/requests.go @@ -1,6 +1,10 @@ package tokens -import "github.com/gophercloud/gophercloud" +import ( + "context" + + "github.com/gophercloud/gophercloud" +) // PasswordCredentialsV2 represents the required options to authenticate // with a username and password. @@ -77,17 +81,17 @@ func (opts AuthOptions) ToTokenV2CreateMap() (map[string]interface{}, error) { return b, nil } -// Create authenticates to the identity service and attempts to acquire a Token. +// CreateWithContext authenticates to the identity service and attempts to acquire a Token. // Generally, rather than interact with this call directly, end users should // call openstack.AuthenticatedClient(), which abstracts all of the gory details // about navigating service catalogs and such. -func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) { +func CreateWithContext(ctx context.Context, client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) { b, err := auth.ToTokenV2CreateMap() if err != nil { r.Err = err return } - resp, err := client.Post(CreateURL(client), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.PostWithContext(ctx, CreateURL(client), b, &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{200, 203}, OmitHeaders: []string{"X-Auth-Token"}, }) @@ -95,11 +99,21 @@ func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r Creat return } -// Get validates and retrieves information for user's token. -func Get(client *gophercloud.ServiceClient, token string) (r GetResult) { +// Create is a compatibility wrapper around CreateWithContext +func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) { + return CreateWithContext(context.Background(), client, auth) +} + +// GetWithContext validates and retrieves information for user's token. +func GetWithContext(ctx context.Context, client *gophercloud.ServiceClient, token string) (r GetResult) { resp, err := client.Get(GetURL(client, token), &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{200, 203}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } + +// Get is a compatibility wrapper around GetWithContext +func Get(client *gophercloud.ServiceClient, token string) (r GetResult) { + return GetWithContext(context.Background(), client, token) +} diff --git a/openstack/identity/v3/extensions/ec2tokens/requests.go b/openstack/identity/v3/extensions/ec2tokens/requests.go index 32ba0e621d..b5b5350c54 100644 --- a/openstack/identity/v3/extensions/ec2tokens/requests.go +++ b/openstack/identity/v3/extensions/ec2tokens/requests.go @@ -1,6 +1,7 @@ package ec2tokens import ( + "context" "crypto/hmac" "crypto/sha1" "crypto/sha256" @@ -287,8 +288,8 @@ func (opts *AuthOptions) ToTokenV3CreateMap(map[string]interface{}) (map[string] return b, nil } -// Create authenticates and either generates a new token from EC2 credentials -func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { +// CreateWithContext authenticates and either generates a new token from EC2 credentials +func CreateWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { b, err := opts.ToTokenV3CreateMap(nil) if err != nil { r.Err = err @@ -298,7 +299,7 @@ func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tok // delete "token" element, since it is used in s3tokens deleteBodyElements(b, "token") - resp, err := c.Post(ec2tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := c.PostWithContext(ctx, ec2tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{ MoreHeaders: map[string]string{"X-Auth-Token": ""}, OkCodes: []int{200}, }) @@ -306,9 +307,15 @@ func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tok return } -// ValidateS3Token authenticates an S3 request using EC2 credentials. Doesn't -// generate a new token ID, but returns a tokens.CreateResult. -func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { +// Create is a compatibility wrapper around CreateWithContext +func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { + return CreateWithContext(context.Background(), c, opts) +} + +// ValidateS3TokenWithContext authenticates an S3 request using EC2 +// credentials. Doesn't generate a new token ID, but returns a +// tokens.CreateResult. +func ValidateS3TokenWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { b, err := opts.ToTokenV3CreateMap(nil) if err != nil { r.Err = err @@ -318,7 +325,7 @@ func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilde // delete unused element, since it is used in ec2tokens only deleteBodyElements(b, "body_hash", "headers", "host", "params", "path", "verb") - resp, err := c.Post(s3tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := c.PostWithContext(ctx, s3tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{ MoreHeaders: map[string]string{"X-Auth-Token": ""}, OkCodes: []int{200}, }) @@ -326,6 +333,11 @@ func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilde return } +// ValidateS3Token is a compatibility wrapper around ValidateS3TokenWithContext +func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { + return ValidateS3TokenWithContext(context.Background(), c, opts) +} + // The following are small helper functions used to help build the signature. // sumHMAC1 is a func to implement the HMAC SHA1 signature method. diff --git a/openstack/identity/v3/extensions/oauth1/requests.go b/openstack/identity/v3/extensions/oauth1/requests.go index 028b5a45bd..9921056320 100644 --- a/openstack/identity/v3/extensions/oauth1/requests.go +++ b/openstack/identity/v3/extensions/oauth1/requests.go @@ -1,6 +1,7 @@ package oauth1 import ( + "context" "crypto/hmac" "crypto/sha1" "encoding/base64" @@ -133,9 +134,9 @@ func (opts AuthOptions) ToTokenV3CreateMap(map[string]interface{}) (map[string]i return gophercloud.BuildRequestBody(req, "") } -// Create authenticates and either generates a new OpenStack token from an -// OAuth1 token. -func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { +// CreateWithContext authenticates and either generates a new OpenStack token +// from an OAuth1 token. +func CreateWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { b, err := opts.ToTokenV3CreateMap(nil) if err != nil { r.Err = err @@ -153,7 +154,7 @@ func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) ( return } - resp, err := client.Post(authURL(client), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.PostWithContext(ctx, authURL(client), b, &r.Body, &gophercloud.RequestOpts{ MoreHeaders: h, OkCodes: []int{201}, }) @@ -161,6 +162,11 @@ func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) ( return } +// Create is a compatibility wrapper around CreateWithContext. +func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { + return CreateWithContext(context.Background(), client, opts) +} + // CreateConsumerOptsBuilder allows extensions to add additional parameters to // the CreateConsumer request. type CreateConsumerOptsBuilder interface { @@ -178,27 +184,37 @@ func (opts CreateConsumerOpts) ToOAuth1CreateConsumerMap() (map[string]interface return gophercloud.BuildRequestBody(opts, "consumer") } -// Create creates a new Consumer. -func CreateConsumer(client *gophercloud.ServiceClient, opts CreateConsumerOptsBuilder) (r CreateConsumerResult) { +// CreateConsumerWithContext creates a new Consumer. +func CreateConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts CreateConsumerOptsBuilder) (r CreateConsumerResult) { b, err := opts.ToOAuth1CreateConsumerMap() if err != nil { r.Err = err return } - resp, err := client.Post(consumersURL(client), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.PostWithContext(ctx, consumersURL(client), b, &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{201}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// Delete deletes a Consumer. -func DeleteConsumer(client *gophercloud.ServiceClient, id string) (r DeleteConsumerResult) { - resp, err := client.Delete(consumerURL(client, id), nil) +// CreateConsumer is a compatibility wrapper around CreateConsumerWithContext. +func CreateConsumer(client *gophercloud.ServiceClient, opts CreateConsumerOptsBuilder) (r CreateConsumerResult) { + return CreateConsumerWithContext(context.Background(), client, opts) +} + +// DeleteConsumerWithContext deletes a Consumer. +func DeleteConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string) (r DeleteConsumerResult) { + resp, err := client.DeleteWithContext(ctx, consumerURL(client, id), nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// DeleteConsumer is a compatibility wrapper around DeleteConsumerWithContext. +func DeleteConsumer(client *gophercloud.ServiceClient, id string) (r DeleteConsumerResult) { + return DeleteConsumerWithContext(context.Background(), client, id) +} + // List enumerates Consumers. func ListConsumers(client *gophercloud.ServiceClient) pagination.Pager { return pagination.NewPager(client, consumersURL(client), func(r pagination.PageResult) pagination.Page { @@ -206,13 +222,18 @@ func ListConsumers(client *gophercloud.ServiceClient) pagination.Pager { }) } -// GetConsumer retrieves details on a single Consumer by ID. -func GetConsumer(client *gophercloud.ServiceClient, id string) (r GetConsumerResult) { - resp, err := client.Get(consumerURL(client, id), &r.Body, nil) +// GetConsumerWithContext retrieves details on a single Consumer by ID. +func GetConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetConsumerResult) { + resp, err := client.GetWithContext(ctx, consumerURL(client, id), &r.Body, nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// GetConsumer is a compatibility wrapper around GetConsumerWithContext. +func GetConsumer(client *gophercloud.ServiceClient, id string) (r GetConsumerResult) { + return GetConsumerWithContext(context.Background(), client, id) +} + // UpdateConsumerOpts provides options used to update a consumer. type UpdateConsumerOpts struct { // Description is the consumer description. @@ -225,20 +246,25 @@ func (opts UpdateConsumerOpts) ToOAuth1UpdateConsumerMap() (map[string]interface return gophercloud.BuildRequestBody(opts, "consumer") } -// UpdateConsumer updates an existing Consumer. -func UpdateConsumer(client *gophercloud.ServiceClient, id string, opts UpdateConsumerOpts) (r UpdateConsumerResult) { +// UpdateConsumerWithContext updates an existing Consumer. +func UpdateConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string, opts UpdateConsumerOpts) (r UpdateConsumerResult) { b, err := opts.ToOAuth1UpdateConsumerMap() if err != nil { r.Err = err return } - resp, err := client.Patch(consumerURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.PatchWithContext(ctx, consumerURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{200}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// UpdateConsumer is a compatibility wrapper around UpdateConsumerWithContext. +func UpdateConsumer(client *gophercloud.ServiceClient, id string, opts UpdateConsumerOpts) (r UpdateConsumerResult) { + return UpdateConsumerWithContext(context.Background(), client, id, opts) +} + // RequestTokenOptsBuilder allows extensions to add additional parameters to the // RequestToken request. type RequestTokenOptsBuilder interface { @@ -297,15 +323,15 @@ func (opts RequestTokenOpts) ToOAuth1RequestTokenHeaders(method, u string) (map[ return h, nil } -// RequestToken requests an unauthorized OAuth1 Token. -func RequestToken(client *gophercloud.ServiceClient, opts RequestTokenOptsBuilder) (r TokenResult) { +// RequestTokenWithContext requests an unauthorized OAuth1 Token. +func RequestTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts RequestTokenOptsBuilder) (r TokenResult) { h, err := opts.ToOAuth1RequestTokenHeaders("POST", requestTokenURL(client)) if err != nil { r.Err = err return } - resp, err := client.Post(requestTokenURL(client), nil, nil, &gophercloud.RequestOpts{ + resp, err := client.PostWithContext(ctx, requestTokenURL(client), nil, nil, &gophercloud.RequestOpts{ MoreHeaders: h, OkCodes: []int{201}, KeepResponseBody: true, @@ -323,6 +349,11 @@ func RequestToken(client *gophercloud.ServiceClient, opts RequestTokenOptsBuilde return } +// RequestToken is a compatibility wrapper around RequestTokenWithContext. +func RequestToken(client *gophercloud.ServiceClient, opts RequestTokenOptsBuilder) (r TokenResult) { + return RequestTokenWithContext(context.Background(), client, opts) +} + // AuthorizeTokenOptsBuilder allows extensions to add additional parameters to // the AuthorizeToken request. type AuthorizeTokenOptsBuilder interface { @@ -351,20 +382,25 @@ func (opts AuthorizeTokenOpts) ToOAuth1AuthorizeTokenMap() (map[string]interface return gophercloud.BuildRequestBody(opts, "") } -// AuthorizeToken authorizes an unauthorized consumer token. -func AuthorizeToken(client *gophercloud.ServiceClient, id string, opts AuthorizeTokenOptsBuilder) (r AuthorizeTokenResult) { +// AuthorizeTokenWithContext authorizes an unauthorized consumer token. +func AuthorizeTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string, opts AuthorizeTokenOptsBuilder) (r AuthorizeTokenResult) { b, err := opts.ToOAuth1AuthorizeTokenMap() if err != nil { r.Err = err return } - resp, err := client.Put(authorizeTokenURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.PutWithContext(ctx, authorizeTokenURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{200}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// AuthorizeToken is a compatibility wrapper around AuthorizeTokenWithContext. +func AuthorizeToken(client *gophercloud.ServiceClient, id string, opts AuthorizeTokenOptsBuilder) (r AuthorizeTokenResult) { + return AuthorizeTokenWithContext(context.Background(), client, id, opts) +} + // CreateAccessTokenOptsBuilder allows extensions to add additional parameters // to the CreateAccessToken request. type CreateAccessTokenOptsBuilder interface { @@ -425,15 +461,15 @@ func (opts CreateAccessTokenOpts) ToOAuth1CreateAccessTokenHeaders(method, u str return headers, nil } -// CreateAccessToken creates a new OAuth1 Access Token -func CreateAccessToken(client *gophercloud.ServiceClient, opts CreateAccessTokenOptsBuilder) (r TokenResult) { +// CreateAccessTokenWithContext creates a new OAuth1 Access Token +func CreateAccessTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts CreateAccessTokenOptsBuilder) (r TokenResult) { h, err := opts.ToOAuth1CreateAccessTokenHeaders("POST", createAccessTokenURL(client)) if err != nil { r.Err = err return } - resp, err := client.Post(createAccessTokenURL(client), nil, nil, &gophercloud.RequestOpts{ + resp, err := client.PostWithContext(ctx, createAccessTokenURL(client), nil, nil, &gophercloud.RequestOpts{ MoreHeaders: h, OkCodes: []int{201}, KeepResponseBody: true, @@ -451,20 +487,35 @@ func CreateAccessToken(client *gophercloud.ServiceClient, opts CreateAccessToken return } -// GetAccessToken retrieves details on a single OAuth1 access token by an ID. -func GetAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r GetAccessTokenResult) { - resp, err := client.Get(userAccessTokenURL(client, userID, id), &r.Body, nil) +// CreateAccessToken is a compatibility wrapper around CreateAccessTokenWithContext. +func CreateAccessToken(client *gophercloud.ServiceClient, opts CreateAccessTokenOptsBuilder) (r TokenResult) { + return CreateAccessTokenWithContext(context.Background(), client, opts) +} + +// GetAccessTokenWithContext retrieves details on a single OAuth1 access token by an ID. +func GetAccessTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, userID string, id string) (r GetAccessTokenResult) { + resp, err := client.GetWithContext(ctx, userAccessTokenURL(client, userID, id), &r.Body, nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// RevokeAccessToken revokes an OAuth1 access token. -func RevokeAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r RevokeAccessTokenResult) { - resp, err := client.Delete(userAccessTokenURL(client, userID, id), nil) +// GetAccessToken is a compatibility wrapper around GetAccessTokenWithContext. +func GetAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r GetAccessTokenResult) { + return GetAccessTokenWithContext(context.Background(), client, userID, id) +} + +// RevokeAccessTokenWithContext revokes an OAuth1 access token. +func RevokeAccessTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, userID string, id string) (r RevokeAccessTokenResult) { + resp, err := client.DeleteWithContext(ctx, userAccessTokenURL(client, userID, id), nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// RevokeAccessToken is a compatibility wrapper around RevokeAccessTokenWithContext. +func RevokeAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r RevokeAccessTokenResult) { + return RevokeAccessTokenWithContext(context.Background(), client, userID, id) +} + // ListAccessTokens enumerates authorized access tokens. func ListAccessTokens(client *gophercloud.ServiceClient, userID string) pagination.Pager { url := userAccessTokensURL(client, userID) @@ -481,14 +532,19 @@ func ListAccessTokenRoles(client *gophercloud.ServiceClient, userID string, id s }) } -// GetAccessTokenRole retrieves details on a single OAuth1 access token role by +// GetAccessTokenRoleWithContext retrieves details on a single OAuth1 access token role by // an ID. -func GetAccessTokenRole(client *gophercloud.ServiceClient, userID string, id string, roleID string) (r GetAccessTokenRoleResult) { - resp, err := client.Get(userAccessTokenRoleURL(client, userID, id, roleID), &r.Body, nil) +func GetAccessTokenRoleWithContext(ctx context.Context, client *gophercloud.ServiceClient, userID string, id string, roleID string) (r GetAccessTokenRoleResult) { + resp, err := client.GetWithContext(ctx, userAccessTokenRoleURL(client, userID, id, roleID), &r.Body, nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// GetAccessTokenRole is a compatibility wrapper around GetAccessTokenRoleWithContext. +func GetAccessTokenRole(client *gophercloud.ServiceClient, userID string, id string, roleID string) (r GetAccessTokenRoleResult) { + return GetAccessTokenRoleWithContext(context.Background(), client, userID, id, roleID) +} + // The following are small helper functions used to help build the signature. // buildOAuth1QueryString builds a URLEncoded parameters string specific for diff --git a/openstack/identity/v3/tokens/requests.go b/openstack/identity/v3/tokens/requests.go index 1af55d8137..d5b2fe83fd 100644 --- a/openstack/identity/v3/tokens/requests.go +++ b/openstack/identity/v3/tokens/requests.go @@ -1,6 +1,10 @@ package tokens -import "github.com/gophercloud/gophercloud" +import ( + "context" + + "github.com/gophercloud/gophercloud" +) // Scope allows a created token to be limited to a specific domain or project. type Scope struct { @@ -119,9 +123,9 @@ func subjectTokenHeaders(subjectToken string) map[string]string { } } -// Create authenticates and either generates a new token, or changes the Scope +// CreateWithContext authenticates and either generates a new token, or changes the Scope // of an existing token. -func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) { +func CreateWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) { scope, err := opts.ToTokenV3ScopeMap() if err != nil { r.Err = err @@ -134,16 +138,21 @@ func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResu return } - resp, err := c.Post(tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := c.PostWithContext(ctx, tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{ OmitHeaders: []string{"X-Auth-Token"}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// Get validates and retrieves information about another token. -func Get(c *gophercloud.ServiceClient, token string) (r GetResult) { - resp, err := c.Get(tokenURL(c), &r.Body, &gophercloud.RequestOpts{ +// Create is a compatibility wrapper around CreateWithContext +func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) { + return CreateWithContext(context.Background(), c, opts) +} + +// GetGetWithContext validates and retrieves information about another token. +func GetWithContext(ctx context.Context, c *gophercloud.ServiceClient, token string) (r GetResult) { + resp, err := c.GetWithContext(ctx, tokenURL(c), &r.Body, &gophercloud.RequestOpts{ MoreHeaders: subjectTokenHeaders(token), OkCodes: []int{200, 203}, }) @@ -151,9 +160,14 @@ func Get(c *gophercloud.ServiceClient, token string) (r GetResult) { return } -// Validate determines if a specified token is valid or not. -func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { - resp, err := c.Head(tokenURL(c), &gophercloud.RequestOpts{ +// Get is a compatibility wrapper around GetWithContext +func Get(c *gophercloud.ServiceClient, token string) (r GetResult) { + return GetWithContext(context.Background(), c, token) +} + +// ValidateWithContext determines if a specified token is valid or not. +func ValidateWithContext(ctx context.Context, c *gophercloud.ServiceClient, token string) (bool, error) { + resp, err := c.HeadWithContext(ctx, tokenURL(c), &gophercloud.RequestOpts{ MoreHeaders: subjectTokenHeaders(token), OkCodes: []int{200, 204, 404}, }) @@ -164,11 +178,21 @@ func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { return resp.StatusCode == 200 || resp.StatusCode == 204, nil } -// Revoke immediately makes specified token invalid. -func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) { - resp, err := c.Delete(tokenURL(c), &gophercloud.RequestOpts{ +// Validate is a compatibility wrapper around ValidateWithContext +func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { + return ValidateWithContext(context.Background(), c, token) +} + +// RevokeWithContext immediately makes specified token invalid. +func RevokeWithContext(ctx context.Context, c *gophercloud.ServiceClient, token string) (r RevokeResult) { + resp, err := c.DeleteWithContext(ctx, tokenURL(c), &gophercloud.RequestOpts{ MoreHeaders: subjectTokenHeaders(token), }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } + +// Revoke is a compatibility wrapper around RevokeWithContext +func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) { + return RevokeWithContext(context.Background(), c, token) +} From b8f25bcf0e63e86694f83f688a3fff660fcdd556 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Fri, 2 Feb 2024 21:00:22 +0100 Subject: [PATCH 066/118] client: Add WithContext functions Allow using a context to cancel and trace authentication calls. --- openstack/client.go | 123 +++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 53 deletions(-) diff --git a/openstack/client.go b/openstack/client.go index 81c907c35b..8c6173a264 100644 --- a/openstack/client.go +++ b/openstack/client.go @@ -1,6 +1,7 @@ package openstack import ( + "context" "fmt" "reflect" "strings" @@ -23,20 +24,18 @@ const ( v3 = "v3" ) -/* -NewClient prepares an unauthenticated ProviderClient instance. -Most users will probably prefer using the AuthenticatedClient function -instead. - -This is useful if you wish to explicitly control the version of the identity -service that's used for authentication explicitly, for example. - -A basic example of using this would be: - - ao, err := openstack.AuthOptionsFromEnv() - provider, err := openstack.NewClient(ao.IdentityEndpoint) - client, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{}) -*/ +// NewClient prepares an unauthenticated ProviderClient instance. +// Most users will probably prefer using the AuthenticatedClient function +// instead. +// +// This is useful if you wish to explicitly control the version of the identity +// service that's used for authentication explicitly, for example. +// +// A basic example of using this would be: +// +// ao, err := openstack.AuthOptionsFromEnv() +// provider, err := openstack.NewClient(ao.IdentityEndpoint) +// client, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{}) func NewClient(endpoint string) (*gophercloud.ProviderClient, error) { base, err := utils.BaseEndpoint(endpoint) if err != nil { @@ -54,42 +53,45 @@ func NewClient(endpoint string) (*gophercloud.ProviderClient, error) { return p, nil } -/* -AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint -specified by the options, acquires a token, and returns a Provider Client -instance that's ready to operate. - -If the full path to a versioned identity endpoint was specified (example: -http://example.com:5000/v3), that path will be used as the endpoint to query. - -If a versionless endpoint was specified (example: http://example.com:5000/), -the endpoint will be queried to determine which versions of the identity service -are available, then chooses the most recent or most supported version. - -Example: - - ao, err := openstack.AuthOptionsFromEnv() - provider, err := openstack.AuthenticatedClient(ao) - client, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{ - Region: os.Getenv("OS_REGION_NAME"), - }) -*/ -func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) { +// AuthenticatedClientWithContext logs in to an OpenStack cloud found at the identity endpoint +// specified by the options, acquires a token, and returns a Provider Client +// instance that's ready to operate. +// +// If the full path to a versioned identity endpoint was specified (example: +// http://example.com:5000/v3), that path will be used as the endpoint to query. +// +// If a versionless endpoint was specified (example: http://example.com:5000/), +// the endpoint will be queried to determine which versions of the identity service +// are available, then chooses the most recent or most supported version. +// +// Example: +// +// ao, err := openstack.AuthOptionsFromEnv() +// provider, err := openstack.AuthenticatedClientWithContext(ctx, ao) +// client, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{ +// Region: os.Getenv("OS_REGION_NAME"), +// }) +func AuthenticatedClientWithContext(ctx context.Context, options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) { client, err := NewClient(options.IdentityEndpoint) if err != nil { return nil, err } - err = Authenticate(client, options) + err = AuthenticateWithContext(ctx, client, options) if err != nil { return nil, err } return client, nil } -// Authenticate or re-authenticate against the most recent identity service -// supported at the provided endpoint. -func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { +// AuthenticatedClient is a compatibility wrapper around AuthenticatedClientWithContext +func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) { + return AuthenticatedClientWithContext(context.Background(), options) +} + +// AuthenticateWithContext authenticates or re-authenticates against the most +// recent identity service supported at the provided endpoint. +func AuthenticateWithContext(ctx context.Context, client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { versions := []*utils.Version{ {ID: v2, Priority: 20, Suffix: "/v2.0/"}, {ID: v3, Priority: 30, Suffix: "/v3/"}, @@ -102,21 +104,31 @@ func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOp switch chosen.ID { case v2: - return v2auth(client, endpoint, options, gophercloud.EndpointOpts{}) + return v2auth(ctx, client, endpoint, options, gophercloud.EndpointOpts{}) case v3: - return v3auth(client, endpoint, &options, gophercloud.EndpointOpts{}) + return v3auth(ctx, client, endpoint, &options, gophercloud.EndpointOpts{}) default: // The switch statement must be out of date from the versions list. return fmt.Errorf("Unrecognized identity version: %s", chosen.ID) } } -// AuthenticateV2 explicitly authenticates against the identity v2 endpoint. +// Authenticate is a compatibility wrapper around AuthenticateWithContext. +func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { + return AuthenticateWithContext(context.Background(), client, options) +} + +// AuthenticateV2WithContext explicitly authenticates against the identity v2 endpoint. +func AuthenticateV2WithContext(ctx context.Context, client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { + return v2auth(ctx, client, "", options, eo) +} + +// AuthenticateV2 is a compatibility wrapper around AuthenticateV2WithContext. func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { - return v2auth(client, "", options, eo) + return AuthenticateV2WithContext(context.Background(), client, options, eo) } -func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { +func v2auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { v2Client, err := NewIdentityV2(client, eo) if err != nil { return err @@ -136,7 +148,7 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc TokenID: options.TokenID, } - result := tokens2.Create(v2Client, v2Opts) + result := tokens2.CreateWithContext(ctx, v2Client, v2Opts) err = client.SetTokenAndAuthResult(result) if err != nil { @@ -159,7 +171,7 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc tao := options tao.AllowReauth = false client.ReauthFunc = func() error { - err := v2auth(&tac, endpoint, tao, eo) + err := v2auth(ctx, &tac, endpoint, tao, eo) if err != nil { return err } @@ -174,12 +186,17 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc return nil } -// AuthenticateV3 explicitly authenticates against the identity v3 service. +// AuthenticateV3WithContext explicitly authenticates against the identity v3 service. +func AuthenticateV3WithContext(ctx context.Context, client *gophercloud.ProviderClient, options tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { + return v3auth(ctx, client, "", options, eo) +} + +// AuthenticateV3 is a compatibility wrapper around AuthenticateV3WithContext func AuthenticateV3(client *gophercloud.ProviderClient, options tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { - return v3auth(client, "", options, eo) + return AuthenticateV3WithContext(context.Background(), client, options, eo) } -func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { +func v3auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint string, opts tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { // Override the generated service endpoint with the one returned by the version endpoint. v3Client, err := NewIdentityV3(client, eo) if err != nil { @@ -229,11 +246,11 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au var result tokens3.CreateResult switch opts.(type) { case *ec2tokens.AuthOptions: - result = ec2tokens.Create(v3Client, opts) + result = ec2tokens.CreateWithContext(ctx, v3Client, opts) case *oauth1.AuthOptions: - result = oauth1.Create(v3Client, opts) + result = oauth1.CreateWithContext(ctx, v3Client, opts) default: - result = tokens3.Create(v3Client, opts) + result = tokens3.CreateWithContext(ctx, v3Client, opts) } err = client.SetTokenAndAuthResult(result) @@ -277,7 +294,7 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au tao = opts } client.ReauthFunc = func() error { - err := v3auth(&tac, endpoint, tao, eo) + err := v3auth(ctx, &tac, endpoint, tao, eo) if err != nil { return err } From 2dbf414e62b9b5f7d4080ef02119c8112097384d Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Fri, 2 Feb 2024 18:50:56 +0100 Subject: [PATCH 067/118] pager: Add WithContext functions to enable dependant packages to build ListWithContext. --- pagination/http.go | 12 +++++++++--- pagination/pager.go | 34 ++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/pagination/http.go b/pagination/http.go index 7845cda13b..13b3925232 100644 --- a/pagination/http.go +++ b/pagination/http.go @@ -1,6 +1,7 @@ package pagination import ( + "context" "encoding/json" "io/ioutil" "net/http" @@ -52,11 +53,16 @@ func PageResultFromParsed(resp *http.Response, body interface{}) PageResult { } } -// Request performs an HTTP request and extracts the http.Response from the result. -func Request(client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) { - return client.Get(url, nil, &gophercloud.RequestOpts{ +// RequestWithContext performs an HTTP request and extracts the http.Response from the result. +func RequestWithContext(ctx context.Context, client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) { + return client.GetWithContext(ctx, url, nil, &gophercloud.RequestOpts{ MoreHeaders: headers, OkCodes: []int{200, 204, 300}, KeepResponseBody: true, }) } + +// Request is a compatibility wrapper around RequestWithContext. +func Request(client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) { + return RequestWithContext(context.Background(), client, headers, url) +} diff --git a/pagination/pager.go b/pagination/pager.go index 1dec2703eb..8bc6680804 100644 --- a/pagination/pager.go +++ b/pagination/pager.go @@ -1,6 +1,7 @@ package pagination import ( + "context" "errors" "fmt" "net/http" @@ -69,8 +70,8 @@ func (p Pager) WithPageCreator(createPage func(r PageResult) Page) Pager { } } -func (p Pager) fetchNextPage(url string) (Page, error) { - resp, err := Request(p.client, p.Headers, url) +func (p Pager) fetchNextPage(ctx context.Context, url string) (Page, error) { + resp, err := RequestWithContext(ctx, p.client, p.Headers, url) if err != nil { return nil, err } @@ -83,9 +84,10 @@ func (p Pager) fetchNextPage(url string) (Page, error) { return p.createPage(remembered), nil } -// EachPage iterates over each page returned by a Pager, yielding one at a time to a handler function. -// Return "false" from the handler to prematurely stop iterating. -func (p Pager) EachPage(handler func(Page) (bool, error)) error { +// EachPageWithContext iterates over each page returned by a Pager, yielding +// one at a time to a handler function. Return "false" from the handler to +// prematurely stop iterating. +func (p Pager) EachPageWithContext(ctx context.Context, handler func(context.Context, Page) (bool, error)) error { if p.Err != nil { return p.Err } @@ -99,7 +101,7 @@ func (p Pager) EachPage(handler func(Page) (bool, error)) error { p.firstPage = nil } else { var err error - currentPage, err = p.fetchNextPage(currentURL) + currentPage, err = p.fetchNextPage(ctx, currentURL) if err != nil { return err } @@ -113,7 +115,7 @@ func (p Pager) EachPage(handler func(Page) (bool, error)) error { return nil } - ok, err := handler(currentPage) + ok, err := handler(ctx, currentPage) if err != nil { return err } @@ -131,9 +133,16 @@ func (p Pager) EachPage(handler func(Page) (bool, error)) error { } } -// AllPages returns all the pages from a `List` operation in a single page, +// EachPage is a compatibility wrapper around EachPageWithContext. +func (p Pager) EachPage(handler func(Page) (bool, error)) error { + return p.EachPageWithContext(context.Background(), func(_ context.Context, p Page) (bool, error) { + return handler(p) + }) +} + +// AllPagesWithContext returns all the pages from a `List` operation in a single page, // allowing the user to retrieve all the pages at once. -func (p Pager) AllPages() (Page, error) { +func (p Pager) AllPagesWithContext(ctx context.Context) (Page, error) { if p.Err != nil { return nil, p.Err } @@ -143,7 +152,7 @@ func (p Pager) AllPages() (Page, error) { var body reflect.Value // Grab a first page to ascertain the page body type. - firstPage, err := p.fetchNextPage(p.initialURL) + firstPage, err := p.fetchNextPage(ctx, p.initialURL) if err != nil { return nil, err } @@ -252,3 +261,8 @@ func (p Pager) AllPages() (Page, error) { // `Extract*` methods will work. return page.Elem().Interface().(Page), err } + +// AllPages is a compatibility wrapper around AllPagesWithContext. +func (p Pager) AllPages() (Page, error) { + return p.AllPagesWithContext(context.Background()) +} From 22c56829f05af19f3ab422ff1b8b9db2000789f9 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Mon, 29 Jan 2024 10:38:23 +0100 Subject: [PATCH 068/118] Authenticate with a clouds.yaml This commit imports the clouds.yaml parsing code from the utils module, and exposes it in a way that fits the natural Gophercloud authentication flow. Unlike the code from utils, this new `clouds.Parse` function keeps the separation between the ProviderClient (holding the cloud coordinates and a Keystone token) and the ServiceClient (holding specific endpoint configuration). By default, `clouds.Parse` fetches its configuration from the environment, just like the openstack client would do. Example use: ```Go func main() { ctx := context.Background() ao, eo, tlsConfig, err := clouds.Parse() if err != nil { panic(err) } providerClient, err := config.NewProviderClient(ctx, ao, config.WithTLSConfig(tlsConfig)) if err != nil { panic(err) } networkClient, err := openstack.NewNetworkV2(providerClient, eo) if err != nil { panic(err) } } ``` The `clouds.Parse` function accepts several functional options that can modify its behaviour. For example, to use a `clouds.yaml` that exists in a non-standard path: ```Go ao, eo, tlsConfig, err := clouds.Parse(clouds.WithLocations("/my/path/clouds2.yaml")) ``` It is also possible to pass a reader directly. Note that any number of options can be passed, with each of them taking precedence of the previous if there is conflict. ```Go const exampleClouds = `clouds: openstack: auth: auth_url: https://example.com:13000` ao, eo, tlsConfig, err := clouds.Parse( clouds.WithCloudsYAML(strings.NewReader(exampleClouds)), clouds.WithIdentityEndpoint("https://example.com:13001"), clouds.WithCloudName("osp1"), clouds.WithUsername("alice"), ) ``` --- openstack/config/clouds/clouds.go | 271 +++++++++++++++++++++++++ openstack/config/clouds/clouds_test.go | 64 ++++++ openstack/config/clouds/options.go | 188 +++++++++++++++++ openstack/config/clouds/tls.go | 88 ++++++++ openstack/config/clouds/types.go | 203 ++++++++++++++++++ openstack/config/provider_client.go | 70 +++++++ 6 files changed, 884 insertions(+) create mode 100644 openstack/config/clouds/clouds.go create mode 100644 openstack/config/clouds/clouds_test.go create mode 100644 openstack/config/clouds/options.go create mode 100644 openstack/config/clouds/tls.go create mode 100644 openstack/config/clouds/types.go create mode 100644 openstack/config/provider_client.go diff --git a/openstack/config/clouds/clouds.go b/openstack/config/clouds/clouds.go new file mode 100644 index 0000000000..b04416e68d --- /dev/null +++ b/openstack/config/clouds/clouds.go @@ -0,0 +1,271 @@ +// package clouds provides a parser for OpenStack credentials stored in a clouds.yaml file. +// +// Example use: +// +// ctx := context.Background() +// ao, eo, tlsConfig, err := clouds.Parse() +// if err != nil { +// panic(err) +// } +// +// providerClient, err := config.NewProviderClient(ctx, ao, config.WithTLSConfig(tlsConfig)) +// if err != nil { +// panic(err) +// } +// +// networkClient, err := openstack.NewNetworkV2(providerClient, eo) +// if err != nil { +// panic(err) +// } +package clouds + +import ( + "crypto/tls" + "encoding/json" + "errors" + "fmt" + "os" + "path" + "reflect" + + "github.com/gophercloud/gophercloud" + "gopkg.in/yaml.v2" +) + +// Parse fetches a clouds.yaml file from disk and returns the parsed +// credentials. +// +// By default this function mimics the behaviour of python-openstackclient, which is: +// +// - if the environment variable `OS_CLIENT_CONFIG_FILE` is set and points to a +// clouds.yaml, use that location as the only search location for `clouds.yaml` and `secure.yaml`; +// - otherwise, the search locations for `clouds.yaml` and `secure.yaml` are: +// 1. the current working directory (on Linux: `./`) +// 2. the directory `openstack` under the standatd user config location for +// the operating system (on Linux: `${XDG_CONFIG_HOME:-$HOME/.config}/openstack/`) +// 3. on Linux, `/etc/openstack/` +// +// Once `clouds.yaml` is found in a search location, the same location is used to search for `secure.yaml`. +// +// Like in python-openstackclient, relative paths in the `clouds.yaml` section +// `cacert` are interpreted as relative the the current directory, and not to +// the `clouds.yaml` location. +// +// Search locations, as well as individual `clouds.yaml` properties, can be +// overwritten with functional options. +func Parse(opts ...func(*cloudOpts)) (gophercloud.AuthOptions, gophercloud.EndpointOpts, *tls.Config, error) { + options := cloudOpts{ + cloudName: os.Getenv("OS_CLOUD"), + region: os.Getenv("OS_REGION_NAME"), + endpointType: os.Getenv("OS_INTERFACE"), + locations: func() []string { + if path := os.Getenv("OS_CLIENT_CONFIG_FILE"); path != "" { + return []string{path} + } + return nil + }(), + } + + for _, apply := range opts { + apply(&options) + } + + if options.cloudName == "" { + return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("the empty string \"\" is not a valid cloud name") + } + + // Set the defaults and open the files for reading. This code only runs + // if no override has been set, because it is fallible. + if options.cloudsyamlReader == nil { + if len(options.locations) < 1 { + cwd, err := os.Getwd() + if err != nil { + return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("failed to get the current working directory: %w", err) + } + userConfig, err := os.UserConfigDir() + if err != nil { + return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("failed to get the user config directory: %w", err) + } + options.locations = []string{path.Join(cwd, "clouds.yaml"), path.Join(userConfig, "openstack", "clouds.yaml"), path.Join("/etc", "openstack")} + } + + for _, cloudsPath := range options.locations { + var errNotFound *os.PathError + f, err := os.Open(cloudsPath) + if err != nil && !errors.As(err, &errNotFound) { + return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("failed to open %q: %w", cloudsPath, err) + } + if err == nil { + defer f.Close() + options.cloudsyamlReader = f + + if options.secureyamlReader == nil { + securePath := path.Join(path.Base(cloudsPath), "secure.yaml") + secureF, err := os.Open(securePath) + if err != nil && !errors.As(err, &errNotFound) { + return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("failed to open %q: %w", securePath, err) + } + if err == nil { + defer secureF.Close() + options.secureyamlReader = secureF + } + } + } + } + if options.cloudsyamlReader == nil { + return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("clouds file not found. Search locations were: %v", options.locations) + } + } + + // Parse the YAML payloads. + var clouds Clouds + if err := yaml.NewDecoder(options.cloudsyamlReader).Decode(&clouds); err != nil { + return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, err + } + + cloud, ok := clouds.Clouds[options.cloudName] + if !ok { + return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("cloud %q not found in clouds.yaml", options.cloudName) + } + + if options.secureyamlReader != nil { + var secureClouds Clouds + if err := yaml.NewDecoder(options.secureyamlReader).Decode(&secureClouds); err != nil { + return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("failed to parse secure.yaml: %w", err) + } + + if secureCloud, ok := secureClouds.Clouds[options.cloudName]; ok { + // If secureCloud has content and it differs from the cloud entry, + // merge the two together. + if !reflect.DeepEqual((gophercloud.AuthOptions{}), secureClouds) && !reflect.DeepEqual(clouds, secureClouds) { + var err error + cloud, err = mergeClouds(secureCloud, cloud) + if err != nil { + return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("unable to merge information from clouds.yaml and secure.yaml") + } + } + } + } + + tlsConfig, err := computeTLSConfig(cloud, options) + if err != nil { + return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("unable to compute TLS configuration: %w", err) + } + + endpointType := coalesce(options.endpointType, cloud.EndpointType, cloud.Interface) + + return gophercloud.AuthOptions{ + IdentityEndpoint: coalesce(options.authURL, cloud.AuthInfo.AuthURL), + Username: coalesce(options.username, cloud.AuthInfo.Username), + UserID: coalesce(options.userID, cloud.AuthInfo.UserID), + Password: coalesce(options.password, cloud.AuthInfo.Password), + DomainID: coalesce(options.domainID, cloud.AuthInfo.UserDomainID, cloud.AuthInfo.ProjectDomainID, cloud.AuthInfo.DomainID), + DomainName: coalesce(options.domainName, cloud.AuthInfo.UserDomainName, cloud.AuthInfo.ProjectDomainName, cloud.AuthInfo.DomainName), + TenantID: coalesce(options.projectID, cloud.AuthInfo.ProjectID), + TenantName: coalesce(options.projectName, cloud.AuthInfo.ProjectName), + TokenID: coalesce(options.token, cloud.AuthInfo.Token), + Scope: options.scope, + ApplicationCredentialID: coalesce(options.applicationCredentialID, cloud.AuthInfo.ApplicationCredentialID), + ApplicationCredentialName: coalesce(options.applicationCredentialName, cloud.AuthInfo.ApplicationCredentialName), + ApplicationCredentialSecret: coalesce(options.applicationCredentialSecret, cloud.AuthInfo.ApplicationCredentialSecret), + }, gophercloud.EndpointOpts{ + Region: coalesce(options.region, cloud.RegionName), + Availability: computeAvailability(endpointType), + }, + tlsConfig, + nil +} + +// computeAvailability is a helper method to determine the endpoint type +// requested by the user. +func computeAvailability(endpointType string) gophercloud.Availability { + if endpointType == "internal" || endpointType == "internalURL" { + return gophercloud.AvailabilityInternal + } + if endpointType == "admin" || endpointType == "adminURL" { + return gophercloud.AvailabilityAdmin + } + return gophercloud.AvailabilityPublic +} + +// coalesce returns the first argument that is not the empty string, or the +// empty string. +func coalesce(items ...string) string { + for _, item := range items { + if item != "" { + return item + } + } + return "" +} + +// mergeClouds merges two Clouds recursively (the AuthInfo also gets merged). +// In case both Clouds define a value, the value in the 'override' cloud takes precedence +func mergeClouds(override, cloud Cloud) (Cloud, error) { + overrideJson, err := json.Marshal(override) + if err != nil { + return Cloud{}, err + } + cloudJson, err := json.Marshal(cloud) + if err != nil { + return Cloud{}, err + } + var overrideInterface interface{} + err = json.Unmarshal(overrideJson, &overrideInterface) + if err != nil { + return Cloud{}, err + } + var cloudInterface interface{} + err = json.Unmarshal(cloudJson, &cloudInterface) + if err != nil { + return Cloud{}, err + } + var mergedCloud Cloud + mergedInterface := mergeInterfaces(overrideInterface, cloudInterface) + mergedJson, err := json.Marshal(mergedInterface) + err = json.Unmarshal(mergedJson, &mergedCloud) + if err != nil { + return Cloud{}, err + } + return mergedCloud, nil +} + +// merges two interfaces. In cases where a value is defined for both 'overridingInterface' and +// 'inferiorInterface' the value in 'overridingInterface' will take precedence. +func mergeInterfaces(overridingInterface, inferiorInterface interface{}) interface{} { + switch overriding := overridingInterface.(type) { + case map[string]interface{}: + interfaceMap, ok := inferiorInterface.(map[string]interface{}) + if !ok { + return overriding + } + for k, v := range interfaceMap { + if overridingValue, ok := overriding[k]; ok { + overriding[k] = mergeInterfaces(overridingValue, v) + } else { + overriding[k] = v + } + } + case []interface{}: + list, ok := inferiorInterface.([]interface{}) + if !ok { + return overriding + } + for i := range list { + overriding = append(overriding, list[i]) + } + return overriding + case nil: + // mergeClouds(nil, map[string]interface{...}) -> map[string]interface{...} + v, ok := inferiorInterface.(map[string]interface{}) + if ok { + return v + } + } + // We don't want to override with empty values + if reflect.DeepEqual(overridingInterface, nil) || reflect.DeepEqual(reflect.Zero(reflect.TypeOf(overridingInterface)).Interface(), overridingInterface) { + return inferiorInterface + } else { + return overridingInterface + } +} diff --git a/openstack/config/clouds/clouds_test.go b/openstack/config/clouds/clouds_test.go new file mode 100644 index 0000000000..e25bae0122 --- /dev/null +++ b/openstack/config/clouds/clouds_test.go @@ -0,0 +1,64 @@ +package clouds_test + +import ( + "fmt" + "strings" + + "github.com/gophercloud/gophercloud/openstack/config/clouds" +) + +func ExampleWithCloudName() { + const exampleClouds = `clouds: + openstack: + auth: + auth_url: https://example.com:13000` + + ao, _, _, err := clouds.Parse( + clouds.WithCloudsYAML(strings.NewReader(exampleClouds)), + clouds.WithCloudName("openstack"), + ) + if err != nil { + panic(err) + } + + fmt.Println(ao.IdentityEndpoint) + // Output: https://example.com:13000 +} + +func ExampleWithUserID() { + const exampleClouds = `clouds: + openstack: + auth: + auth_url: https://example.com:13000` + + ao, _, _, err := clouds.Parse( + clouds.WithCloudsYAML(strings.NewReader(exampleClouds)), + clouds.WithCloudName("openstack"), + clouds.WithUsername("Kris"), + ) + if err != nil { + panic(err) + } + + fmt.Println(ao.Username) + // Output: Kris +} + +func ExampleWithRegion() { + const exampleClouds = `clouds: + openstack: + auth: + auth_url: https://example.com:13000` + + _, eo, _, err := clouds.Parse( + clouds.WithCloudsYAML(strings.NewReader(exampleClouds)), + clouds.WithCloudName("openstack"), + clouds.WithRegion("mars"), + ) + if err != nil { + panic(err) + } + + fmt.Println(eo.Region) + // Output: mars +} diff --git a/openstack/config/clouds/options.go b/openstack/config/clouds/options.go new file mode 100644 index 0000000000..30bf6a2ef3 --- /dev/null +++ b/openstack/config/clouds/options.go @@ -0,0 +1,188 @@ +package clouds + +import ( + "io" + + "github.com/gophercloud/gophercloud" +) + +type cloudOpts struct { + cloudName string + locations []string + cloudsyamlReader io.Reader + secureyamlReader io.Reader + + applicationCredentialID string + applicationCredentialName string + applicationCredentialSecret string + authURL string + domainID string + domainName string + endpointType string + password string + projectID string + projectName string + region string + scope *gophercloud.AuthScope + token string + userID string + username string + + caCertPath string + clientCertPath string + clientKeyPath string + insecure *bool +} + +// WithCloudName allows to override the environment variable `OS_CLOUD`. +func WithCloudName(osCloud string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.cloudName = osCloud + } +} + +// WithLocations is a functional option that sets the search locations for the +// clouds.yaml file (and its optional companion secure.yaml). Each location is +// a file path pointing to a possible `clouds.yaml`. +func WithLocations(locations ...string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.locations = locations + } +} + +// WithCloudsYAML is a functional option that lets you pass a clouds.yaml file +// as an io.Reader interface. When this option is passed, FromCloudsYaml will +// not attempt to fetch any file from the file system. To add a secure.yaml, +// use in conjunction with WithSecureYAML. +func WithCloudsYAML(clouds io.Reader) func(*cloudOpts) { + return func(co *cloudOpts) { + co.cloudsyamlReader = clouds + } +} + +// WithSecureYAML is a functional option that lets you pass a secure.yaml file +// as an io.Reader interface, to complement the clouds.yaml that is either +// fetched from the filesystem, or passed with WithCloudsYAML. +func WithSecureYAML(secure io.Reader) func(*cloudOpts) { + return func(co *cloudOpts) { + co.secureyamlReader = secure + } +} + +func WithApplicationCredentialID(applicationCredentialID string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.applicationCredentialID = applicationCredentialID + } +} + +func WithApplicationCredentialName(applicationCredentialName string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.applicationCredentialName = applicationCredentialName + } +} + +func WithApplicationCredentialSecret(applicationCredentialSecret string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.applicationCredentialSecret = applicationCredentialSecret + } +} + +func WithIdentityEndpoint(authURL string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.authURL = authURL + } +} + +func WithDomainID(domainID string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.domainID = domainID + } +} + +func WithDomainName(domainName string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.domainName = domainName + } +} + +// WithRegion allows to override the endpoint type set in clouds.yaml or in the +// environment variable `OS_INTERFACE`. +func WithEndpointType(endpointType string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.endpointType = endpointType + } +} + +func WithPassword(password string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.password = password + } +} + +func WithProjectID(projectID string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.projectID = projectID + } +} + +func WithProjectName(projectName string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.projectName = projectName + } +} + +// WithRegion allows to override the region set in clouds.yaml or in the +// environment variable `OS_REGION_NAME` +func WithRegion(region string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.region = region + } +} + +func WithScope(scope *gophercloud.AuthScope) func(*cloudOpts) { + return func(co *cloudOpts) { + co.scope = scope + } +} + +func WithToken(token string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.token = token + } +} + +func WithUserID(userID string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.userID = userID + } +} + +func WithUsername(username string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.username = username + } +} + +func WithCACertPath(caCertPath string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.caCertPath = caCertPath + } +} + +func WithClientCertPath(clientCertPath string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.clientCertPath = clientCertPath + } +} + +func WithClientKeyPath(clientKeyPath string) func(*cloudOpts) { + return func(co *cloudOpts) { + co.clientKeyPath = clientKeyPath + } +} + +func WithInsecure(insecure bool) func(*cloudOpts) { + return func(co *cloudOpts) { + co.insecure = &insecure + } +} diff --git a/openstack/config/clouds/tls.go b/openstack/config/clouds/tls.go new file mode 100644 index 0000000000..460ede6d04 --- /dev/null +++ b/openstack/config/clouds/tls.go @@ -0,0 +1,88 @@ +package clouds + +import ( + "bytes" + "crypto/tls" + "crypto/x509" + "fmt" + "io/ioutil" + "os" + "path" + "strings" +) + +func computeTLSConfig(cloud Cloud, options cloudOpts) (*tls.Config, error) { + tlsConfig := new(tls.Config) + if caCertPath := coalesce(options.caCertPath, os.Getenv("OS_CACERT"), cloud.CACertFile); caCertPath != "" { + caCertPath, err := resolveTilde(caCertPath) + if err != nil { + return nil, fmt.Errorf("failed to resolve user home directory: %w", err) + } + + caCert, err := ioutil.ReadFile(caCertPath) + if err != nil { + return nil, fmt.Errorf("failed to open the CA cert file: %w", err) + } + + caCertPool := x509.NewCertPool() + if ok := caCertPool.AppendCertsFromPEM(bytes.TrimSpace(caCert)); !ok { + return nil, fmt.Errorf("failed to parse the CA Cert from %q", caCertPath) + } + tlsConfig.RootCAs = caCertPool + } + + tlsConfig.InsecureSkipVerify = func() bool { + if options.insecure != nil { + return *options.insecure + } + if cloud.Verify != nil { + return !*cloud.Verify + } + return false + }() + + if clientCertPath, clientKeyPath := coalesce(options.clientCertPath, os.Getenv("OS_CERT"), cloud.ClientCertFile), coalesce(options.clientKeyPath, os.Getenv("OS_KEY"), cloud.ClientKeyFile); clientCertPath != "" && clientKeyPath != "" { + clientCertPath, err := resolveTilde(clientCertPath) + if err != nil { + return nil, fmt.Errorf("failed to resolve user home directory in client cert path: %w", err) + } + clientKeyPath, err := resolveTilde(clientKeyPath) + if err != nil { + return nil, fmt.Errorf("failed to resolve user home directory in client cert key path: %w", err) + } + + clientCert, err := ioutil.ReadFile(clientCertPath) + if err != nil { + return nil, fmt.Errorf("failed to read the client cert file: %w", err) + } + + clientKey, err := ioutil.ReadFile(clientKeyPath) + if err != nil { + return nil, fmt.Errorf("failed to read the client cert key file: %w", err) + } + + cert, err := tls.X509KeyPair(clientCert, clientKey) + if err != nil { + return nil, err + } + + tlsConfig.Certificates = []tls.Certificate{cert} + } else if clientCertPath != "" && clientKeyPath == "" { + return nil, fmt.Errorf("client cert is set, but client cert key is missing") + } else if clientCertPath == "" && clientKeyPath != "" { + return nil, fmt.Errorf("client cert key is set, but client cert is missing") + } + + return tlsConfig, nil +} + +func resolveTilde(p string) (string, error) { + if after := strings.TrimPrefix(p, "~/"); after != p { + h, err := os.UserHomeDir() + if err != nil { + return "", fmt.Errorf("failed to resolve user home directory: %w", err) + } + return path.Join(h, after), nil + } + return p, nil +} diff --git a/openstack/config/clouds/types.go b/openstack/config/clouds/types.go new file mode 100644 index 0000000000..c1914633ff --- /dev/null +++ b/openstack/config/clouds/types.go @@ -0,0 +1,203 @@ +package clouds + +import "encoding/json" + +// Clouds represents a collection of Cloud entries in a clouds.yaml file. +// The format of clouds.yaml is documented at +// https://docs.openstack.org/os-client-config/latest/user/configuration.html. +type Clouds struct { + Clouds map[string]Cloud `yaml:"clouds" json:"clouds"` +} + +// Cloud represents an entry in a clouds.yaml/public-clouds.yaml/secure.yaml file. +type Cloud struct { + Cloud string `yaml:"cloud,omitempty" json:"cloud,omitempty"` + Profile string `yaml:"profile,omitempty" json:"profile,omitempty"` + AuthInfo *AuthInfo `yaml:"auth,omitempty" json:"auth,omitempty"` + AuthType AuthType `yaml:"auth_type,omitempty" json:"auth_type,omitempty"` + RegionName string `yaml:"region_name,omitempty" json:"region_name,omitempty"` + Regions []Region `yaml:"regions,omitempty" json:"regions,omitempty"` + + // EndpointType and Interface both specify whether to use the public, internal, + // or admin interface of a service. They should be considered synonymous, but + // EndpointType will take precedence when both are specified. + EndpointType string `yaml:"endpoint_type,omitempty" json:"endpoint_type,omitempty"` + Interface string `yaml:"interface,omitempty" json:"interface,omitempty"` + + // API Version overrides. + IdentityAPIVersion string `yaml:"identity_api_version,omitempty" json:"identity_api_version,omitempty"` + VolumeAPIVersion string `yaml:"volume_api_version,omitempty" json:"volume_api_version,omitempty"` + + // Verify whether or not SSL API requests should be verified. + Verify *bool `yaml:"verify,omitempty" json:"verify,omitempty"` + + // CACertFile a path to a CA Cert bundle that can be used as part of + // verifying SSL API requests. + CACertFile string `yaml:"cacert,omitempty" json:"cacert,omitempty"` + + // ClientCertFile a path to a client certificate to use as part of the SSL + // transaction. + ClientCertFile string `yaml:"cert,omitempty" json:"cert,omitempty"` + + // ClientKeyFile a path to a client key to use as part of the SSL + // transaction. + ClientKeyFile string `yaml:"key,omitempty" json:"key,omitempty"` +} + +// AuthInfo represents the auth section of a cloud entry or +// auth options entered explicitly in ClientOpts. +type AuthInfo struct { + // AuthURL is the keystone/identity endpoint URL. + AuthURL string `yaml:"auth_url,omitempty" json:"auth_url,omitempty"` + + // Token is a pre-generated authentication token. + Token string `yaml:"token,omitempty" json:"token,omitempty"` + + // Username is the username of the user. + Username string `yaml:"username,omitempty" json:"username,omitempty"` + + // UserID is the unique ID of a user. + UserID string `yaml:"user_id,omitempty" json:"user_id,omitempty"` + + // Password is the password of the user. + Password string `yaml:"password,omitempty" json:"password,omitempty"` + + // Application Credential ID to login with. + ApplicationCredentialID string `yaml:"application_credential_id,omitempty" json:"application_credential_id,omitempty"` + + // Application Credential name to login with. + ApplicationCredentialName string `yaml:"application_credential_name,omitempty" json:"application_credential_name,omitempty"` + + // Application Credential secret to login with. + ApplicationCredentialSecret string `yaml:"application_credential_secret,omitempty" json:"application_credential_secret,omitempty"` + + // SystemScope is a system information to scope to. + SystemScope string `yaml:"system_scope,omitempty" json:"system_scope,omitempty"` + + // ProjectName is the common/human-readable name of a project. + // Users can be scoped to a project. + // ProjectName on its own is not enough to ensure a unique scope. It must + // also be combined with either a ProjectDomainName or ProjectDomainID. + // ProjectName cannot be combined with ProjectID in a scope. + ProjectName string `yaml:"project_name,omitempty" json:"project_name,omitempty"` + + // ProjectID is the unique ID of a project. + // It can be used to scope a user to a specific project. + ProjectID string `yaml:"project_id,omitempty" json:"project_id,omitempty"` + + // UserDomainName is the name of the domain where a user resides. + // It is used to identify the source domain of a user. + UserDomainName string `yaml:"user_domain_name,omitempty" json:"user_domain_name,omitempty"` + + // UserDomainID is the unique ID of the domain where a user resides. + // It is used to identify the source domain of a user. + UserDomainID string `yaml:"user_domain_id,omitempty" json:"user_domain_id,omitempty"` + + // ProjectDomainName is the name of the domain where a project resides. + // It is used to identify the source domain of a project. + // ProjectDomainName can be used in addition to a ProjectName when scoping + // a user to a specific project. + ProjectDomainName string `yaml:"project_domain_name,omitempty" json:"project_domain_name,omitempty"` + + // ProjectDomainID is the name of the domain where a project resides. + // It is used to identify the source domain of a project. + // ProjectDomainID can be used in addition to a ProjectName when scoping + // a user to a specific project. + ProjectDomainID string `yaml:"project_domain_id,omitempty" json:"project_domain_id,omitempty"` + + // DomainName is the name of a domain which can be used to identify the + // source domain of either a user or a project. + // If UserDomainName and ProjectDomainName are not specified, then DomainName + // is used as a default choice. + // It can also be used be used to specify a domain-only scope. + DomainName string `yaml:"domain_name,omitempty" json:"domain_name,omitempty"` + + // DomainID is the unique ID of a domain which can be used to identify the + // source domain of eitehr a user or a project. + // If UserDomainID and ProjectDomainID are not specified, then DomainID is + // used as a default choice. + // It can also be used be used to specify a domain-only scope. + DomainID string `yaml:"domain_id,omitempty" json:"domain_id,omitempty"` + + // DefaultDomain is the domain ID to fall back on if no other domain has + // been specified and a domain is required for scope. + DefaultDomain string `yaml:"default_domain,omitempty" json:"default_domain,omitempty"` + + // AllowReauth should be set to true if you grant permission for Gophercloud to + // cache your credentials in memory, and to allow Gophercloud to attempt to + // re-authenticate automatically if/when your token expires. If you set it to + // false, it will not cache these settings, but re-authentication will not be + // possible. This setting defaults to false. + AllowReauth bool `yaml:"allow_reauth,omitempty" json:"allow_reauth,omitempty"` +} + +// Region represents a region included as part of cloud in clouds.yaml +// According to Python-based openstacksdk, this can be either a struct (as defined) +// or a plain string. Custom unmarshallers handle both cases. +type Region struct { + Name string `yaml:"name,omitempty" json:"name,omitempty"` + Values Cloud `yaml:"values,omitempty" json:"values,omitempty"` +} + +// UnmarshalJSON handles either a plain string acting as the Name property or +// a struct, mimicking the Python-based openstacksdk. +func (r *Region) UnmarshalJSON(data []byte) error { + var name string + if err := json.Unmarshal(data, &name); err == nil { + r.Name = name + return nil + } + + type region Region + var tmp region + if err := json.Unmarshal(data, &tmp); err != nil { + return err + } + r.Name = tmp.Name + r.Values = tmp.Values + + return nil +} + +// UnmarshalYAML handles either a plain string acting as the Name property or +// a struct, mimicking the Python-based openstacksdk. +func (r *Region) UnmarshalYAML(unmarshal func(interface{}) error) error { + var name string + if err := unmarshal(&name); err == nil { + r.Name = name + return nil + } + + type region Region + var tmp region + if err := unmarshal(&tmp); err != nil { + return err + } + r.Name = tmp.Name + r.Values = tmp.Values + + return nil +} + +// AuthType respresents a valid method of authentication. +type AuthType string + +const ( + // AuthPassword defines an unknown version of the password + AuthPassword AuthType = "password" + // AuthToken defined an unknown version of the token + AuthToken AuthType = "token" + + // AuthV2Password defines version 2 of the password + AuthV2Password AuthType = "v2password" + // AuthV2Token defines version 2 of the token + AuthV2Token AuthType = "v2token" + + // AuthV3Password defines version 3 of the password + AuthV3Password AuthType = "v3password" + // AuthV3Token defines version 3 of the token + AuthV3Token AuthType = "v3token" + + // AuthV3ApplicationCredential defines version 3 of the application credential + AuthV3ApplicationCredential AuthType = "v3applicationcredential" +) diff --git a/openstack/config/provider_client.go b/openstack/config/provider_client.go new file mode 100644 index 0000000000..a26b3511bd --- /dev/null +++ b/openstack/config/provider_client.go @@ -0,0 +1,70 @@ +package config + +import ( + "context" + "crypto/tls" + "net/http" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/openstack" +) + +type options struct { + httpClient http.Client + tlsConfig *tls.Config +} + +// WithHTTPClient enables passing a custom http.Client to be used in the +// ProviderClient for authentication and for any further call, for example when +// using a ServiceClient derived from this ProviderClient. +func WithHTTPClient(httpClient http.Client) func(*options) { + return func(o *options) { + o.httpClient = httpClient + } +} + +// WithTLSConfig replaces the Transport of the default HTTP client (or of the +// HTTP client passed with WithHTTPClient) with a RoundTripper containing the +// given TLS config. +func WithTLSConfig(tlsConfig *tls.Config) func(*options) { + return func(o *options) { + o.tlsConfig = tlsConfig + } +} + +// NewProviderClient logs in to an OpenStack cloud found at the identity +// endpoint specified by the options, acquires a token, and returns a Provider +// Client instance that's ready to operate. +// +// If the full path to a versioned identity endpoint was specified (example: +// http://example.com:5000/v3), that path will be used as the endpoint to +// query. +// +// If a versionless endpoint was specified (example: http://example.com:5000/), +// the endpoint will be queried to determine which versions of the identity +// service are available, then chooses the most recent or most supported +// version. +func NewProviderClient(ctx context.Context, authOptions gophercloud.AuthOptions, opts ...func(*options)) (*gophercloud.ProviderClient, error) { + var options options + for _, apply := range opts { + apply(&options) + } + + client, err := openstack.NewClient(authOptions.IdentityEndpoint) + if err != nil { + return nil, err + } + + if options.tlsConfig != nil { + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.TLSClientConfig = options.tlsConfig + options.httpClient.Transport = transport + } + client.HTTPClient = options.httpClient + + err = openstack.AuthenticateWithContext(ctx, client, authOptions) + if err != nil { + return nil, err + } + return client, nil +} From af248d5a5dc495630277e7760a7d58eadb2301b4 Mon Sep 17 00:00:00 2001 From: Vladimir Ermakov Date: Tue, 13 Feb 2024 11:59:09 +0100 Subject: [PATCH 069/118] clouds: fix default /etc/openstack/clouds.yaml selection That fix following error returned by Parse(): ``` Failed to parse clouds.yaml: yaml: input error: read /etc/openstack: is a directory ``` Signed-off-by: Vladimir Ermakov --- openstack/config/clouds/clouds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openstack/config/clouds/clouds.go b/openstack/config/clouds/clouds.go index b04416e68d..d16801adfa 100644 --- a/openstack/config/clouds/clouds.go +++ b/openstack/config/clouds/clouds.go @@ -86,7 +86,7 @@ func Parse(opts ...func(*cloudOpts)) (gophercloud.AuthOptions, gophercloud.Endpo if err != nil { return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("failed to get the user config directory: %w", err) } - options.locations = []string{path.Join(cwd, "clouds.yaml"), path.Join(userConfig, "openstack", "clouds.yaml"), path.Join("/etc", "openstack")} + options.locations = []string{path.Join(cwd, "clouds.yaml"), path.Join(userConfig, "openstack", "clouds.yaml"), path.Join("/etc", "openstack", "clouds.yaml")} } for _, cloudsPath := range options.locations { From 018a0795e6715ceea69113e8d484c6fb42bcea1f Mon Sep 17 00:00:00 2001 From: Vladimir Ermakov Date: Tue, 13 Feb 2024 12:11:32 +0100 Subject: [PATCH 070/118] clouds: export ParseOption to allow conditionally compose With* opts Fix #2913 Signed-off-by: Vladimir Ermakov --- openstack/config/clouds/clouds.go | 2 +- openstack/config/clouds/options.go | 49 ++++++++++++++++-------------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/openstack/config/clouds/clouds.go b/openstack/config/clouds/clouds.go index d16801adfa..54f3e8774b 100644 --- a/openstack/config/clouds/clouds.go +++ b/openstack/config/clouds/clouds.go @@ -53,7 +53,7 @@ import ( // // Search locations, as well as individual `clouds.yaml` properties, can be // overwritten with functional options. -func Parse(opts ...func(*cloudOpts)) (gophercloud.AuthOptions, gophercloud.EndpointOpts, *tls.Config, error) { +func Parse(opts ...ParseOption) (gophercloud.AuthOptions, gophercloud.EndpointOpts, *tls.Config, error) { options := cloudOpts{ cloudName: os.Getenv("OS_CLOUD"), region: os.Getenv("OS_REGION_NAME"), diff --git a/openstack/config/clouds/options.go b/openstack/config/clouds/options.go index 30bf6a2ef3..459c217555 100644 --- a/openstack/config/clouds/options.go +++ b/openstack/config/clouds/options.go @@ -34,8 +34,11 @@ type cloudOpts struct { insecure *bool } +// ParseOption one of parse configuration returned by With* modifier +type ParseOption = func(*cloudOpts) + // WithCloudName allows to override the environment variable `OS_CLOUD`. -func WithCloudName(osCloud string) func(*cloudOpts) { +func WithCloudName(osCloud string) ParseOption { return func(co *cloudOpts) { co.cloudName = osCloud } @@ -44,7 +47,7 @@ func WithCloudName(osCloud string) func(*cloudOpts) { // WithLocations is a functional option that sets the search locations for the // clouds.yaml file (and its optional companion secure.yaml). Each location is // a file path pointing to a possible `clouds.yaml`. -func WithLocations(locations ...string) func(*cloudOpts) { +func WithLocations(locations ...string) ParseOption { return func(co *cloudOpts) { co.locations = locations } @@ -54,7 +57,7 @@ func WithLocations(locations ...string) func(*cloudOpts) { // as an io.Reader interface. When this option is passed, FromCloudsYaml will // not attempt to fetch any file from the file system. To add a secure.yaml, // use in conjunction with WithSecureYAML. -func WithCloudsYAML(clouds io.Reader) func(*cloudOpts) { +func WithCloudsYAML(clouds io.Reader) ParseOption { return func(co *cloudOpts) { co.cloudsyamlReader = clouds } @@ -63,43 +66,43 @@ func WithCloudsYAML(clouds io.Reader) func(*cloudOpts) { // WithSecureYAML is a functional option that lets you pass a secure.yaml file // as an io.Reader interface, to complement the clouds.yaml that is either // fetched from the filesystem, or passed with WithCloudsYAML. -func WithSecureYAML(secure io.Reader) func(*cloudOpts) { +func WithSecureYAML(secure io.Reader) ParseOption { return func(co *cloudOpts) { co.secureyamlReader = secure } } -func WithApplicationCredentialID(applicationCredentialID string) func(*cloudOpts) { +func WithApplicationCredentialID(applicationCredentialID string) ParseOption { return func(co *cloudOpts) { co.applicationCredentialID = applicationCredentialID } } -func WithApplicationCredentialName(applicationCredentialName string) func(*cloudOpts) { +func WithApplicationCredentialName(applicationCredentialName string) ParseOption { return func(co *cloudOpts) { co.applicationCredentialName = applicationCredentialName } } -func WithApplicationCredentialSecret(applicationCredentialSecret string) func(*cloudOpts) { +func WithApplicationCredentialSecret(applicationCredentialSecret string) ParseOption { return func(co *cloudOpts) { co.applicationCredentialSecret = applicationCredentialSecret } } -func WithIdentityEndpoint(authURL string) func(*cloudOpts) { +func WithIdentityEndpoint(authURL string) ParseOption { return func(co *cloudOpts) { co.authURL = authURL } } -func WithDomainID(domainID string) func(*cloudOpts) { +func WithDomainID(domainID string) ParseOption { return func(co *cloudOpts) { co.domainID = domainID } } -func WithDomainName(domainName string) func(*cloudOpts) { +func WithDomainName(domainName string) ParseOption { return func(co *cloudOpts) { co.domainName = domainName } @@ -107,25 +110,25 @@ func WithDomainName(domainName string) func(*cloudOpts) { // WithRegion allows to override the endpoint type set in clouds.yaml or in the // environment variable `OS_INTERFACE`. -func WithEndpointType(endpointType string) func(*cloudOpts) { +func WithEndpointType(endpointType string) ParseOption { return func(co *cloudOpts) { co.endpointType = endpointType } } -func WithPassword(password string) func(*cloudOpts) { +func WithPassword(password string) ParseOption { return func(co *cloudOpts) { co.password = password } } -func WithProjectID(projectID string) func(*cloudOpts) { +func WithProjectID(projectID string) ParseOption { return func(co *cloudOpts) { co.projectID = projectID } } -func WithProjectName(projectName string) func(*cloudOpts) { +func WithProjectName(projectName string) ParseOption { return func(co *cloudOpts) { co.projectName = projectName } @@ -133,55 +136,55 @@ func WithProjectName(projectName string) func(*cloudOpts) { // WithRegion allows to override the region set in clouds.yaml or in the // environment variable `OS_REGION_NAME` -func WithRegion(region string) func(*cloudOpts) { +func WithRegion(region string) ParseOption { return func(co *cloudOpts) { co.region = region } } -func WithScope(scope *gophercloud.AuthScope) func(*cloudOpts) { +func WithScope(scope *gophercloud.AuthScope) ParseOption { return func(co *cloudOpts) { co.scope = scope } } -func WithToken(token string) func(*cloudOpts) { +func WithToken(token string) ParseOption { return func(co *cloudOpts) { co.token = token } } -func WithUserID(userID string) func(*cloudOpts) { +func WithUserID(userID string) ParseOption { return func(co *cloudOpts) { co.userID = userID } } -func WithUsername(username string) func(*cloudOpts) { +func WithUsername(username string) ParseOption { return func(co *cloudOpts) { co.username = username } } -func WithCACertPath(caCertPath string) func(*cloudOpts) { +func WithCACertPath(caCertPath string) ParseOption { return func(co *cloudOpts) { co.caCertPath = caCertPath } } -func WithClientCertPath(clientCertPath string) func(*cloudOpts) { +func WithClientCertPath(clientCertPath string) ParseOption { return func(co *cloudOpts) { co.clientCertPath = clientCertPath } } -func WithClientKeyPath(clientKeyPath string) func(*cloudOpts) { +func WithClientKeyPath(clientKeyPath string) ParseOption { return func(co *cloudOpts) { co.clientKeyPath = clientKeyPath } } -func WithInsecure(insecure bool) func(*cloudOpts) { +func WithInsecure(insecure bool) ParseOption { return func(co *cloudOpts) { co.insecure = &insecure } From ac7c64d7b35c129ed8e786aa1b3abc87f7726290 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Mon, 12 Feb 2024 12:54:38 +0100 Subject: [PATCH 071/118] build(deps): bump EmilienM/devstack-action from 0.11 to 0.14 Also start using the commit hash of the release, rather than the tag. --- .github/workflows/functional-baremetal.yaml | 2 +- .github/workflows/functional-basic.yaml | 2 +- .github/workflows/functional-blockstorage.yaml | 2 +- .github/workflows/functional-clustering.yaml | 2 +- .github/workflows/functional-compute.yaml | 2 +- .github/workflows/functional-containerinfra.yaml | 2 +- .github/workflows/functional-dns.yaml | 2 +- .github/workflows/functional-fwaas_v2.yaml | 2 +- .github/workflows/functional-identity.yaml | 2 +- .github/workflows/functional-imageservice.yaml | 2 +- .github/workflows/functional-keymanager.yaml | 2 +- .github/workflows/functional-loadbalancer.yaml | 2 +- .github/workflows/functional-messaging.yaml | 2 +- .github/workflows/functional-networking.yaml | 2 +- .github/workflows/functional-objectstorage.yaml | 2 +- .github/workflows/functional-orchestration.yaml | 2 +- .github/workflows/functional-placement.yaml | 2 +- .github/workflows/functional-sharedfilesystems.yaml | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index f66da92a26..831a672442 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index a679a0f27e..c7331f42b8 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -42,7 +42,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} enabled_services: 's-account,s-container,s-object,s-proxy' diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index b0b5f759ec..721a9a5f6e 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-clustering.yaml b/.github/workflows/functional-clustering.yaml index c7d7a53c65..529c6e3833 100644 --- a/.github/workflows/functional-clustering.yaml +++ b/.github/workflows/functional-clustering.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index 6cf62990ff..cc6261b984 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index 9ed76d8026..335fcbbe51 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -63,7 +63,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index 43177088c7..d01af4bb93 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -40,7 +40,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml index 020163ce27..e2b2f5c04b 100644 --- a/.github/workflows/functional-fwaas_v2.yaml +++ b/.github/workflows/functional-fwaas_v2.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml index a62ddacf78..650f1fc0b8 100644 --- a/.github/workflows/functional-identity.yaml +++ b/.github/workflows/functional-identity.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} - name: Checkout go diff --git a/.github/workflows/functional-imageservice.yaml b/.github/workflows/functional-imageservice.yaml index 9dec83dd54..a99cdb175c 100644 --- a/.github/workflows/functional-imageservice.yaml +++ b/.github/workflows/functional-imageservice.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} - name: Checkout go diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml index e0fb3db115..22668b3b7d 100644 --- a/.github/workflows/functional-keymanager.yaml +++ b/.github/workflows/functional-keymanager.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml index 8dc42208cf..45ab11b657 100644 --- a/.github/workflows/functional-loadbalancer.yaml +++ b/.github/workflows/functional-loadbalancer.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml index 2355cfed85..70e195174f 100644 --- a/.github/workflows/functional-messaging.yaml +++ b/.github/workflows/functional-messaging.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index 8539acc80c..c3968a04e4 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml index 60cd27e9f2..30d07b877c 100644 --- a/.github/workflows/functional-objectstorage.yaml +++ b/.github/workflows/functional-objectstorage.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml index 73d461aac6..85dd87eaa2 100644 --- a/.github/workflows/functional-orchestration.yaml +++ b/.github/workflows/functional-orchestration.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml index 016157562d..c02b7d61a5 100644 --- a/.github/workflows/functional-placement.yaml +++ b/.github/workflows/functional-placement.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} - name: Checkout go diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml index 6924d001fe..0750dc4893 100644 --- a/.github/workflows/functional-sharedfilesystems.yaml +++ b/.github/workflows/functional-sharedfilesystems.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v3 - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: branch: ${{ matrix.openstack_version }} conf_overrides: | From ac1ecd42da6eec266c6c8b3cad9ce4d45ffcf62d Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Tue, 20 Feb 2024 13:56:34 +0100 Subject: [PATCH 072/118] Fix AllowReauth reauthentication Due to an error in implementing the addition of context.Context, the default reauth function caught the context passed when generating the ProviderClient, which could be long canceled when the reauthentication takes place. --- openstack/client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openstack/client.go b/openstack/client.go index 8c6173a264..acaa02be46 100644 --- a/openstack/client.go +++ b/openstack/client.go @@ -171,7 +171,7 @@ func v2auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint st tao := options tao.AllowReauth = false client.ReauthFunc = func() error { - err := v2auth(ctx, &tac, endpoint, tao, eo) + err := v2auth(context.Background(), &tac, endpoint, tao, eo) if err != nil { return err } @@ -294,7 +294,7 @@ func v3auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint st tao = opts } client.ReauthFunc = func() error { - err := v3auth(ctx, &tac, endpoint, tao, eo) + err := v3auth(context.Background(), &tac, endpoint, tao, eo) if err != nil { return err } From 3323f810f901410f775f6ea36f00311409075bd6 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Wed, 21 Feb 2024 18:11:01 +0000 Subject: [PATCH 073/118] compute: Use volumeID, not attachmentID for volume attachments The volume attachments API operates on volumes, not attachments. Correct the variable name. Signed-off-by: Stephen Finucane Closes: #2861 --- openstack/compute/v2/extensions/volumeattach/doc.go | 4 ++-- openstack/compute/v2/extensions/volumeattach/requests.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openstack/compute/v2/extensions/volumeattach/doc.go b/openstack/compute/v2/extensions/volumeattach/doc.go index 484eb20000..857ab19cc5 100644 --- a/openstack/compute/v2/extensions/volumeattach/doc.go +++ b/openstack/compute/v2/extensions/volumeattach/doc.go @@ -20,9 +20,9 @@ Example to Attach a Volume Example to Detach a Volume serverID := "7ac8686c-de71-4acb-9600-ec18b1a1ed6d" - attachmentID := "ed081613-1c9b-4231-aa5e-ebfd4d87f983" + volumeID := "ed081613-1c9b-4231-aa5e-ebfd4d87f983" - err := volumeattach.Delete(computeClient, serverID, attachmentID).ExtractErr() + err := volumeattach.Delete(computeClient, serverID, volumeID).ExtractErr() if err != nil { panic(err) } diff --git a/openstack/compute/v2/extensions/volumeattach/requests.go b/openstack/compute/v2/extensions/volumeattach/requests.go index 8c5a2ba03e..fe0b1075d6 100644 --- a/openstack/compute/v2/extensions/volumeattach/requests.go +++ b/openstack/compute/v2/extensions/volumeattach/requests.go @@ -56,16 +56,16 @@ func Create(client *gophercloud.ServiceClient, serverID string, opts CreateOptsB } // Get returns public data about a previously created VolumeAttachment. -func Get(client *gophercloud.ServiceClient, serverID, attachmentID string) (r GetResult) { - resp, err := client.Get(getURL(client, serverID, attachmentID), &r.Body, nil) +func Get(client *gophercloud.ServiceClient, serverID, volumeID string) (r GetResult) { + resp, err := client.Get(getURL(client, serverID, volumeID), &r.Body, nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } // Delete requests the deletion of a previous stored VolumeAttachment from // the server. -func Delete(client *gophercloud.ServiceClient, serverID, attachmentID string) (r DeleteResult) { - resp, err := client.Delete(deleteURL(client, serverID, attachmentID), nil) +func Delete(client *gophercloud.ServiceClient, serverID, volumeID string) (r DeleteResult) { + resp, err := client.Delete(deleteURL(client, serverID, volumeID), nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } From e31725833415a925c66f69bfd84fa9d53bbd142f Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Tue, 27 Feb 2024 16:12:49 +0100 Subject: [PATCH 074/118] Prepare v1.10.0 --- CHANGELOG.md | 10 ++++++++++ provider_client.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e10078ade6..3d99d01ff2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## v1.10.0 (2024-02-27) + +* [GH-2893](https://github.com/gophercloud/gophercloud/pull/2893) [v1] authentication: Add WithContext functions +* [GH-2894](https://github.com/gophercloud/gophercloud/pull/2894) [v1] pager: Add WithContext functions +* [GH-2899](https://github.com/gophercloud/gophercloud/pull/2899) [v1] Authenticate with a clouds.yaml +* [GH-2917](https://github.com/gophercloud/gophercloud/pull/2917) [v1] Add ParseOption type to made clouds.Parse() more usable for optional With* funcs +* [GH-2924](https://github.com/gophercloud/gophercloud/pull/2924) [v1] build(deps): bump EmilienM/devstack-action from 0.11 to 0.14 +* [GH-2933](https://github.com/gophercloud/gophercloud/pull/2933) [v1] Fix AllowReauth reauthentication +* [GH-2950](https://github.com/gophercloud/gophercloud/pull/2950) [v1] compute: Use volumeID, not attachmentID for volume attachments + ## v1.9.0 (2024-02-02) New features and improvements: diff --git a/provider_client.go b/provider_client.go index 5cb5e150ff..64787e5337 100644 --- a/provider_client.go +++ b/provider_client.go @@ -16,7 +16,7 @@ import ( // DefaultUserAgent is the default User-Agent string set in the request header. const ( - DefaultUserAgent = "gophercloud/v1.9.0" + DefaultUserAgent = "gophercloud/v1.10.0" DefaultMaxBackoffRetries = 60 ) From 16b3cd52f754a6fcdb11e3a091b1fa467ce23779 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 6 Mar 2024 16:51:40 +0100 Subject: [PATCH 075/118] Revert "Fix AllowReauth reauthentication" This reverts commit ac1ecd42da6eec266c6c8b3cad9ce4d45ffcf62d. --- openstack/client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openstack/client.go b/openstack/client.go index acaa02be46..8c6173a264 100644 --- a/openstack/client.go +++ b/openstack/client.go @@ -171,7 +171,7 @@ func v2auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint st tao := options tao.AllowReauth = false client.ReauthFunc = func() error { - err := v2auth(context.Background(), &tac, endpoint, tao, eo) + err := v2auth(ctx, &tac, endpoint, tao, eo) if err != nil { return err } @@ -294,7 +294,7 @@ func v3auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint st tao = opts } client.ReauthFunc = func() error { - err := v3auth(context.Background(), &tac, endpoint, tao, eo) + err := v3auth(ctx, &tac, endpoint, tao, eo) if err != nil { return err } From fbfac92f640786a02ed622021124c13dcd15d292 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 6 Mar 2024 16:52:14 +0100 Subject: [PATCH 076/118] Revert "clouds: export ParseOption to allow conditionally compose With* opts" This reverts commit 018a0795e6715ceea69113e8d484c6fb42bcea1f. --- openstack/config/clouds/clouds.go | 2 +- openstack/config/clouds/options.go | 49 ++++++++++++++---------------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/openstack/config/clouds/clouds.go b/openstack/config/clouds/clouds.go index 54f3e8774b..d16801adfa 100644 --- a/openstack/config/clouds/clouds.go +++ b/openstack/config/clouds/clouds.go @@ -53,7 +53,7 @@ import ( // // Search locations, as well as individual `clouds.yaml` properties, can be // overwritten with functional options. -func Parse(opts ...ParseOption) (gophercloud.AuthOptions, gophercloud.EndpointOpts, *tls.Config, error) { +func Parse(opts ...func(*cloudOpts)) (gophercloud.AuthOptions, gophercloud.EndpointOpts, *tls.Config, error) { options := cloudOpts{ cloudName: os.Getenv("OS_CLOUD"), region: os.Getenv("OS_REGION_NAME"), diff --git a/openstack/config/clouds/options.go b/openstack/config/clouds/options.go index 459c217555..30bf6a2ef3 100644 --- a/openstack/config/clouds/options.go +++ b/openstack/config/clouds/options.go @@ -34,11 +34,8 @@ type cloudOpts struct { insecure *bool } -// ParseOption one of parse configuration returned by With* modifier -type ParseOption = func(*cloudOpts) - // WithCloudName allows to override the environment variable `OS_CLOUD`. -func WithCloudName(osCloud string) ParseOption { +func WithCloudName(osCloud string) func(*cloudOpts) { return func(co *cloudOpts) { co.cloudName = osCloud } @@ -47,7 +44,7 @@ func WithCloudName(osCloud string) ParseOption { // WithLocations is a functional option that sets the search locations for the // clouds.yaml file (and its optional companion secure.yaml). Each location is // a file path pointing to a possible `clouds.yaml`. -func WithLocations(locations ...string) ParseOption { +func WithLocations(locations ...string) func(*cloudOpts) { return func(co *cloudOpts) { co.locations = locations } @@ -57,7 +54,7 @@ func WithLocations(locations ...string) ParseOption { // as an io.Reader interface. When this option is passed, FromCloudsYaml will // not attempt to fetch any file from the file system. To add a secure.yaml, // use in conjunction with WithSecureYAML. -func WithCloudsYAML(clouds io.Reader) ParseOption { +func WithCloudsYAML(clouds io.Reader) func(*cloudOpts) { return func(co *cloudOpts) { co.cloudsyamlReader = clouds } @@ -66,43 +63,43 @@ func WithCloudsYAML(clouds io.Reader) ParseOption { // WithSecureYAML is a functional option that lets you pass a secure.yaml file // as an io.Reader interface, to complement the clouds.yaml that is either // fetched from the filesystem, or passed with WithCloudsYAML. -func WithSecureYAML(secure io.Reader) ParseOption { +func WithSecureYAML(secure io.Reader) func(*cloudOpts) { return func(co *cloudOpts) { co.secureyamlReader = secure } } -func WithApplicationCredentialID(applicationCredentialID string) ParseOption { +func WithApplicationCredentialID(applicationCredentialID string) func(*cloudOpts) { return func(co *cloudOpts) { co.applicationCredentialID = applicationCredentialID } } -func WithApplicationCredentialName(applicationCredentialName string) ParseOption { +func WithApplicationCredentialName(applicationCredentialName string) func(*cloudOpts) { return func(co *cloudOpts) { co.applicationCredentialName = applicationCredentialName } } -func WithApplicationCredentialSecret(applicationCredentialSecret string) ParseOption { +func WithApplicationCredentialSecret(applicationCredentialSecret string) func(*cloudOpts) { return func(co *cloudOpts) { co.applicationCredentialSecret = applicationCredentialSecret } } -func WithIdentityEndpoint(authURL string) ParseOption { +func WithIdentityEndpoint(authURL string) func(*cloudOpts) { return func(co *cloudOpts) { co.authURL = authURL } } -func WithDomainID(domainID string) ParseOption { +func WithDomainID(domainID string) func(*cloudOpts) { return func(co *cloudOpts) { co.domainID = domainID } } -func WithDomainName(domainName string) ParseOption { +func WithDomainName(domainName string) func(*cloudOpts) { return func(co *cloudOpts) { co.domainName = domainName } @@ -110,25 +107,25 @@ func WithDomainName(domainName string) ParseOption { // WithRegion allows to override the endpoint type set in clouds.yaml or in the // environment variable `OS_INTERFACE`. -func WithEndpointType(endpointType string) ParseOption { +func WithEndpointType(endpointType string) func(*cloudOpts) { return func(co *cloudOpts) { co.endpointType = endpointType } } -func WithPassword(password string) ParseOption { +func WithPassword(password string) func(*cloudOpts) { return func(co *cloudOpts) { co.password = password } } -func WithProjectID(projectID string) ParseOption { +func WithProjectID(projectID string) func(*cloudOpts) { return func(co *cloudOpts) { co.projectID = projectID } } -func WithProjectName(projectName string) ParseOption { +func WithProjectName(projectName string) func(*cloudOpts) { return func(co *cloudOpts) { co.projectName = projectName } @@ -136,55 +133,55 @@ func WithProjectName(projectName string) ParseOption { // WithRegion allows to override the region set in clouds.yaml or in the // environment variable `OS_REGION_NAME` -func WithRegion(region string) ParseOption { +func WithRegion(region string) func(*cloudOpts) { return func(co *cloudOpts) { co.region = region } } -func WithScope(scope *gophercloud.AuthScope) ParseOption { +func WithScope(scope *gophercloud.AuthScope) func(*cloudOpts) { return func(co *cloudOpts) { co.scope = scope } } -func WithToken(token string) ParseOption { +func WithToken(token string) func(*cloudOpts) { return func(co *cloudOpts) { co.token = token } } -func WithUserID(userID string) ParseOption { +func WithUserID(userID string) func(*cloudOpts) { return func(co *cloudOpts) { co.userID = userID } } -func WithUsername(username string) ParseOption { +func WithUsername(username string) func(*cloudOpts) { return func(co *cloudOpts) { co.username = username } } -func WithCACertPath(caCertPath string) ParseOption { +func WithCACertPath(caCertPath string) func(*cloudOpts) { return func(co *cloudOpts) { co.caCertPath = caCertPath } } -func WithClientCertPath(clientCertPath string) ParseOption { +func WithClientCertPath(clientCertPath string) func(*cloudOpts) { return func(co *cloudOpts) { co.clientCertPath = clientCertPath } } -func WithClientKeyPath(clientKeyPath string) ParseOption { +func WithClientKeyPath(clientKeyPath string) func(*cloudOpts) { return func(co *cloudOpts) { co.clientKeyPath = clientKeyPath } } -func WithInsecure(insecure bool) ParseOption { +func WithInsecure(insecure bool) func(*cloudOpts) { return func(co *cloudOpts) { co.insecure = &insecure } From 52d12eccaffe113fb25b4f51c0ac78e17073dfab Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 6 Mar 2024 16:52:26 +0100 Subject: [PATCH 077/118] Revert "clouds: fix default /etc/openstack/clouds.yaml selection" This reverts commit af248d5a5dc495630277e7760a7d58eadb2301b4. --- openstack/config/clouds/clouds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openstack/config/clouds/clouds.go b/openstack/config/clouds/clouds.go index d16801adfa..b04416e68d 100644 --- a/openstack/config/clouds/clouds.go +++ b/openstack/config/clouds/clouds.go @@ -86,7 +86,7 @@ func Parse(opts ...func(*cloudOpts)) (gophercloud.AuthOptions, gophercloud.Endpo if err != nil { return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("failed to get the user config directory: %w", err) } - options.locations = []string{path.Join(cwd, "clouds.yaml"), path.Join(userConfig, "openstack", "clouds.yaml"), path.Join("/etc", "openstack", "clouds.yaml")} + options.locations = []string{path.Join(cwd, "clouds.yaml"), path.Join(userConfig, "openstack", "clouds.yaml"), path.Join("/etc", "openstack")} } for _, cloudsPath := range options.locations { From da1523b7ae462acf6d0ef89af94acd3d54150aa0 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 6 Mar 2024 16:52:38 +0100 Subject: [PATCH 078/118] Revert "Authenticate with a clouds.yaml" This reverts commit 22c56829f05af19f3ab422ff1b8b9db2000789f9. --- openstack/config/clouds/clouds.go | 271 ------------------------- openstack/config/clouds/clouds_test.go | 64 ------ openstack/config/clouds/options.go | 188 ----------------- openstack/config/clouds/tls.go | 88 -------- openstack/config/clouds/types.go | 203 ------------------ openstack/config/provider_client.go | 70 ------- 6 files changed, 884 deletions(-) delete mode 100644 openstack/config/clouds/clouds.go delete mode 100644 openstack/config/clouds/clouds_test.go delete mode 100644 openstack/config/clouds/options.go delete mode 100644 openstack/config/clouds/tls.go delete mode 100644 openstack/config/clouds/types.go delete mode 100644 openstack/config/provider_client.go diff --git a/openstack/config/clouds/clouds.go b/openstack/config/clouds/clouds.go deleted file mode 100644 index b04416e68d..0000000000 --- a/openstack/config/clouds/clouds.go +++ /dev/null @@ -1,271 +0,0 @@ -// package clouds provides a parser for OpenStack credentials stored in a clouds.yaml file. -// -// Example use: -// -// ctx := context.Background() -// ao, eo, tlsConfig, err := clouds.Parse() -// if err != nil { -// panic(err) -// } -// -// providerClient, err := config.NewProviderClient(ctx, ao, config.WithTLSConfig(tlsConfig)) -// if err != nil { -// panic(err) -// } -// -// networkClient, err := openstack.NewNetworkV2(providerClient, eo) -// if err != nil { -// panic(err) -// } -package clouds - -import ( - "crypto/tls" - "encoding/json" - "errors" - "fmt" - "os" - "path" - "reflect" - - "github.com/gophercloud/gophercloud" - "gopkg.in/yaml.v2" -) - -// Parse fetches a clouds.yaml file from disk and returns the parsed -// credentials. -// -// By default this function mimics the behaviour of python-openstackclient, which is: -// -// - if the environment variable `OS_CLIENT_CONFIG_FILE` is set and points to a -// clouds.yaml, use that location as the only search location for `clouds.yaml` and `secure.yaml`; -// - otherwise, the search locations for `clouds.yaml` and `secure.yaml` are: -// 1. the current working directory (on Linux: `./`) -// 2. the directory `openstack` under the standatd user config location for -// the operating system (on Linux: `${XDG_CONFIG_HOME:-$HOME/.config}/openstack/`) -// 3. on Linux, `/etc/openstack/` -// -// Once `clouds.yaml` is found in a search location, the same location is used to search for `secure.yaml`. -// -// Like in python-openstackclient, relative paths in the `clouds.yaml` section -// `cacert` are interpreted as relative the the current directory, and not to -// the `clouds.yaml` location. -// -// Search locations, as well as individual `clouds.yaml` properties, can be -// overwritten with functional options. -func Parse(opts ...func(*cloudOpts)) (gophercloud.AuthOptions, gophercloud.EndpointOpts, *tls.Config, error) { - options := cloudOpts{ - cloudName: os.Getenv("OS_CLOUD"), - region: os.Getenv("OS_REGION_NAME"), - endpointType: os.Getenv("OS_INTERFACE"), - locations: func() []string { - if path := os.Getenv("OS_CLIENT_CONFIG_FILE"); path != "" { - return []string{path} - } - return nil - }(), - } - - for _, apply := range opts { - apply(&options) - } - - if options.cloudName == "" { - return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("the empty string \"\" is not a valid cloud name") - } - - // Set the defaults and open the files for reading. This code only runs - // if no override has been set, because it is fallible. - if options.cloudsyamlReader == nil { - if len(options.locations) < 1 { - cwd, err := os.Getwd() - if err != nil { - return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("failed to get the current working directory: %w", err) - } - userConfig, err := os.UserConfigDir() - if err != nil { - return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("failed to get the user config directory: %w", err) - } - options.locations = []string{path.Join(cwd, "clouds.yaml"), path.Join(userConfig, "openstack", "clouds.yaml"), path.Join("/etc", "openstack")} - } - - for _, cloudsPath := range options.locations { - var errNotFound *os.PathError - f, err := os.Open(cloudsPath) - if err != nil && !errors.As(err, &errNotFound) { - return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("failed to open %q: %w", cloudsPath, err) - } - if err == nil { - defer f.Close() - options.cloudsyamlReader = f - - if options.secureyamlReader == nil { - securePath := path.Join(path.Base(cloudsPath), "secure.yaml") - secureF, err := os.Open(securePath) - if err != nil && !errors.As(err, &errNotFound) { - return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("failed to open %q: %w", securePath, err) - } - if err == nil { - defer secureF.Close() - options.secureyamlReader = secureF - } - } - } - } - if options.cloudsyamlReader == nil { - return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("clouds file not found. Search locations were: %v", options.locations) - } - } - - // Parse the YAML payloads. - var clouds Clouds - if err := yaml.NewDecoder(options.cloudsyamlReader).Decode(&clouds); err != nil { - return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, err - } - - cloud, ok := clouds.Clouds[options.cloudName] - if !ok { - return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("cloud %q not found in clouds.yaml", options.cloudName) - } - - if options.secureyamlReader != nil { - var secureClouds Clouds - if err := yaml.NewDecoder(options.secureyamlReader).Decode(&secureClouds); err != nil { - return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("failed to parse secure.yaml: %w", err) - } - - if secureCloud, ok := secureClouds.Clouds[options.cloudName]; ok { - // If secureCloud has content and it differs from the cloud entry, - // merge the two together. - if !reflect.DeepEqual((gophercloud.AuthOptions{}), secureClouds) && !reflect.DeepEqual(clouds, secureClouds) { - var err error - cloud, err = mergeClouds(secureCloud, cloud) - if err != nil { - return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("unable to merge information from clouds.yaml and secure.yaml") - } - } - } - } - - tlsConfig, err := computeTLSConfig(cloud, options) - if err != nil { - return gophercloud.AuthOptions{}, gophercloud.EndpointOpts{}, nil, fmt.Errorf("unable to compute TLS configuration: %w", err) - } - - endpointType := coalesce(options.endpointType, cloud.EndpointType, cloud.Interface) - - return gophercloud.AuthOptions{ - IdentityEndpoint: coalesce(options.authURL, cloud.AuthInfo.AuthURL), - Username: coalesce(options.username, cloud.AuthInfo.Username), - UserID: coalesce(options.userID, cloud.AuthInfo.UserID), - Password: coalesce(options.password, cloud.AuthInfo.Password), - DomainID: coalesce(options.domainID, cloud.AuthInfo.UserDomainID, cloud.AuthInfo.ProjectDomainID, cloud.AuthInfo.DomainID), - DomainName: coalesce(options.domainName, cloud.AuthInfo.UserDomainName, cloud.AuthInfo.ProjectDomainName, cloud.AuthInfo.DomainName), - TenantID: coalesce(options.projectID, cloud.AuthInfo.ProjectID), - TenantName: coalesce(options.projectName, cloud.AuthInfo.ProjectName), - TokenID: coalesce(options.token, cloud.AuthInfo.Token), - Scope: options.scope, - ApplicationCredentialID: coalesce(options.applicationCredentialID, cloud.AuthInfo.ApplicationCredentialID), - ApplicationCredentialName: coalesce(options.applicationCredentialName, cloud.AuthInfo.ApplicationCredentialName), - ApplicationCredentialSecret: coalesce(options.applicationCredentialSecret, cloud.AuthInfo.ApplicationCredentialSecret), - }, gophercloud.EndpointOpts{ - Region: coalesce(options.region, cloud.RegionName), - Availability: computeAvailability(endpointType), - }, - tlsConfig, - nil -} - -// computeAvailability is a helper method to determine the endpoint type -// requested by the user. -func computeAvailability(endpointType string) gophercloud.Availability { - if endpointType == "internal" || endpointType == "internalURL" { - return gophercloud.AvailabilityInternal - } - if endpointType == "admin" || endpointType == "adminURL" { - return gophercloud.AvailabilityAdmin - } - return gophercloud.AvailabilityPublic -} - -// coalesce returns the first argument that is not the empty string, or the -// empty string. -func coalesce(items ...string) string { - for _, item := range items { - if item != "" { - return item - } - } - return "" -} - -// mergeClouds merges two Clouds recursively (the AuthInfo also gets merged). -// In case both Clouds define a value, the value in the 'override' cloud takes precedence -func mergeClouds(override, cloud Cloud) (Cloud, error) { - overrideJson, err := json.Marshal(override) - if err != nil { - return Cloud{}, err - } - cloudJson, err := json.Marshal(cloud) - if err != nil { - return Cloud{}, err - } - var overrideInterface interface{} - err = json.Unmarshal(overrideJson, &overrideInterface) - if err != nil { - return Cloud{}, err - } - var cloudInterface interface{} - err = json.Unmarshal(cloudJson, &cloudInterface) - if err != nil { - return Cloud{}, err - } - var mergedCloud Cloud - mergedInterface := mergeInterfaces(overrideInterface, cloudInterface) - mergedJson, err := json.Marshal(mergedInterface) - err = json.Unmarshal(mergedJson, &mergedCloud) - if err != nil { - return Cloud{}, err - } - return mergedCloud, nil -} - -// merges two interfaces. In cases where a value is defined for both 'overridingInterface' and -// 'inferiorInterface' the value in 'overridingInterface' will take precedence. -func mergeInterfaces(overridingInterface, inferiorInterface interface{}) interface{} { - switch overriding := overridingInterface.(type) { - case map[string]interface{}: - interfaceMap, ok := inferiorInterface.(map[string]interface{}) - if !ok { - return overriding - } - for k, v := range interfaceMap { - if overridingValue, ok := overriding[k]; ok { - overriding[k] = mergeInterfaces(overridingValue, v) - } else { - overriding[k] = v - } - } - case []interface{}: - list, ok := inferiorInterface.([]interface{}) - if !ok { - return overriding - } - for i := range list { - overriding = append(overriding, list[i]) - } - return overriding - case nil: - // mergeClouds(nil, map[string]interface{...}) -> map[string]interface{...} - v, ok := inferiorInterface.(map[string]interface{}) - if ok { - return v - } - } - // We don't want to override with empty values - if reflect.DeepEqual(overridingInterface, nil) || reflect.DeepEqual(reflect.Zero(reflect.TypeOf(overridingInterface)).Interface(), overridingInterface) { - return inferiorInterface - } else { - return overridingInterface - } -} diff --git a/openstack/config/clouds/clouds_test.go b/openstack/config/clouds/clouds_test.go deleted file mode 100644 index e25bae0122..0000000000 --- a/openstack/config/clouds/clouds_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package clouds_test - -import ( - "fmt" - "strings" - - "github.com/gophercloud/gophercloud/openstack/config/clouds" -) - -func ExampleWithCloudName() { - const exampleClouds = `clouds: - openstack: - auth: - auth_url: https://example.com:13000` - - ao, _, _, err := clouds.Parse( - clouds.WithCloudsYAML(strings.NewReader(exampleClouds)), - clouds.WithCloudName("openstack"), - ) - if err != nil { - panic(err) - } - - fmt.Println(ao.IdentityEndpoint) - // Output: https://example.com:13000 -} - -func ExampleWithUserID() { - const exampleClouds = `clouds: - openstack: - auth: - auth_url: https://example.com:13000` - - ao, _, _, err := clouds.Parse( - clouds.WithCloudsYAML(strings.NewReader(exampleClouds)), - clouds.WithCloudName("openstack"), - clouds.WithUsername("Kris"), - ) - if err != nil { - panic(err) - } - - fmt.Println(ao.Username) - // Output: Kris -} - -func ExampleWithRegion() { - const exampleClouds = `clouds: - openstack: - auth: - auth_url: https://example.com:13000` - - _, eo, _, err := clouds.Parse( - clouds.WithCloudsYAML(strings.NewReader(exampleClouds)), - clouds.WithCloudName("openstack"), - clouds.WithRegion("mars"), - ) - if err != nil { - panic(err) - } - - fmt.Println(eo.Region) - // Output: mars -} diff --git a/openstack/config/clouds/options.go b/openstack/config/clouds/options.go deleted file mode 100644 index 30bf6a2ef3..0000000000 --- a/openstack/config/clouds/options.go +++ /dev/null @@ -1,188 +0,0 @@ -package clouds - -import ( - "io" - - "github.com/gophercloud/gophercloud" -) - -type cloudOpts struct { - cloudName string - locations []string - cloudsyamlReader io.Reader - secureyamlReader io.Reader - - applicationCredentialID string - applicationCredentialName string - applicationCredentialSecret string - authURL string - domainID string - domainName string - endpointType string - password string - projectID string - projectName string - region string - scope *gophercloud.AuthScope - token string - userID string - username string - - caCertPath string - clientCertPath string - clientKeyPath string - insecure *bool -} - -// WithCloudName allows to override the environment variable `OS_CLOUD`. -func WithCloudName(osCloud string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.cloudName = osCloud - } -} - -// WithLocations is a functional option that sets the search locations for the -// clouds.yaml file (and its optional companion secure.yaml). Each location is -// a file path pointing to a possible `clouds.yaml`. -func WithLocations(locations ...string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.locations = locations - } -} - -// WithCloudsYAML is a functional option that lets you pass a clouds.yaml file -// as an io.Reader interface. When this option is passed, FromCloudsYaml will -// not attempt to fetch any file from the file system. To add a secure.yaml, -// use in conjunction with WithSecureYAML. -func WithCloudsYAML(clouds io.Reader) func(*cloudOpts) { - return func(co *cloudOpts) { - co.cloudsyamlReader = clouds - } -} - -// WithSecureYAML is a functional option that lets you pass a secure.yaml file -// as an io.Reader interface, to complement the clouds.yaml that is either -// fetched from the filesystem, or passed with WithCloudsYAML. -func WithSecureYAML(secure io.Reader) func(*cloudOpts) { - return func(co *cloudOpts) { - co.secureyamlReader = secure - } -} - -func WithApplicationCredentialID(applicationCredentialID string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.applicationCredentialID = applicationCredentialID - } -} - -func WithApplicationCredentialName(applicationCredentialName string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.applicationCredentialName = applicationCredentialName - } -} - -func WithApplicationCredentialSecret(applicationCredentialSecret string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.applicationCredentialSecret = applicationCredentialSecret - } -} - -func WithIdentityEndpoint(authURL string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.authURL = authURL - } -} - -func WithDomainID(domainID string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.domainID = domainID - } -} - -func WithDomainName(domainName string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.domainName = domainName - } -} - -// WithRegion allows to override the endpoint type set in clouds.yaml or in the -// environment variable `OS_INTERFACE`. -func WithEndpointType(endpointType string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.endpointType = endpointType - } -} - -func WithPassword(password string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.password = password - } -} - -func WithProjectID(projectID string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.projectID = projectID - } -} - -func WithProjectName(projectName string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.projectName = projectName - } -} - -// WithRegion allows to override the region set in clouds.yaml or in the -// environment variable `OS_REGION_NAME` -func WithRegion(region string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.region = region - } -} - -func WithScope(scope *gophercloud.AuthScope) func(*cloudOpts) { - return func(co *cloudOpts) { - co.scope = scope - } -} - -func WithToken(token string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.token = token - } -} - -func WithUserID(userID string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.userID = userID - } -} - -func WithUsername(username string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.username = username - } -} - -func WithCACertPath(caCertPath string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.caCertPath = caCertPath - } -} - -func WithClientCertPath(clientCertPath string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.clientCertPath = clientCertPath - } -} - -func WithClientKeyPath(clientKeyPath string) func(*cloudOpts) { - return func(co *cloudOpts) { - co.clientKeyPath = clientKeyPath - } -} - -func WithInsecure(insecure bool) func(*cloudOpts) { - return func(co *cloudOpts) { - co.insecure = &insecure - } -} diff --git a/openstack/config/clouds/tls.go b/openstack/config/clouds/tls.go deleted file mode 100644 index 460ede6d04..0000000000 --- a/openstack/config/clouds/tls.go +++ /dev/null @@ -1,88 +0,0 @@ -package clouds - -import ( - "bytes" - "crypto/tls" - "crypto/x509" - "fmt" - "io/ioutil" - "os" - "path" - "strings" -) - -func computeTLSConfig(cloud Cloud, options cloudOpts) (*tls.Config, error) { - tlsConfig := new(tls.Config) - if caCertPath := coalesce(options.caCertPath, os.Getenv("OS_CACERT"), cloud.CACertFile); caCertPath != "" { - caCertPath, err := resolveTilde(caCertPath) - if err != nil { - return nil, fmt.Errorf("failed to resolve user home directory: %w", err) - } - - caCert, err := ioutil.ReadFile(caCertPath) - if err != nil { - return nil, fmt.Errorf("failed to open the CA cert file: %w", err) - } - - caCertPool := x509.NewCertPool() - if ok := caCertPool.AppendCertsFromPEM(bytes.TrimSpace(caCert)); !ok { - return nil, fmt.Errorf("failed to parse the CA Cert from %q", caCertPath) - } - tlsConfig.RootCAs = caCertPool - } - - tlsConfig.InsecureSkipVerify = func() bool { - if options.insecure != nil { - return *options.insecure - } - if cloud.Verify != nil { - return !*cloud.Verify - } - return false - }() - - if clientCertPath, clientKeyPath := coalesce(options.clientCertPath, os.Getenv("OS_CERT"), cloud.ClientCertFile), coalesce(options.clientKeyPath, os.Getenv("OS_KEY"), cloud.ClientKeyFile); clientCertPath != "" && clientKeyPath != "" { - clientCertPath, err := resolveTilde(clientCertPath) - if err != nil { - return nil, fmt.Errorf("failed to resolve user home directory in client cert path: %w", err) - } - clientKeyPath, err := resolveTilde(clientKeyPath) - if err != nil { - return nil, fmt.Errorf("failed to resolve user home directory in client cert key path: %w", err) - } - - clientCert, err := ioutil.ReadFile(clientCertPath) - if err != nil { - return nil, fmt.Errorf("failed to read the client cert file: %w", err) - } - - clientKey, err := ioutil.ReadFile(clientKeyPath) - if err != nil { - return nil, fmt.Errorf("failed to read the client cert key file: %w", err) - } - - cert, err := tls.X509KeyPair(clientCert, clientKey) - if err != nil { - return nil, err - } - - tlsConfig.Certificates = []tls.Certificate{cert} - } else if clientCertPath != "" && clientKeyPath == "" { - return nil, fmt.Errorf("client cert is set, but client cert key is missing") - } else if clientCertPath == "" && clientKeyPath != "" { - return nil, fmt.Errorf("client cert key is set, but client cert is missing") - } - - return tlsConfig, nil -} - -func resolveTilde(p string) (string, error) { - if after := strings.TrimPrefix(p, "~/"); after != p { - h, err := os.UserHomeDir() - if err != nil { - return "", fmt.Errorf("failed to resolve user home directory: %w", err) - } - return path.Join(h, after), nil - } - return p, nil -} diff --git a/openstack/config/clouds/types.go b/openstack/config/clouds/types.go deleted file mode 100644 index c1914633ff..0000000000 --- a/openstack/config/clouds/types.go +++ /dev/null @@ -1,203 +0,0 @@ -package clouds - -import "encoding/json" - -// Clouds represents a collection of Cloud entries in a clouds.yaml file. -// The format of clouds.yaml is documented at -// https://docs.openstack.org/os-client-config/latest/user/configuration.html. -type Clouds struct { - Clouds map[string]Cloud `yaml:"clouds" json:"clouds"` -} - -// Cloud represents an entry in a clouds.yaml/public-clouds.yaml/secure.yaml file. -type Cloud struct { - Cloud string `yaml:"cloud,omitempty" json:"cloud,omitempty"` - Profile string `yaml:"profile,omitempty" json:"profile,omitempty"` - AuthInfo *AuthInfo `yaml:"auth,omitempty" json:"auth,omitempty"` - AuthType AuthType `yaml:"auth_type,omitempty" json:"auth_type,omitempty"` - RegionName string `yaml:"region_name,omitempty" json:"region_name,omitempty"` - Regions []Region `yaml:"regions,omitempty" json:"regions,omitempty"` - - // EndpointType and Interface both specify whether to use the public, internal, - // or admin interface of a service. They should be considered synonymous, but - // EndpointType will take precedence when both are specified. - EndpointType string `yaml:"endpoint_type,omitempty" json:"endpoint_type,omitempty"` - Interface string `yaml:"interface,omitempty" json:"interface,omitempty"` - - // API Version overrides. - IdentityAPIVersion string `yaml:"identity_api_version,omitempty" json:"identity_api_version,omitempty"` - VolumeAPIVersion string `yaml:"volume_api_version,omitempty" json:"volume_api_version,omitempty"` - - // Verify whether or not SSL API requests should be verified. - Verify *bool `yaml:"verify,omitempty" json:"verify,omitempty"` - - // CACertFile a path to a CA Cert bundle that can be used as part of - // verifying SSL API requests. - CACertFile string `yaml:"cacert,omitempty" json:"cacert,omitempty"` - - // ClientCertFile a path to a client certificate to use as part of the SSL - // transaction. - ClientCertFile string `yaml:"cert,omitempty" json:"cert,omitempty"` - - // ClientKeyFile a path to a client key to use as part of the SSL - // transaction. - ClientKeyFile string `yaml:"key,omitempty" json:"key,omitempty"` -} - -// AuthInfo represents the auth section of a cloud entry or -// auth options entered explicitly in ClientOpts. -type AuthInfo struct { - // AuthURL is the keystone/identity endpoint URL. - AuthURL string `yaml:"auth_url,omitempty" json:"auth_url,omitempty"` - - // Token is a pre-generated authentication token. - Token string `yaml:"token,omitempty" json:"token,omitempty"` - - // Username is the username of the user. - Username string `yaml:"username,omitempty" json:"username,omitempty"` - - // UserID is the unique ID of a user. - UserID string `yaml:"user_id,omitempty" json:"user_id,omitempty"` - - // Password is the password of the user. - Password string `yaml:"password,omitempty" json:"password,omitempty"` - - // Application Credential ID to login with. - ApplicationCredentialID string `yaml:"application_credential_id,omitempty" json:"application_credential_id,omitempty"` - - // Application Credential name to login with. - ApplicationCredentialName string `yaml:"application_credential_name,omitempty" json:"application_credential_name,omitempty"` - - // Application Credential secret to login with. - ApplicationCredentialSecret string `yaml:"application_credential_secret,omitempty" json:"application_credential_secret,omitempty"` - - // SystemScope is a system information to scope to. - SystemScope string `yaml:"system_scope,omitempty" json:"system_scope,omitempty"` - - // ProjectName is the common/human-readable name of a project. - // Users can be scoped to a project. - // ProjectName on its own is not enough to ensure a unique scope. It must - // also be combined with either a ProjectDomainName or ProjectDomainID. - // ProjectName cannot be combined with ProjectID in a scope. - ProjectName string `yaml:"project_name,omitempty" json:"project_name,omitempty"` - - // ProjectID is the unique ID of a project. - // It can be used to scope a user to a specific project. - ProjectID string `yaml:"project_id,omitempty" json:"project_id,omitempty"` - - // UserDomainName is the name of the domain where a user resides. - // It is used to identify the source domain of a user. - UserDomainName string `yaml:"user_domain_name,omitempty" json:"user_domain_name,omitempty"` - - // UserDomainID is the unique ID of the domain where a user resides. - // It is used to identify the source domain of a user. - UserDomainID string `yaml:"user_domain_id,omitempty" json:"user_domain_id,omitempty"` - - // ProjectDomainName is the name of the domain where a project resides. - // It is used to identify the source domain of a project. - // ProjectDomainName can be used in addition to a ProjectName when scoping - // a user to a specific project. - ProjectDomainName string `yaml:"project_domain_name,omitempty" json:"project_domain_name,omitempty"` - - // ProjectDomainID is the name of the domain where a project resides. - // It is used to identify the source domain of a project. - // ProjectDomainID can be used in addition to a ProjectName when scoping - // a user to a specific project. - ProjectDomainID string `yaml:"project_domain_id,omitempty" json:"project_domain_id,omitempty"` - - // DomainName is the name of a domain which can be used to identify the - // source domain of either a user or a project. - // If UserDomainName and ProjectDomainName are not specified, then DomainName - // is used as a default choice. - // It can also be used be used to specify a domain-only scope. - DomainName string `yaml:"domain_name,omitempty" json:"domain_name,omitempty"` - - // DomainID is the unique ID of a domain which can be used to identify the - // source domain of eitehr a user or a project. - // If UserDomainID and ProjectDomainID are not specified, then DomainID is - // used as a default choice. - // It can also be used be used to specify a domain-only scope. - DomainID string `yaml:"domain_id,omitempty" json:"domain_id,omitempty"` - - // DefaultDomain is the domain ID to fall back on if no other domain has - // been specified and a domain is required for scope. - DefaultDomain string `yaml:"default_domain,omitempty" json:"default_domain,omitempty"` - - // AllowReauth should be set to true if you grant permission for Gophercloud to - // cache your credentials in memory, and to allow Gophercloud to attempt to - // re-authenticate automatically if/when your token expires. If you set it to - // false, it will not cache these settings, but re-authentication will not be - // possible. This setting defaults to false. - AllowReauth bool `yaml:"allow_reauth,omitempty" json:"allow_reauth,omitempty"` -} - -// Region represents a region included as part of cloud in clouds.yaml -// According to Python-based openstacksdk, this can be either a struct (as defined) -// or a plain string. Custom unmarshallers handle both cases. -type Region struct { - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Values Cloud `yaml:"values,omitempty" json:"values,omitempty"` -} - -// UnmarshalJSON handles either a plain string acting as the Name property or -// a struct, mimicking the Python-based openstacksdk. -func (r *Region) UnmarshalJSON(data []byte) error { - var name string - if err := json.Unmarshal(data, &name); err == nil { - r.Name = name - return nil - } - - type region Region - var tmp region - if err := json.Unmarshal(data, &tmp); err != nil { - return err - } - r.Name = tmp.Name - r.Values = tmp.Values - - return nil -} - -// UnmarshalYAML handles either a plain string acting as the Name property or -// a struct, mimicking the Python-based openstacksdk. -func (r *Region) UnmarshalYAML(unmarshal func(interface{}) error) error { - var name string - if err := unmarshal(&name); err == nil { - r.Name = name - return nil - } - - type region Region - var tmp region - if err := unmarshal(&tmp); err != nil { - return err - } - r.Name = tmp.Name - r.Values = tmp.Values - - return nil -} - -// AuthType respresents a valid method of authentication. -type AuthType string - -const ( - // AuthPassword defines an unknown version of the password - AuthPassword AuthType = "password" - // AuthToken defined an unknown version of the token - AuthToken AuthType = "token" - - // AuthV2Password defines version 2 of the password - AuthV2Password AuthType = "v2password" - // AuthV2Token defines version 2 of the token - AuthV2Token AuthType = "v2token" - - // AuthV3Password defines version 3 of the password - AuthV3Password AuthType = "v3password" - // AuthV3Token defines version 3 of the token - AuthV3Token AuthType = "v3token" - - // AuthV3ApplicationCredential defines version 3 of the application credential - AuthV3ApplicationCredential AuthType = "v3applicationcredential" -) diff --git a/openstack/config/provider_client.go b/openstack/config/provider_client.go deleted file mode 100644 index a26b3511bd..0000000000 --- a/openstack/config/provider_client.go +++ /dev/null @@ -1,70 +0,0 @@ -package config - -import ( - "context" - "crypto/tls" - "net/http" - - "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/openstack" -) - -type options struct { - httpClient http.Client - tlsConfig *tls.Config -} - -// WithHTTPClient enables passing a custom http.Client to be used in the -// ProviderClient for authentication and for any further call, for example when -// using a ServiceClient derived from this ProviderClient. -func WithHTTPClient(httpClient http.Client) func(*options) { - return func(o *options) { - o.httpClient = httpClient - } -} - -// WithTLSConfig replaces the Transport of the default HTTP client (or of the -// HTTP client passed with WithHTTPClient) with a RoundTripper containing the -// given TLS config. -func WithTLSConfig(tlsConfig *tls.Config) func(*options) { - return func(o *options) { - o.tlsConfig = tlsConfig - } -} - -// NewProviderClient logs in to an OpenStack cloud found at the identity -// endpoint specified by the options, acquires a token, and returns a Provider -// Client instance that's ready to operate. -// -// If the full path to a versioned identity endpoint was specified (example: -// http://example.com:5000/v3), that path will be used as the endpoint to -// query. -// -// If a versionless endpoint was specified (example: http://example.com:5000/), -// the endpoint will be queried to determine which versions of the identity -// service are available, then chooses the most recent or most supported -// version. -func NewProviderClient(ctx context.Context, authOptions gophercloud.AuthOptions, opts ...func(*options)) (*gophercloud.ProviderClient, error) { - var options options - for _, apply := range opts { - apply(&options) - } - - client, err := openstack.NewClient(authOptions.IdentityEndpoint) - if err != nil { - return nil, err - } - - if options.tlsConfig != nil { - transport := http.DefaultTransport.(*http.Transport).Clone() - transport.TLSClientConfig = options.tlsConfig - options.httpClient.Transport = transport - } - client.HTTPClient = options.httpClient - - err = openstack.AuthenticateWithContext(ctx, client, authOptions) - if err != nil { - return nil, err - } - return client, nil -} From 2e1a5f8891397c1007e3148eb31f0d3298b6686e Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 6 Mar 2024 16:52:52 +0100 Subject: [PATCH 079/118] Revert "pager: Add WithContext functions" This reverts commit 2dbf414e62b9b5f7d4080ef02119c8112097384d. --- pagination/http.go | 12 +++--------- pagination/pager.go | 34 ++++++++++------------------------ 2 files changed, 13 insertions(+), 33 deletions(-) diff --git a/pagination/http.go b/pagination/http.go index 13b3925232..7845cda13b 100644 --- a/pagination/http.go +++ b/pagination/http.go @@ -1,7 +1,6 @@ package pagination import ( - "context" "encoding/json" "io/ioutil" "net/http" @@ -53,16 +52,11 @@ func PageResultFromParsed(resp *http.Response, body interface{}) PageResult { } } -// RequestWithContext performs an HTTP request and extracts the http.Response from the result. -func RequestWithContext(ctx context.Context, client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) { - return client.GetWithContext(ctx, url, nil, &gophercloud.RequestOpts{ +// Request performs an HTTP request and extracts the http.Response from the result. +func Request(client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) { + return client.Get(url, nil, &gophercloud.RequestOpts{ MoreHeaders: headers, OkCodes: []int{200, 204, 300}, KeepResponseBody: true, }) } - -// Request is a compatibility wrapper around RequestWithContext. -func Request(client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) { - return RequestWithContext(context.Background(), client, headers, url) -} diff --git a/pagination/pager.go b/pagination/pager.go index 8bc6680804..1dec2703eb 100644 --- a/pagination/pager.go +++ b/pagination/pager.go @@ -1,7 +1,6 @@ package pagination import ( - "context" "errors" "fmt" "net/http" @@ -70,8 +69,8 @@ func (p Pager) WithPageCreator(createPage func(r PageResult) Page) Pager { } } -func (p Pager) fetchNextPage(ctx context.Context, url string) (Page, error) { - resp, err := RequestWithContext(ctx, p.client, p.Headers, url) +func (p Pager) fetchNextPage(url string) (Page, error) { + resp, err := Request(p.client, p.Headers, url) if err != nil { return nil, err } @@ -84,10 +83,9 @@ func (p Pager) fetchNextPage(ctx context.Context, url string) (Page, error) { return p.createPage(remembered), nil } -// EachPageWithContext iterates over each page returned by a Pager, yielding -// one at a time to a handler function. Return "false" from the handler to -// prematurely stop iterating. -func (p Pager) EachPageWithContext(ctx context.Context, handler func(context.Context, Page) (bool, error)) error { +// EachPage iterates over each page returned by a Pager, yielding one at a time to a handler function. +// Return "false" from the handler to prematurely stop iterating. +func (p Pager) EachPage(handler func(Page) (bool, error)) error { if p.Err != nil { return p.Err } @@ -101,7 +99,7 @@ func (p Pager) EachPageWithContext(ctx context.Context, handler func(context.Con p.firstPage = nil } else { var err error - currentPage, err = p.fetchNextPage(ctx, currentURL) + currentPage, err = p.fetchNextPage(currentURL) if err != nil { return err } @@ -115,7 +113,7 @@ func (p Pager) EachPageWithContext(ctx context.Context, handler func(context.Con return nil } - ok, err := handler(ctx, currentPage) + ok, err := handler(currentPage) if err != nil { return err } @@ -133,16 +131,9 @@ func (p Pager) EachPageWithContext(ctx context.Context, handler func(context.Con } } -// EachPage is a compatibility wrapper around EachPageWithContext. -func (p Pager) EachPage(handler func(Page) (bool, error)) error { - return p.EachPageWithContext(context.Background(), func(_ context.Context, p Page) (bool, error) { - return handler(p) - }) -} - -// AllPagesWithContext returns all the pages from a `List` operation in a single page, +// AllPages returns all the pages from a `List` operation in a single page, // allowing the user to retrieve all the pages at once. -func (p Pager) AllPagesWithContext(ctx context.Context) (Page, error) { +func (p Pager) AllPages() (Page, error) { if p.Err != nil { return nil, p.Err } @@ -152,7 +143,7 @@ func (p Pager) AllPagesWithContext(ctx context.Context) (Page, error) { var body reflect.Value // Grab a first page to ascertain the page body type. - firstPage, err := p.fetchNextPage(ctx, p.initialURL) + firstPage, err := p.fetchNextPage(p.initialURL) if err != nil { return nil, err } @@ -261,8 +252,3 @@ func (p Pager) AllPagesWithContext(ctx context.Context) (Page, error) { // `Extract*` methods will work. return page.Elem().Interface().(Page), err } - -// AllPages is a compatibility wrapper around AllPagesWithContext. -func (p Pager) AllPages() (Page, error) { - return p.AllPagesWithContext(context.Background()) -} From 4bd4c3832eca09554203475b75d8a67357c4a0f4 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 6 Mar 2024 16:53:11 +0100 Subject: [PATCH 080/118] Revert "client: Add WithContext functions" This reverts commit b8f25bcf0e63e86694f83f688a3fff660fcdd556. --- openstack/client.go | 123 +++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 70 deletions(-) diff --git a/openstack/client.go b/openstack/client.go index 8c6173a264..81c907c35b 100644 --- a/openstack/client.go +++ b/openstack/client.go @@ -1,7 +1,6 @@ package openstack import ( - "context" "fmt" "reflect" "strings" @@ -24,18 +23,20 @@ const ( v3 = "v3" ) -// NewClient prepares an unauthenticated ProviderClient instance. -// Most users will probably prefer using the AuthenticatedClient function -// instead. -// -// This is useful if you wish to explicitly control the version of the identity -// service that's used for authentication explicitly, for example. -// -// A basic example of using this would be: -// -// ao, err := openstack.AuthOptionsFromEnv() -// provider, err := openstack.NewClient(ao.IdentityEndpoint) -// client, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{}) +/* +NewClient prepares an unauthenticated ProviderClient instance. +Most users will probably prefer using the AuthenticatedClient function +instead. + +This is useful if you wish to explicitly control the version of the identity +service that's used for authentication explicitly, for example. + +A basic example of using this would be: + + ao, err := openstack.AuthOptionsFromEnv() + provider, err := openstack.NewClient(ao.IdentityEndpoint) + client, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{}) +*/ func NewClient(endpoint string) (*gophercloud.ProviderClient, error) { base, err := utils.BaseEndpoint(endpoint) if err != nil { @@ -53,45 +54,42 @@ func NewClient(endpoint string) (*gophercloud.ProviderClient, error) { return p, nil } -// AuthenticatedClientWithContext logs in to an OpenStack cloud found at the identity endpoint -// specified by the options, acquires a token, and returns a Provider Client -// instance that's ready to operate. -// -// If the full path to a versioned identity endpoint was specified (example: -// http://example.com:5000/v3), that path will be used as the endpoint to query. -// -// If a versionless endpoint was specified (example: http://example.com:5000/), -// the endpoint will be queried to determine which versions of the identity service -// are available, then chooses the most recent or most supported version. -// -// Example: -// -// ao, err := openstack.AuthOptionsFromEnv() -// provider, err := openstack.AuthenticatedClientWithContext(ctx, ao) -// client, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{ -// Region: os.Getenv("OS_REGION_NAME"), -// }) -func AuthenticatedClientWithContext(ctx context.Context, options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) { +/* +AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint +specified by the options, acquires a token, and returns a Provider Client +instance that's ready to operate. + +If the full path to a versioned identity endpoint was specified (example: +http://example.com:5000/v3), that path will be used as the endpoint to query. + +If a versionless endpoint was specified (example: http://example.com:5000/), +the endpoint will be queried to determine which versions of the identity service +are available, then chooses the most recent or most supported version. + +Example: + + ao, err := openstack.AuthOptionsFromEnv() + provider, err := openstack.AuthenticatedClient(ao) + client, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{ + Region: os.Getenv("OS_REGION_NAME"), + }) +*/ +func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) { client, err := NewClient(options.IdentityEndpoint) if err != nil { return nil, err } - err = AuthenticateWithContext(ctx, client, options) + err = Authenticate(client, options) if err != nil { return nil, err } return client, nil } -// AuthenticatedClient is a compatibility wrapper around AuthenticatedClientWithContext -func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) { - return AuthenticatedClientWithContext(context.Background(), options) -} - -// AuthenticateWithContext authenticates or re-authenticates against the most -// recent identity service supported at the provided endpoint. -func AuthenticateWithContext(ctx context.Context, client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { +// Authenticate or re-authenticate against the most recent identity service +// supported at the provided endpoint. +func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { versions := []*utils.Version{ {ID: v2, Priority: 20, Suffix: "/v2.0/"}, {ID: v3, Priority: 30, Suffix: "/v3/"}, @@ -104,31 +102,21 @@ func AuthenticateWithContext(ctx context.Context, client *gophercloud.ProviderCl switch chosen.ID { case v2: - return v2auth(ctx, client, endpoint, options, gophercloud.EndpointOpts{}) + return v2auth(client, endpoint, options, gophercloud.EndpointOpts{}) case v3: - return v3auth(ctx, client, endpoint, &options, gophercloud.EndpointOpts{}) + return v3auth(client, endpoint, &options, gophercloud.EndpointOpts{}) default: // The switch statement must be out of date from the versions list. return fmt.Errorf("Unrecognized identity version: %s", chosen.ID) } } -// Authenticate is a compatibility wrapper around AuthenticateWithContext. -func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { - return AuthenticateWithContext(context.Background(), client, options) -} - -// AuthenticateV2WithContext explicitly authenticates against the identity v2 endpoint. -func AuthenticateV2WithContext(ctx context.Context, client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { - return v2auth(ctx, client, "", options, eo) -} - -// AuthenticateV2 is a compatibility wrapper around AuthenticateV2WithContext. +// AuthenticateV2 explicitly authenticates against the identity v2 endpoint. func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { - return AuthenticateV2WithContext(context.Background(), client, options, eo) + return v2auth(client, "", options, eo) } -func v2auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { +func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { v2Client, err := NewIdentityV2(client, eo) if err != nil { return err @@ -148,7 +136,7 @@ func v2auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint st TokenID: options.TokenID, } - result := tokens2.CreateWithContext(ctx, v2Client, v2Opts) + result := tokens2.Create(v2Client, v2Opts) err = client.SetTokenAndAuthResult(result) if err != nil { @@ -171,7 +159,7 @@ func v2auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint st tao := options tao.AllowReauth = false client.ReauthFunc = func() error { - err := v2auth(ctx, &tac, endpoint, tao, eo) + err := v2auth(&tac, endpoint, tao, eo) if err != nil { return err } @@ -186,17 +174,12 @@ func v2auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint st return nil } -// AuthenticateV3WithContext explicitly authenticates against the identity v3 service. -func AuthenticateV3WithContext(ctx context.Context, client *gophercloud.ProviderClient, options tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { - return v3auth(ctx, client, "", options, eo) -} - -// AuthenticateV3 is a compatibility wrapper around AuthenticateV3WithContext +// AuthenticateV3 explicitly authenticates against the identity v3 service. func AuthenticateV3(client *gophercloud.ProviderClient, options tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { - return AuthenticateV3WithContext(context.Background(), client, options, eo) + return v3auth(client, "", options, eo) } -func v3auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint string, opts tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { +func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { // Override the generated service endpoint with the one returned by the version endpoint. v3Client, err := NewIdentityV3(client, eo) if err != nil { @@ -246,11 +229,11 @@ func v3auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint st var result tokens3.CreateResult switch opts.(type) { case *ec2tokens.AuthOptions: - result = ec2tokens.CreateWithContext(ctx, v3Client, opts) + result = ec2tokens.Create(v3Client, opts) case *oauth1.AuthOptions: - result = oauth1.CreateWithContext(ctx, v3Client, opts) + result = oauth1.Create(v3Client, opts) default: - result = tokens3.CreateWithContext(ctx, v3Client, opts) + result = tokens3.Create(v3Client, opts) } err = client.SetTokenAndAuthResult(result) @@ -294,7 +277,7 @@ func v3auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint st tao = opts } client.ReauthFunc = func() error { - err := v3auth(ctx, &tac, endpoint, tao, eo) + err := v3auth(&tac, endpoint, tao, eo) if err != nil { return err } From 6046211a881759d50fa63d922b47ceefbc908383 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 6 Mar 2024 16:53:19 +0100 Subject: [PATCH 081/118] Revert "tokens: Add WithContext functions" This reverts commit b0d7555b64cf64871644bdb3e3d8d97b2d65fc6d. --- openstack/identity/v2/tokens/requests.go | 26 +--- .../v3/extensions/ec2tokens/requests.go | 26 +--- .../identity/v3/extensions/oauth1/requests.go | 124 +++++------------- openstack/identity/v3/tokens/requests.go | 50 ++----- 4 files changed, 60 insertions(+), 166 deletions(-) diff --git a/openstack/identity/v2/tokens/requests.go b/openstack/identity/v2/tokens/requests.go index 67c04fced2..84f16c3fc2 100644 --- a/openstack/identity/v2/tokens/requests.go +++ b/openstack/identity/v2/tokens/requests.go @@ -1,10 +1,6 @@ package tokens -import ( - "context" - - "github.com/gophercloud/gophercloud" -) +import "github.com/gophercloud/gophercloud" // PasswordCredentialsV2 represents the required options to authenticate // with a username and password. @@ -81,17 +77,17 @@ func (opts AuthOptions) ToTokenV2CreateMap() (map[string]interface{}, error) { return b, nil } -// CreateWithContext authenticates to the identity service and attempts to acquire a Token. +// Create authenticates to the identity service and attempts to acquire a Token. // Generally, rather than interact with this call directly, end users should // call openstack.AuthenticatedClient(), which abstracts all of the gory details // about navigating service catalogs and such. -func CreateWithContext(ctx context.Context, client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) { +func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) { b, err := auth.ToTokenV2CreateMap() if err != nil { r.Err = err return } - resp, err := client.PostWithContext(ctx, CreateURL(client), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.Post(CreateURL(client), b, &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{200, 203}, OmitHeaders: []string{"X-Auth-Token"}, }) @@ -99,21 +95,11 @@ func CreateWithContext(ctx context.Context, client *gophercloud.ServiceClient, a return } -// Create is a compatibility wrapper around CreateWithContext -func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) { - return CreateWithContext(context.Background(), client, auth) -} - -// GetWithContext validates and retrieves information for user's token. -func GetWithContext(ctx context.Context, client *gophercloud.ServiceClient, token string) (r GetResult) { +// Get validates and retrieves information for user's token. +func Get(client *gophercloud.ServiceClient, token string) (r GetResult) { resp, err := client.Get(GetURL(client, token), &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{200, 203}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } - -// Get is a compatibility wrapper around GetWithContext -func Get(client *gophercloud.ServiceClient, token string) (r GetResult) { - return GetWithContext(context.Background(), client, token) -} diff --git a/openstack/identity/v3/extensions/ec2tokens/requests.go b/openstack/identity/v3/extensions/ec2tokens/requests.go index b5b5350c54..32ba0e621d 100644 --- a/openstack/identity/v3/extensions/ec2tokens/requests.go +++ b/openstack/identity/v3/extensions/ec2tokens/requests.go @@ -1,7 +1,6 @@ package ec2tokens import ( - "context" "crypto/hmac" "crypto/sha1" "crypto/sha256" @@ -288,8 +287,8 @@ func (opts *AuthOptions) ToTokenV3CreateMap(map[string]interface{}) (map[string] return b, nil } -// CreateWithContext authenticates and either generates a new token from EC2 credentials -func CreateWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { +// Create authenticates and either generates a new token from EC2 credentials +func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { b, err := opts.ToTokenV3CreateMap(nil) if err != nil { r.Err = err @@ -299,7 +298,7 @@ func CreateWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts t // delete "token" element, since it is used in s3tokens deleteBodyElements(b, "token") - resp, err := c.PostWithContext(ctx, ec2tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := c.Post(ec2tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{ MoreHeaders: map[string]string{"X-Auth-Token": ""}, OkCodes: []int{200}, }) @@ -307,15 +306,9 @@ func CreateWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts t return } -// Create is a compatibility wrapper around CreateWithContext -func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { - return CreateWithContext(context.Background(), c, opts) -} - -// ValidateS3TokenWithContext authenticates an S3 request using EC2 -// credentials. Doesn't generate a new token ID, but returns a -// tokens.CreateResult. -func ValidateS3TokenWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { +// ValidateS3Token authenticates an S3 request using EC2 credentials. Doesn't +// generate a new token ID, but returns a tokens.CreateResult. +func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { b, err := opts.ToTokenV3CreateMap(nil) if err != nil { r.Err = err @@ -325,7 +318,7 @@ func ValidateS3TokenWithContext(ctx context.Context, c *gophercloud.ServiceClien // delete unused element, since it is used in ec2tokens only deleteBodyElements(b, "body_hash", "headers", "host", "params", "path", "verb") - resp, err := c.PostWithContext(ctx, s3tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := c.Post(s3tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{ MoreHeaders: map[string]string{"X-Auth-Token": ""}, OkCodes: []int{200}, }) @@ -333,11 +326,6 @@ func ValidateS3TokenWithContext(ctx context.Context, c *gophercloud.ServiceClien return } -// ValidateS3Token is a compatibility wrapper around ValidateS3TokenWithContext -func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { - return ValidateS3TokenWithContext(context.Background(), c, opts) -} - // The following are small helper functions used to help build the signature. // sumHMAC1 is a func to implement the HMAC SHA1 signature method. diff --git a/openstack/identity/v3/extensions/oauth1/requests.go b/openstack/identity/v3/extensions/oauth1/requests.go index 9921056320..028b5a45bd 100644 --- a/openstack/identity/v3/extensions/oauth1/requests.go +++ b/openstack/identity/v3/extensions/oauth1/requests.go @@ -1,7 +1,6 @@ package oauth1 import ( - "context" "crypto/hmac" "crypto/sha1" "encoding/base64" @@ -134,9 +133,9 @@ func (opts AuthOptions) ToTokenV3CreateMap(map[string]interface{}) (map[string]i return gophercloud.BuildRequestBody(req, "") } -// CreateWithContext authenticates and either generates a new OpenStack token -// from an OAuth1 token. -func CreateWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { +// Create authenticates and either generates a new OpenStack token from an +// OAuth1 token. +func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { b, err := opts.ToTokenV3CreateMap(nil) if err != nil { r.Err = err @@ -154,7 +153,7 @@ func CreateWithContext(ctx context.Context, client *gophercloud.ServiceClient, o return } - resp, err := client.PostWithContext(ctx, authURL(client), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.Post(authURL(client), b, &r.Body, &gophercloud.RequestOpts{ MoreHeaders: h, OkCodes: []int{201}, }) @@ -162,11 +161,6 @@ func CreateWithContext(ctx context.Context, client *gophercloud.ServiceClient, o return } -// Create is a compatibility wrapper around CreateWithContext. -func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { - return CreateWithContext(context.Background(), client, opts) -} - // CreateConsumerOptsBuilder allows extensions to add additional parameters to // the CreateConsumer request. type CreateConsumerOptsBuilder interface { @@ -184,37 +178,27 @@ func (opts CreateConsumerOpts) ToOAuth1CreateConsumerMap() (map[string]interface return gophercloud.BuildRequestBody(opts, "consumer") } -// CreateConsumerWithContext creates a new Consumer. -func CreateConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts CreateConsumerOptsBuilder) (r CreateConsumerResult) { +// Create creates a new Consumer. +func CreateConsumer(client *gophercloud.ServiceClient, opts CreateConsumerOptsBuilder) (r CreateConsumerResult) { b, err := opts.ToOAuth1CreateConsumerMap() if err != nil { r.Err = err return } - resp, err := client.PostWithContext(ctx, consumersURL(client), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.Post(consumersURL(client), b, &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{201}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// CreateConsumer is a compatibility wrapper around CreateConsumerWithContext. -func CreateConsumer(client *gophercloud.ServiceClient, opts CreateConsumerOptsBuilder) (r CreateConsumerResult) { - return CreateConsumerWithContext(context.Background(), client, opts) -} - -// DeleteConsumerWithContext deletes a Consumer. -func DeleteConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string) (r DeleteConsumerResult) { - resp, err := client.DeleteWithContext(ctx, consumerURL(client, id), nil) +// Delete deletes a Consumer. +func DeleteConsumer(client *gophercloud.ServiceClient, id string) (r DeleteConsumerResult) { + resp, err := client.Delete(consumerURL(client, id), nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// DeleteConsumer is a compatibility wrapper around DeleteConsumerWithContext. -func DeleteConsumer(client *gophercloud.ServiceClient, id string) (r DeleteConsumerResult) { - return DeleteConsumerWithContext(context.Background(), client, id) -} - // List enumerates Consumers. func ListConsumers(client *gophercloud.ServiceClient) pagination.Pager { return pagination.NewPager(client, consumersURL(client), func(r pagination.PageResult) pagination.Page { @@ -222,18 +206,13 @@ func ListConsumers(client *gophercloud.ServiceClient) pagination.Pager { }) } -// GetConsumerWithContext retrieves details on a single Consumer by ID. -func GetConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetConsumerResult) { - resp, err := client.GetWithContext(ctx, consumerURL(client, id), &r.Body, nil) +// GetConsumer retrieves details on a single Consumer by ID. +func GetConsumer(client *gophercloud.ServiceClient, id string) (r GetConsumerResult) { + resp, err := client.Get(consumerURL(client, id), &r.Body, nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// GetConsumer is a compatibility wrapper around GetConsumerWithContext. -func GetConsumer(client *gophercloud.ServiceClient, id string) (r GetConsumerResult) { - return GetConsumerWithContext(context.Background(), client, id) -} - // UpdateConsumerOpts provides options used to update a consumer. type UpdateConsumerOpts struct { // Description is the consumer description. @@ -246,25 +225,20 @@ func (opts UpdateConsumerOpts) ToOAuth1UpdateConsumerMap() (map[string]interface return gophercloud.BuildRequestBody(opts, "consumer") } -// UpdateConsumerWithContext updates an existing Consumer. -func UpdateConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string, opts UpdateConsumerOpts) (r UpdateConsumerResult) { +// UpdateConsumer updates an existing Consumer. +func UpdateConsumer(client *gophercloud.ServiceClient, id string, opts UpdateConsumerOpts) (r UpdateConsumerResult) { b, err := opts.ToOAuth1UpdateConsumerMap() if err != nil { r.Err = err return } - resp, err := client.PatchWithContext(ctx, consumerURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.Patch(consumerURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{200}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// UpdateConsumer is a compatibility wrapper around UpdateConsumerWithContext. -func UpdateConsumer(client *gophercloud.ServiceClient, id string, opts UpdateConsumerOpts) (r UpdateConsumerResult) { - return UpdateConsumerWithContext(context.Background(), client, id, opts) -} - // RequestTokenOptsBuilder allows extensions to add additional parameters to the // RequestToken request. type RequestTokenOptsBuilder interface { @@ -323,15 +297,15 @@ func (opts RequestTokenOpts) ToOAuth1RequestTokenHeaders(method, u string) (map[ return h, nil } -// RequestTokenWithContext requests an unauthorized OAuth1 Token. -func RequestTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts RequestTokenOptsBuilder) (r TokenResult) { +// RequestToken requests an unauthorized OAuth1 Token. +func RequestToken(client *gophercloud.ServiceClient, opts RequestTokenOptsBuilder) (r TokenResult) { h, err := opts.ToOAuth1RequestTokenHeaders("POST", requestTokenURL(client)) if err != nil { r.Err = err return } - resp, err := client.PostWithContext(ctx, requestTokenURL(client), nil, nil, &gophercloud.RequestOpts{ + resp, err := client.Post(requestTokenURL(client), nil, nil, &gophercloud.RequestOpts{ MoreHeaders: h, OkCodes: []int{201}, KeepResponseBody: true, @@ -349,11 +323,6 @@ func RequestTokenWithContext(ctx context.Context, client *gophercloud.ServiceCli return } -// RequestToken is a compatibility wrapper around RequestTokenWithContext. -func RequestToken(client *gophercloud.ServiceClient, opts RequestTokenOptsBuilder) (r TokenResult) { - return RequestTokenWithContext(context.Background(), client, opts) -} - // AuthorizeTokenOptsBuilder allows extensions to add additional parameters to // the AuthorizeToken request. type AuthorizeTokenOptsBuilder interface { @@ -382,25 +351,20 @@ func (opts AuthorizeTokenOpts) ToOAuth1AuthorizeTokenMap() (map[string]interface return gophercloud.BuildRequestBody(opts, "") } -// AuthorizeTokenWithContext authorizes an unauthorized consumer token. -func AuthorizeTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string, opts AuthorizeTokenOptsBuilder) (r AuthorizeTokenResult) { +// AuthorizeToken authorizes an unauthorized consumer token. +func AuthorizeToken(client *gophercloud.ServiceClient, id string, opts AuthorizeTokenOptsBuilder) (r AuthorizeTokenResult) { b, err := opts.ToOAuth1AuthorizeTokenMap() if err != nil { r.Err = err return } - resp, err := client.PutWithContext(ctx, authorizeTokenURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.Put(authorizeTokenURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{200}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// AuthorizeToken is a compatibility wrapper around AuthorizeTokenWithContext. -func AuthorizeToken(client *gophercloud.ServiceClient, id string, opts AuthorizeTokenOptsBuilder) (r AuthorizeTokenResult) { - return AuthorizeTokenWithContext(context.Background(), client, id, opts) -} - // CreateAccessTokenOptsBuilder allows extensions to add additional parameters // to the CreateAccessToken request. type CreateAccessTokenOptsBuilder interface { @@ -461,15 +425,15 @@ func (opts CreateAccessTokenOpts) ToOAuth1CreateAccessTokenHeaders(method, u str return headers, nil } -// CreateAccessTokenWithContext creates a new OAuth1 Access Token -func CreateAccessTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts CreateAccessTokenOptsBuilder) (r TokenResult) { +// CreateAccessToken creates a new OAuth1 Access Token +func CreateAccessToken(client *gophercloud.ServiceClient, opts CreateAccessTokenOptsBuilder) (r TokenResult) { h, err := opts.ToOAuth1CreateAccessTokenHeaders("POST", createAccessTokenURL(client)) if err != nil { r.Err = err return } - resp, err := client.PostWithContext(ctx, createAccessTokenURL(client), nil, nil, &gophercloud.RequestOpts{ + resp, err := client.Post(createAccessTokenURL(client), nil, nil, &gophercloud.RequestOpts{ MoreHeaders: h, OkCodes: []int{201}, KeepResponseBody: true, @@ -487,33 +451,18 @@ func CreateAccessTokenWithContext(ctx context.Context, client *gophercloud.Servi return } -// CreateAccessToken is a compatibility wrapper around CreateAccessTokenWithContext. -func CreateAccessToken(client *gophercloud.ServiceClient, opts CreateAccessTokenOptsBuilder) (r TokenResult) { - return CreateAccessTokenWithContext(context.Background(), client, opts) -} - -// GetAccessTokenWithContext retrieves details on a single OAuth1 access token by an ID. -func GetAccessTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, userID string, id string) (r GetAccessTokenResult) { - resp, err := client.GetWithContext(ctx, userAccessTokenURL(client, userID, id), &r.Body, nil) - _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) - return -} - -// GetAccessToken is a compatibility wrapper around GetAccessTokenWithContext. +// GetAccessToken retrieves details on a single OAuth1 access token by an ID. func GetAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r GetAccessTokenResult) { - return GetAccessTokenWithContext(context.Background(), client, userID, id) -} - -// RevokeAccessTokenWithContext revokes an OAuth1 access token. -func RevokeAccessTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, userID string, id string) (r RevokeAccessTokenResult) { - resp, err := client.DeleteWithContext(ctx, userAccessTokenURL(client, userID, id), nil) + resp, err := client.Get(userAccessTokenURL(client, userID, id), &r.Body, nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// RevokeAccessToken is a compatibility wrapper around RevokeAccessTokenWithContext. +// RevokeAccessToken revokes an OAuth1 access token. func RevokeAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r RevokeAccessTokenResult) { - return RevokeAccessTokenWithContext(context.Background(), client, userID, id) + resp, err := client.Delete(userAccessTokenURL(client, userID, id), nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return } // ListAccessTokens enumerates authorized access tokens. @@ -532,19 +481,14 @@ func ListAccessTokenRoles(client *gophercloud.ServiceClient, userID string, id s }) } -// GetAccessTokenRoleWithContext retrieves details on a single OAuth1 access token role by +// GetAccessTokenRole retrieves details on a single OAuth1 access token role by // an ID. -func GetAccessTokenRoleWithContext(ctx context.Context, client *gophercloud.ServiceClient, userID string, id string, roleID string) (r GetAccessTokenRoleResult) { - resp, err := client.GetWithContext(ctx, userAccessTokenRoleURL(client, userID, id, roleID), &r.Body, nil) +func GetAccessTokenRole(client *gophercloud.ServiceClient, userID string, id string, roleID string) (r GetAccessTokenRoleResult) { + resp, err := client.Get(userAccessTokenRoleURL(client, userID, id, roleID), &r.Body, nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// GetAccessTokenRole is a compatibility wrapper around GetAccessTokenRoleWithContext. -func GetAccessTokenRole(client *gophercloud.ServiceClient, userID string, id string, roleID string) (r GetAccessTokenRoleResult) { - return GetAccessTokenRoleWithContext(context.Background(), client, userID, id, roleID) -} - // The following are small helper functions used to help build the signature. // buildOAuth1QueryString builds a URLEncoded parameters string specific for diff --git a/openstack/identity/v3/tokens/requests.go b/openstack/identity/v3/tokens/requests.go index d5b2fe83fd..1af55d8137 100644 --- a/openstack/identity/v3/tokens/requests.go +++ b/openstack/identity/v3/tokens/requests.go @@ -1,10 +1,6 @@ package tokens -import ( - "context" - - "github.com/gophercloud/gophercloud" -) +import "github.com/gophercloud/gophercloud" // Scope allows a created token to be limited to a specific domain or project. type Scope struct { @@ -123,9 +119,9 @@ func subjectTokenHeaders(subjectToken string) map[string]string { } } -// CreateWithContext authenticates and either generates a new token, or changes the Scope +// Create authenticates and either generates a new token, or changes the Scope // of an existing token. -func CreateWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) { +func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) { scope, err := opts.ToTokenV3ScopeMap() if err != nil { r.Err = err @@ -138,21 +134,16 @@ func CreateWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts A return } - resp, err := c.PostWithContext(ctx, tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := c.Post(tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{ OmitHeaders: []string{"X-Auth-Token"}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// Create is a compatibility wrapper around CreateWithContext -func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) { - return CreateWithContext(context.Background(), c, opts) -} - -// GetGetWithContext validates and retrieves information about another token. -func GetWithContext(ctx context.Context, c *gophercloud.ServiceClient, token string) (r GetResult) { - resp, err := c.GetWithContext(ctx, tokenURL(c), &r.Body, &gophercloud.RequestOpts{ +// Get validates and retrieves information about another token. +func Get(c *gophercloud.ServiceClient, token string) (r GetResult) { + resp, err := c.Get(tokenURL(c), &r.Body, &gophercloud.RequestOpts{ MoreHeaders: subjectTokenHeaders(token), OkCodes: []int{200, 203}, }) @@ -160,14 +151,9 @@ func GetWithContext(ctx context.Context, c *gophercloud.ServiceClient, token str return } -// Get is a compatibility wrapper around GetWithContext -func Get(c *gophercloud.ServiceClient, token string) (r GetResult) { - return GetWithContext(context.Background(), c, token) -} - -// ValidateWithContext determines if a specified token is valid or not. -func ValidateWithContext(ctx context.Context, c *gophercloud.ServiceClient, token string) (bool, error) { - resp, err := c.HeadWithContext(ctx, tokenURL(c), &gophercloud.RequestOpts{ +// Validate determines if a specified token is valid or not. +func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { + resp, err := c.Head(tokenURL(c), &gophercloud.RequestOpts{ MoreHeaders: subjectTokenHeaders(token), OkCodes: []int{200, 204, 404}, }) @@ -178,21 +164,11 @@ func ValidateWithContext(ctx context.Context, c *gophercloud.ServiceClient, toke return resp.StatusCode == 200 || resp.StatusCode == 204, nil } -// Validate is a compatibility wrapper around ValidateWithContext -func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { - return ValidateWithContext(context.Background(), c, token) -} - -// RevokeWithContext immediately makes specified token invalid. -func RevokeWithContext(ctx context.Context, c *gophercloud.ServiceClient, token string) (r RevokeResult) { - resp, err := c.DeleteWithContext(ctx, tokenURL(c), &gophercloud.RequestOpts{ +// Revoke immediately makes specified token invalid. +func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) { + resp, err := c.Delete(tokenURL(c), &gophercloud.RequestOpts{ MoreHeaders: subjectTokenHeaders(token), }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } - -// Revoke is a compatibility wrapper around RevokeWithContext -func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) { - return RevokeWithContext(context.Background(), c, token) -} From 322ccdf71b3ddd15c0f554a101822a42648624f8 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 6 Mar 2024 17:30:30 +0100 Subject: [PATCH 082/118] Revert "Context-aware methods to ProviderClient and ServiceClient" This reverts commit ef06ea2bef3b883355e3d109bbf4c48c4f40e8e0. --- internal/ctxt/context.go | 739 ------------------------------------ internal/ctxt/merge.go | 52 --- internal/ctxt/merge_test.go | 133 ------- provider_client.go | 45 +-- service_client.go | 76 +--- 5 files changed, 37 insertions(+), 1008 deletions(-) delete mode 100644 internal/ctxt/context.go delete mode 100644 internal/ctxt/merge.go delete mode 100644 internal/ctxt/merge_test.go diff --git a/internal/ctxt/context.go b/internal/ctxt/context.go deleted file mode 100644 index 2352583714..0000000000 --- a/internal/ctxt/context.go +++ /dev/null @@ -1,739 +0,0 @@ -package ctxt - -// This file is package context of the standard library that ships with Go -// v1.21.6. It has been vendored to import AfterFunc. -// -// Changes made to the original file: -// * replace "internal/reflectlite" with "reflect" in the imports -// * replace "any" with "interface{}" -// * remove the atomic.Int32 type that only exists for testing and is not -// compatible with Go v1.14. -// -// https://cs.opensource.google/go/go/+/refs/tags/go1.21.6:src/context/context.go - -import ( - "errors" - reflectlite "reflect" - "sync" - "sync/atomic" - "time" -) - -// A Context carries a deadline, a cancellation signal, and other values across -// API boundaries. -// -// Context's methods may be called by multiple goroutines simultaneously. -type Context interface { - // Deadline returns the time when work done on behalf of this context - // should be canceled. Deadline returns ok==false when no deadline is - // set. Successive calls to Deadline return the same results. - Deadline() (deadline time.Time, ok bool) - - // Done returns a channel that's closed when work done on behalf of this - // context should be canceled. Done may return nil if this context can - // never be canceled. Successive calls to Done return the same value. - // The close of the Done channel may happen asynchronously, - // after the cancel function returns. - // - // WithCancel arranges for Done to be closed when cancel is called; - // WithDeadline arranges for Done to be closed when the deadline - // expires; WithTimeout arranges for Done to be closed when the timeout - // elapses. - // - // Done is provided for use in select statements: - // - // // Stream generates values with DoSomething and sends them to out - // // until DoSomething returns an error or ctx.Done is closed. - // func Stream(ctx context.Context, out chan<- Value) error { - // for { - // v, err := DoSomething(ctx) - // if err != nil { - // return err - // } - // select { - // case <-ctx.Done(): - // return ctx.Err() - // case out <- v: - // } - // } - // } - // - // See https://blog.golang.org/pipelines for more examples of how to use - // a Done channel for cancellation. - Done() <-chan struct{} - - // If Done is not yet closed, Err returns nil. - // If Done is closed, Err returns a non-nil error explaining why: - // Canceled if the context was canceled - // or DeadlineExceeded if the context's deadline passed. - // After Err returns a non-nil error, successive calls to Err return the same error. - Err() error - - // Value returns the value associated with this context for key, or nil - // if no value is associated with key. Successive calls to Value with - // the same key returns the same result. - // - // Use context values only for request-scoped data that transits - // processes and API boundaries, not for passing optional parameters to - // functions. - // - // A key identifies a specific value in a Context. Functions that wish - // to store values in Context typically allocate a key in a global - // variable then use that key as the argument to context.WithValue and - // Context.Value. A key can be any type that supports equality; - // packages should define keys as an unexported type to avoid - // collisions. - // - // Packages that define a Context key should provide type-safe accessors - // for the values stored using that key: - // - // // Package user defines a User type that's stored in Contexts. - // package user - // - // import "context" - // - // // User is the type of value stored in the Contexts. - // type User struct {...} - // - // // key is an unexported type for keys defined in this package. - // // This prevents collisions with keys defined in other packages. - // type key int - // - // // userKey is the key for user.User values in Contexts. It is - // // unexported; clients use user.NewContext and user.FromContext - // // instead of using this key directly. - // var userKey key - // - // // NewContext returns a new Context that carries value u. - // func NewContext(ctx context.Context, u *User) context.Context { - // return context.WithValue(ctx, userKey, u) - // } - // - // // FromContext returns the User value stored in ctx, if any. - // func FromContext(ctx context.Context) (*User, bool) { - // u, ok := ctx.Value(userKey).(*User) - // return u, ok - // } - Value(key interface{}) interface{} -} - -// Canceled is the error returned by [Context.Err] when the context is canceled. -var Canceled = errors.New("context canceled") - -// DeadlineExceeded is the error returned by [Context.Err] when the context's -// deadline passes. -var DeadlineExceeded error = deadlineExceededError{} - -type deadlineExceededError struct{} - -func (deadlineExceededError) Error() string { return "context deadline exceeded" } -func (deadlineExceededError) Timeout() bool { return true } -func (deadlineExceededError) Temporary() bool { return true } - -// An emptyCtx is never canceled, has no values, and has no deadline. -// It is the common base of backgroundCtx and todoCtx. -type emptyCtx struct{} - -func (emptyCtx) Deadline() (deadline time.Time, ok bool) { - return -} - -func (emptyCtx) Done() <-chan struct{} { - return nil -} - -func (emptyCtx) Err() error { - return nil -} - -func (emptyCtx) Value(key interface{}) interface{} { - return nil -} - -type backgroundCtx struct{ emptyCtx } - -func (backgroundCtx) String() string { - return "context.Background" -} - -type todoCtx struct{ emptyCtx } - -func (todoCtx) String() string { - return "context.TODO" -} - -// Background returns a non-nil, empty [Context]. It is never canceled, has no -// values, and has no deadline. It is typically used by the main function, -// initialization, and tests, and as the top-level Context for incoming -// requests. -func Background() Context { - return backgroundCtx{} -} - -// TODO returns a non-nil, empty [Context]. Code should use context.TODO when -// it's unclear which Context to use or it is not yet available (because the -// surrounding function has not yet been extended to accept a Context -// parameter). -func TODO() Context { - return todoCtx{} -} - -// A CancelFunc tells an operation to abandon its work. -// A CancelFunc does not wait for the work to stop. -// A CancelFunc may be called by multiple goroutines simultaneously. -// After the first call, subsequent calls to a CancelFunc do nothing. -type CancelFunc func() - -// WithCancel returns a copy of parent with a new Done channel. The returned -// context's Done channel is closed when the returned cancel function is called -// or when the parent context's Done channel is closed, whichever happens first. -// -// Canceling this context releases resources associated with it, so code should -// call cancel as soon as the operations running in this Context complete. -func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { - c := withCancel(parent) - return c, func() { c.cancel(true, Canceled, nil) } -} - -// A CancelCauseFunc behaves like a [CancelFunc] but additionally sets the cancellation cause. -// This cause can be retrieved by calling [Cause] on the canceled Context or on -// any of its derived Contexts. -// -// If the context has already been canceled, CancelCauseFunc does not set the cause. -// For example, if childContext is derived from parentContext: -// - if parentContext is canceled with cause1 before childContext is canceled with cause2, -// then Cause(parentContext) == Cause(childContext) == cause1 -// - if childContext is canceled with cause2 before parentContext is canceled with cause1, -// then Cause(parentContext) == cause1 and Cause(childContext) == cause2 -type CancelCauseFunc func(cause error) - -// WithCancelCause behaves like [WithCancel] but returns a [CancelCauseFunc] instead of a [CancelFunc]. -// Calling cancel with a non-nil error (the "cause") records that error in ctx; -// it can then be retrieved using Cause(ctx). -// Calling cancel with nil sets the cause to Canceled. -// -// Example use: -// -// ctx, cancel := context.WithCancelCause(parent) -// cancel(myError) -// ctx.Err() // returns context.Canceled -// context.Cause(ctx) // returns myError -func WithCancelCause(parent Context) (ctx Context, cancel CancelCauseFunc) { - c := withCancel(parent) - return c, func(cause error) { c.cancel(true, Canceled, cause) } -} - -func withCancel(parent Context) *cancelCtx { - if parent == nil { - panic("cannot create context from nil parent") - } - c := &cancelCtx{} - c.propagateCancel(parent, c) - return c -} - -// Cause returns a non-nil error explaining why c was canceled. -// The first cancellation of c or one of its parents sets the cause. -// If that cancellation happened via a call to CancelCauseFunc(err), -// then [Cause] returns err. -// Otherwise Cause(c) returns the same value as c.Err(). -// Cause returns nil if c has not been canceled yet. -func Cause(c Context) error { - if cc, ok := c.Value(&cancelCtxKey).(*cancelCtx); ok { - cc.mu.Lock() - defer cc.mu.Unlock() - return cc.cause - } - return nil -} - -// AfterFunc arranges to call f in its own goroutine after ctx is done -// (cancelled or timed out). -// If ctx is already done, AfterFunc calls f immediately in its own goroutine. -// -// Multiple calls to AfterFunc on a context operate independently; -// one does not replace another. -// -// Calling the returned stop function stops the association of ctx with f. -// It returns true if the call stopped f from being run. -// If stop returns false, -// either the context is done and f has been started in its own goroutine; -// or f was already stopped. -// The stop function does not wait for f to complete before returning. -// If the caller needs to know whether f is completed, -// it must coordinate with f explicitly. -// -// If ctx has a "AfterFunc(func()) func() bool" method, -// AfterFunc will use it to schedule the call. -func AfterFunc(ctx Context, f func()) (stop func() bool) { - a := &afterFuncCtx{ - f: f, - } - a.cancelCtx.propagateCancel(ctx, a) - return func() bool { - stopped := false - a.once.Do(func() { - stopped = true - }) - if stopped { - a.cancel(true, Canceled, nil) - } - return stopped - } -} - -type afterFuncer interface { - AfterFunc(func()) func() bool -} - -type afterFuncCtx struct { - cancelCtx - once sync.Once // either starts running f or stops f from running - f func() -} - -func (a *afterFuncCtx) cancel(removeFromParent bool, err, cause error) { - a.cancelCtx.cancel(false, err, cause) - if removeFromParent { - removeChild(a.Context, a) - } - a.once.Do(func() { - go a.f() - }) -} - -// A stopCtx is used as the parent context of a cancelCtx when -// an AfterFunc has been registered with the parent. -// It holds the stop function used to unregister the AfterFunc. -type stopCtx struct { - Context - stop func() bool -} - -// &cancelCtxKey is the key that a cancelCtx returns itself for. -var cancelCtxKey int - -// parentCancelCtx returns the underlying *cancelCtx for parent. -// It does this by looking up parent.Value(&cancelCtxKey) to find -// the innermost enclosing *cancelCtx and then checking whether -// parent.Done() matches that *cancelCtx. (If not, the *cancelCtx -// has been wrapped in a custom implementation providing a -// different done channel, in which case we should not bypass it.) -func parentCancelCtx(parent Context) (*cancelCtx, bool) { - done := parent.Done() - if done == closedchan || done == nil { - return nil, false - } - p, ok := parent.Value(&cancelCtxKey).(*cancelCtx) - if !ok { - return nil, false - } - pdone, _ := p.done.Load().(chan struct{}) - if pdone != done { - return nil, false - } - return p, true -} - -// removeChild removes a context from its parent. -func removeChild(parent Context, child canceler) { - if s, ok := parent.(stopCtx); ok { - s.stop() - return - } - p, ok := parentCancelCtx(parent) - if !ok { - return - } - p.mu.Lock() - if p.children != nil { - delete(p.children, child) - } - p.mu.Unlock() -} - -// A canceler is a context type that can be canceled directly. The -// implementations are *cancelCtx and *timerCtx. -type canceler interface { - cancel(removeFromParent bool, err, cause error) - Done() <-chan struct{} -} - -// closedchan is a reusable closed channel. -var closedchan = make(chan struct{}) - -func init() { - close(closedchan) -} - -// A cancelCtx can be canceled. When canceled, it also cancels any children -// that implement canceler. -type cancelCtx struct { - Context - - mu sync.Mutex // protects following fields - done atomic.Value // of chan struct{}, created lazily, closed by first cancel call - children map[canceler]struct{} // set to nil by the first cancel call - err error // set to non-nil by the first cancel call - cause error // set to non-nil by the first cancel call -} - -func (c *cancelCtx) Value(key interface{}) interface{} { - if key == &cancelCtxKey { - return c - } - return value(c.Context, key) -} - -func (c *cancelCtx) Done() <-chan struct{} { - d := c.done.Load() - if d != nil { - return d.(chan struct{}) - } - c.mu.Lock() - defer c.mu.Unlock() - d = c.done.Load() - if d == nil { - d = make(chan struct{}) - c.done.Store(d) - } - return d.(chan struct{}) -} - -func (c *cancelCtx) Err() error { - c.mu.Lock() - err := c.err - c.mu.Unlock() - return err -} - -// propagateCancel arranges for child to be canceled when parent is. -// It sets the parent context of cancelCtx. -func (c *cancelCtx) propagateCancel(parent Context, child canceler) { - c.Context = parent - - done := parent.Done() - if done == nil { - return // parent is never canceled - } - - select { - case <-done: - // parent is already canceled - child.cancel(false, parent.Err(), Cause(parent)) - return - default: - } - - if p, ok := parentCancelCtx(parent); ok { - // parent is a *cancelCtx, or derives from one. - p.mu.Lock() - if p.err != nil { - // parent has already been canceled - child.cancel(false, p.err, p.cause) - } else { - if p.children == nil { - p.children = make(map[canceler]struct{}) - } - p.children[child] = struct{}{} - } - p.mu.Unlock() - return - } - - if a, ok := parent.(afterFuncer); ok { - // parent implements an AfterFunc method. - c.mu.Lock() - stop := a.AfterFunc(func() { - child.cancel(false, parent.Err(), Cause(parent)) - }) - c.Context = stopCtx{ - Context: parent, - stop: stop, - } - c.mu.Unlock() - return - } - - go func() { - select { - case <-parent.Done(): - child.cancel(false, parent.Err(), Cause(parent)) - case <-child.Done(): - } - }() -} - -type stringer interface { - String() string -} - -func contextName(c Context) string { - if s, ok := c.(stringer); ok { - return s.String() - } - return reflectlite.TypeOf(c).String() -} - -func (c *cancelCtx) String() string { - return contextName(c.Context) + ".WithCancel" -} - -// cancel closes c.done, cancels each of c's children, and, if -// removeFromParent is true, removes c from its parent's children. -// cancel sets c.cause to cause if this is the first time c is canceled. -func (c *cancelCtx) cancel(removeFromParent bool, err, cause error) { - if err == nil { - panic("context: internal error: missing cancel error") - } - if cause == nil { - cause = err - } - c.mu.Lock() - if c.err != nil { - c.mu.Unlock() - return // already canceled - } - c.err = err - c.cause = cause - d, _ := c.done.Load().(chan struct{}) - if d == nil { - c.done.Store(closedchan) - } else { - close(d) - } - for child := range c.children { - // NOTE: acquiring the child's lock while holding parent's lock. - child.cancel(false, err, cause) - } - c.children = nil - c.mu.Unlock() - - if removeFromParent { - removeChild(c.Context, c) - } -} - -// WithoutCancel returns a copy of parent that is not canceled when parent is canceled. -// The returned context returns no Deadline or Err, and its Done channel is nil. -// Calling [Cause] on the returned context returns nil. -func WithoutCancel(parent Context) Context { - if parent == nil { - panic("cannot create context from nil parent") - } - return withoutCancelCtx{parent} -} - -type withoutCancelCtx struct { - c Context -} - -func (withoutCancelCtx) Deadline() (deadline time.Time, ok bool) { - return -} - -func (withoutCancelCtx) Done() <-chan struct{} { - return nil -} - -func (withoutCancelCtx) Err() error { - return nil -} - -func (c withoutCancelCtx) Value(key interface{}) interface{} { - return value(c, key) -} - -func (c withoutCancelCtx) String() string { - return contextName(c.c) + ".WithoutCancel" -} - -// WithDeadline returns a copy of the parent context with the deadline adjusted -// to be no later than d. If the parent's deadline is already earlier than d, -// WithDeadline(parent, d) is semantically equivalent to parent. The returned -// [Context.Done] channel is closed when the deadline expires, when the returned -// cancel function is called, or when the parent context's Done channel is -// closed, whichever happens first. -// -// Canceling this context releases resources associated with it, so code should -// call cancel as soon as the operations running in this [Context] complete. -func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) { - return WithDeadlineCause(parent, d, nil) -} - -// WithDeadlineCause behaves like [WithDeadline] but also sets the cause of the -// returned Context when the deadline is exceeded. The returned [CancelFunc] does -// not set the cause. -func WithDeadlineCause(parent Context, d time.Time, cause error) (Context, CancelFunc) { - if parent == nil { - panic("cannot create context from nil parent") - } - if cur, ok := parent.Deadline(); ok && cur.Before(d) { - // The current deadline is already sooner than the new one. - return WithCancel(parent) - } - c := &timerCtx{ - deadline: d, - } - c.cancelCtx.propagateCancel(parent, c) - dur := time.Until(d) - if dur <= 0 { - c.cancel(true, DeadlineExceeded, cause) // deadline has already passed - return c, func() { c.cancel(false, Canceled, nil) } - } - c.mu.Lock() - defer c.mu.Unlock() - if c.err == nil { - c.timer = time.AfterFunc(dur, func() { - c.cancel(true, DeadlineExceeded, cause) - }) - } - return c, func() { c.cancel(true, Canceled, nil) } -} - -// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to -// implement Done and Err. It implements cancel by stopping its timer then -// delegating to cancelCtx.cancel. -type timerCtx struct { - cancelCtx - timer *time.Timer // Under cancelCtx.mu. - - deadline time.Time -} - -func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { - return c.deadline, true -} - -func (c *timerCtx) String() string { - return contextName(c.cancelCtx.Context) + ".WithDeadline(" + - c.deadline.String() + " [" + - time.Until(c.deadline).String() + "])" -} - -func (c *timerCtx) cancel(removeFromParent bool, err, cause error) { - c.cancelCtx.cancel(false, err, cause) - if removeFromParent { - // Remove this timerCtx from its parent cancelCtx's children. - removeChild(c.cancelCtx.Context, c) - } - c.mu.Lock() - if c.timer != nil { - c.timer.Stop() - c.timer = nil - } - c.mu.Unlock() -} - -// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). -// -// Canceling this context releases resources associated with it, so code should -// call cancel as soon as the operations running in this [Context] complete: -// -// func slowOperationWithTimeout(ctx context.Context) (Result, error) { -// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) -// defer cancel() // releases resources if slowOperation completes before timeout elapses -// return slowOperation(ctx) -// } -func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { - return WithDeadline(parent, time.Now().Add(timeout)) -} - -// WithTimeoutCause behaves like [WithTimeout] but also sets the cause of the -// returned Context when the timeout expires. The returned [CancelFunc] does -// not set the cause. -func WithTimeoutCause(parent Context, timeout time.Duration, cause error) (Context, CancelFunc) { - return WithDeadlineCause(parent, time.Now().Add(timeout), cause) -} - -// WithValue returns a copy of parent in which the value associated with key is -// val. -// -// Use context Values only for request-scoped data that transits processes and -// APIs, not for passing optional parameters to functions. -// -// The provided key must be comparable and should not be of type -// string or any other built-in type to avoid collisions between -// packages using context. Users of WithValue should define their own -// types for keys. To avoid allocating when assigning to an -// interface{}, context keys often have concrete type -// struct{}. Alternatively, exported context key variables' static -// type should be a pointer or interface. -func WithValue(parent Context, key, val interface{}) Context { - if parent == nil { - panic("cannot create context from nil parent") - } - if key == nil { - panic("nil key") - } - if !reflectlite.TypeOf(key).Comparable() { - panic("key is not comparable") - } - return &valueCtx{parent, key, val} -} - -// A valueCtx carries a key-value pair. It implements Value for that key and -// delegates all other calls to the embedded Context. -type valueCtx struct { - Context - key, val interface{} -} - -// stringify tries a bit to stringify v, without using fmt, since we don't -// want context depending on the unicode tables. This is only used by -// *valueCtx.String(). -func stringify(v interface{}) string { - switch s := v.(type) { - case stringer: - return s.String() - case string: - return s - } - return "" -} - -func (c *valueCtx) String() string { - return contextName(c.Context) + ".WithValue(type " + - reflectlite.TypeOf(c.key).String() + - ", val " + stringify(c.val) + ")" -} - -func (c *valueCtx) Value(key interface{}) interface{} { - if c.key == key { - return c.val - } - return value(c.Context, key) -} - -func value(c Context, key interface{}) interface{} { - for { - switch ctx := c.(type) { - case *valueCtx: - if key == ctx.key { - return ctx.val - } - c = ctx.Context - case *cancelCtx: - if key == &cancelCtxKey { - return c - } - c = ctx.Context - case withoutCancelCtx: - if key == &cancelCtxKey { - // This implements Cause(ctx) == nil - // when ctx is created using WithoutCancel. - return nil - } - c = ctx.c - case *timerCtx: - if key == &cancelCtxKey { - return &ctx.cancelCtx - } - c = ctx.Context - case backgroundCtx, todoCtx: - return nil - default: - return c.Value(key) - } - } -} diff --git a/internal/ctxt/merge.go b/internal/ctxt/merge.go deleted file mode 100644 index 7604c78e6e..0000000000 --- a/internal/ctxt/merge.go +++ /dev/null @@ -1,52 +0,0 @@ -// package ctxt implements context merging. -package ctxt - -import ( - "context" - "time" -) - -type mergeContext struct { - context.Context - ctx2 context.Context -} - -// Merge returns a context that is cancelled when at least one of the parents -// is cancelled. The returned context also returns the values of ctx1, or ctx2 -// if nil. -func Merge(ctx1, ctx2 context.Context) (context.Context, context.CancelFunc) { - ctx, cancel := WithCancelCause(ctx1) - stop := AfterFunc(ctx2, func() { - cancel(Cause(ctx2)) - }) - - return &mergeContext{ - Context: ctx, - ctx2: ctx2, - }, func() { - stop() - cancel(context.Canceled) - } -} - -// Value returns ctx2's value if ctx's is nil. -func (ctx *mergeContext) Value(key interface{}) interface{} { - if v := ctx.Context.Value(key); v != nil { - return v - } - return ctx.ctx2.Value(key) -} - -// Deadline returns the earlier deadline of the two parents of ctx. -func (ctx *mergeContext) Deadline() (time.Time, bool) { - if d1, ok := ctx.Context.Deadline(); ok { - if d2, ok := ctx.ctx2.Deadline(); ok { - if d1.Before(d2) { - return d1, true - } - return d2, true - } - return d1, ok - } - return ctx.ctx2.Deadline() -} diff --git a/internal/ctxt/merge_test.go b/internal/ctxt/merge_test.go deleted file mode 100644 index c111ae7a09..0000000000 --- a/internal/ctxt/merge_test.go +++ /dev/null @@ -1,133 +0,0 @@ -package ctxt_test - -import ( - "context" - "testing" - "time" - - "github.com/gophercloud/gophercloud/internal/ctxt" -) - -func TestMerge(t *testing.T) { - t.Run("returns values from both parents", func(t *testing.T) { - ctx1 := context.WithValue(context.Background(), - "key1", "value1") - - ctx2 := context.WithValue(context.WithValue(context.Background(), - "key1", "this value should be overridden"), - "key2", "value2") - - ctx, cancel := ctxt.Merge(ctx1, ctx2) - defer cancel() - - if v1 := ctx.Value("key1"); v1 != nil { - if s1, ok := v1.(string); ok { - if s1 != "value1" { - t.Errorf("found value for key1 %q, expected %q", s1, "value1") - } - } else { - t.Errorf("key1 is not the expected type string") - } - } else { - t.Errorf("key1 returned nil") - } - - if v2 := ctx.Value("key2"); v2 != nil { - if s2, ok := v2.(string); ok { - if s2 != "value2" { - t.Errorf("found value for key2 %q, expected %q", s2, "value2") - } - } else { - t.Errorf("key2 is not the expected type string") - } - } else { - t.Errorf("key2 returned nil") - } - }) - - t.Run("first parent cancels", func(t *testing.T) { - ctx1, cancel1 := context.WithCancel(context.Background()) - ctx2, cancel2 := context.WithCancel(context.Background()) - defer cancel2() - - ctx, cancel := ctxt.Merge(ctx1, ctx2) - defer cancel() - - if err := ctx.Err(); err != nil { - t.Errorf("context unexpectedly done: %v", err) - } - - cancel1() - time.Sleep(1 * time.Millisecond) - if err := ctx.Err(); err == nil { - t.Errorf("context not done despite parent1 cancelled") - } - }) - - t.Run("second parent cancels", func(t *testing.T) { - ctx1, cancel1 := context.WithCancel(context.Background()) - ctx2, cancel2 := context.WithCancel(context.Background()) - defer cancel1() - - ctx, cancel := ctxt.Merge(ctx1, ctx2) - defer cancel() - - if err := ctx.Err(); err != nil { - t.Errorf("context unexpectedly done: %v", err) - } - - cancel2() - time.Sleep(1 * time.Millisecond) - if err := ctx.Err(); err == nil { - t.Errorf("context not done despite parent2 cancelled") - } - }) - - t.Run("inherits deadline from first parent", func(t *testing.T) { - now := time.Now() - t1 := now.Add(time.Hour) - t2 := t1.Add(time.Second) - - ctx1, cancel1 := context.WithDeadline(context.Background(), t1) - ctx2, cancel2 := context.WithDeadline(context.Background(), t2) - defer cancel1() - defer cancel2() - - ctx, cancel := ctxt.Merge(ctx1, ctx2) - defer cancel() - - if err := ctx.Err(); err != nil { - t.Errorf("context unexpectedly done: %v", err) - } - - if deadline, ok := ctx.Deadline(); ok { - if deadline != t1 { - t.Errorf("expected deadline to be %v, found %v", t1, deadline) - } - } - }) - - t.Run("inherits deadline from second parent", func(t *testing.T) { - now := time.Now() - t2 := now.Add(time.Hour) - t1 := t2.Add(time.Second) - - ctx1, cancel1 := context.WithDeadline(context.Background(), t1) - ctx2, cancel2 := context.WithDeadline(context.Background(), t2) - defer cancel1() - defer cancel2() - - ctx, cancel := ctxt.Merge(ctx1, ctx2) - defer cancel() - - if err := ctx.Err(); err != nil { - t.Errorf("context unexpectedly done: %v", err) - } - - if deadline, ok := ctx.Deadline(); ok { - if deadline != t2 { - t.Errorf("expected deadline to be %v, found %v", t2, deadline) - } - } - }) -} diff --git a/provider_client.go b/provider_client.go index 64787e5337..add4744ec5 100644 --- a/provider_client.go +++ b/provider_client.go @@ -10,8 +10,6 @@ import ( "net/http" "strings" "sync" - - "github.com/gophercloud/gophercloud/internal/ctxt" ) // DefaultUserAgent is the default User-Agent string set in the request header. @@ -90,9 +88,7 @@ type ProviderClient struct { // with the token and reauth func zeroed. Such client can be used to perform reauthorization. Throwaway bool - // Context is the context passed to the HTTP request. Values set on the - // per-call context, when available, override values set on this - // context. + // Context is the context passed to the HTTP request. Context context.Context // Retry backoff func is called when rate limited. @@ -356,20 +352,15 @@ type requestState struct { var applicationJSON = "application/json" -// RequestWithContext performs an HTTP request using the ProviderClient's -// current HTTPClient. An authentication header will automatically be provided. -func (client *ProviderClient) RequestWithContext(ctx context.Context, method, url string, options *RequestOpts) (*http.Response, error) { - return client.doRequest(ctx, method, url, options, &requestState{ +// Request performs an HTTP request using the ProviderClient's current HTTPClient. An authentication +// header will automatically be provided. +func (client *ProviderClient) Request(method, url string, options *RequestOpts) (*http.Response, error) { + return client.doRequest(method, url, options, &requestState{ hasReauthenticated: false, }) } -// Request is a compatibility wrapper for Request. -func (client *ProviderClient) Request(method, url string, options *RequestOpts) (*http.Response, error) { - return client.RequestWithContext(context.Background(), method, url, options) -} - -func (client *ProviderClient) doRequest(ctx context.Context, method, url string, options *RequestOpts, state *requestState) (*http.Response, error) { +func (client *ProviderClient) doRequest(method, url string, options *RequestOpts, state *requestState) (*http.Response, error) { var body io.Reader var contentType *string @@ -398,16 +389,14 @@ func (client *ProviderClient) doRequest(ctx context.Context, method, url string, body = options.RawBody } - if client.Context != nil { - var cancel context.CancelFunc - ctx, cancel = ctxt.Merge(ctx, client.Context) - defer cancel() - } - - req, err := http.NewRequestWithContext(ctx, method, url, body) + // Construct the http.Request. + req, err := http.NewRequest(method, url, body) if err != nil { return nil, err } + if client.Context != nil { + req = req.WithContext(client.Context) + } // Populate the request headers. // Apply options.MoreHeaders and options.OmitHeaders, to give the caller the chance to @@ -443,12 +432,12 @@ func (client *ProviderClient) doRequest(ctx context.Context, method, url string, if client.RetryFunc != nil { var e error state.retries = state.retries + 1 - e = client.RetryFunc(ctx, method, url, options, err, state.retries) + e = client.RetryFunc(client.Context, method, url, options, err, state.retries) if e != nil { return nil, e } - return client.doRequest(ctx, method, url, options, state) + return client.doRequest(method, url, options, state) } return nil, err } @@ -502,7 +491,7 @@ func (client *ProviderClient) doRequest(ctx context.Context, method, url string, } } state.hasReauthenticated = true - resp, err = client.doRequest(ctx, method, url, options, state) + resp, err = client.doRequest(method, url, options, state) if err != nil { switch err.(type) { case *ErrUnexpectedResponseCode: @@ -567,7 +556,7 @@ func (client *ProviderClient) doRequest(ctx context.Context, method, url string, return resp, e } - return client.doRequest(ctx, method, url, options, state) + return client.doRequest(method, url, options, state) } case http.StatusInternalServerError: err = ErrDefault500{respErr} @@ -603,7 +592,7 @@ func (client *ProviderClient) doRequest(ctx context.Context, method, url string, return resp, e } - return client.doRequest(ctx, method, url, options, state) + return client.doRequest(method, url, options, state) } return resp, err @@ -627,7 +616,7 @@ func (client *ProviderClient) doRequest(ctx context.Context, method, url string, return resp, e } - return client.doRequest(ctx, method, url, options, state) + return client.doRequest(method, url, options, state) } return nil, err } diff --git a/service_client.go b/service_client.go index b8e6fd1a38..94a161e340 100644 --- a/service_client.go +++ b/service_client.go @@ -1,7 +1,6 @@ package gophercloud import ( - "context" "io" "net/http" "strings" @@ -60,88 +59,58 @@ func (client *ServiceClient) initReqOpts(JSONBody interface{}, JSONResponse inte } } -// GetWithContext calls `Request` with the "GET" HTTP verb. -func (client *ServiceClient) GetWithContext(ctx context.Context, url string, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { - if opts == nil { - opts = new(RequestOpts) - } - client.initReqOpts(nil, JSONResponse, opts) - return client.RequestWithContext(ctx, "GET", url, opts) -} - -// Get is a compatibility wrapper for GetWithContext. +// Get calls `Request` with the "GET" HTTP verb. func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { - return client.GetWithContext(context.Background(), url, JSONResponse, opts) -} - -// PostWithContext calls `Request` with the "POST" HTTP verb. -func (client *ServiceClient) PostWithContext(ctx context.Context, url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = new(RequestOpts) } - client.initReqOpts(JSONBody, JSONResponse, opts) - return client.RequestWithContext(ctx, "POST", url, opts) + client.initReqOpts(nil, JSONResponse, opts) + return client.Request("GET", url, opts) } -// Post is a compatibility wrapper for PostWithContext. +// Post calls `Request` with the "POST" HTTP verb. func (client *ServiceClient) Post(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { - return client.PostWithContext(context.Background(), url, JSONBody, JSONResponse, opts) -} - -// PutWithContext calls `Request` with the "PUT" HTTP verb. -func (client *ServiceClient) PutWithContext(ctx context.Context, url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = new(RequestOpts) } client.initReqOpts(JSONBody, JSONResponse, opts) - return client.RequestWithContext(ctx, "PUT", url, opts) + return client.Request("POST", url, opts) } -// Put is a compatibility wrapper for PurWithContext. +// Put calls `Request` with the "PUT" HTTP verb. func (client *ServiceClient) Put(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { - return client.PutWithContext(context.Background(), url, JSONBody, JSONResponse, opts) -} - -// PatchWithContext calls `Request` with the "PATCH" HTTP verb. -func (client *ServiceClient) PatchWithContext(ctx context.Context, url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = new(RequestOpts) } client.initReqOpts(JSONBody, JSONResponse, opts) - return client.RequestWithContext(ctx, "PATCH", url, opts) + return client.Request("PUT", url, opts) } -// Patch is a compatibility wrapper for PatchWithContext. +// Patch calls `Request` with the "PATCH" HTTP verb. func (client *ServiceClient) Patch(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { - return client.PatchWithContext(context.Background(), url, JSONBody, JSONResponse, opts) -} - -// DeleteWithContext calls `Request` with the "DELETE" HTTP verb. -func (client *ServiceClient) DeleteWithContext(ctx context.Context, url string, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = new(RequestOpts) } - client.initReqOpts(nil, nil, opts) - return client.RequestWithContext(ctx, "DELETE", url, opts) + client.initReqOpts(JSONBody, JSONResponse, opts) + return client.Request("PATCH", url, opts) } -// Delete is a compatibility wrapper for DeleteWithContext. +// Delete calls `Request` with the "DELETE" HTTP verb. func (client *ServiceClient) Delete(url string, opts *RequestOpts) (*http.Response, error) { - return client.DeleteWithContext(context.Background(), url, opts) -} - -// HeadWithContext calls `Request` with the "HEAD" HTTP verb. -func (client *ServiceClient) HeadWithContext(ctx context.Context, url string, opts *RequestOpts) (*http.Response, error) { if opts == nil { opts = new(RequestOpts) } client.initReqOpts(nil, nil, opts) - return client.RequestWithContext(ctx, "HEAD", url, opts) + return client.Request("DELETE", url, opts) } -// Head is a compatibility wrapper for HeadWithContext. +// Head calls `Request` with the "HEAD" HTTP verb. func (client *ServiceClient) Head(url string, opts *RequestOpts) (*http.Response, error) { - return client.HeadWithContext(context.Background(), url, opts) + if opts == nil { + opts = new(RequestOpts) + } + client.initReqOpts(nil, nil, opts) + return client.Request("HEAD", url, opts) } func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) { @@ -164,7 +133,7 @@ func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) { } // Request carries out the HTTP operation for the service client -func (client *ServiceClient) RequestWithContext(ctx context.Context, method, url string, options *RequestOpts) (*http.Response, error) { +func (client *ServiceClient) Request(method, url string, options *RequestOpts) (*http.Response, error) { if options.MoreHeaders == nil { options.MoreHeaders = make(map[string]string) } @@ -182,12 +151,7 @@ func (client *ServiceClient) RequestWithContext(ctx context.Context, method, url options.MoreHeaders[k] = v } } - return client.ProviderClient.RequestWithContext(ctx, method, url, options) -} - -// Request is a compatibility wrapper for RequestWithContext. -func (client *ServiceClient) Request(method, url string, options *RequestOpts) (*http.Response, error) { - return client.RequestWithContext(context.Background(), method, url, options) + return client.ProviderClient.Request(method, url, options) } // ParseResponse is a helper function to parse http.Response to constituents. From f7678f869b1431dd5e0d96323a79c445bcf3da78 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 6 Mar 2024 17:03:52 +0100 Subject: [PATCH 083/118] Prepare v1.11.0 When the Provider client contains a non-nil Context, the [`doRequest` method](https://github.com/gophercloud/gophercloud/blob/5b44c45ec947301d531178302c4cecc0a923ad96/provider_client.go#L401-L405) of the Provider client generated a new context by merging the Provider client's and the per-call context. However the new context is too short-lived to let the callers consume a response body. This version reverts the inclusion of Context in the v1 branch. This version replaces v1.9 and v1.10. --- CHANGELOG.md | 10 ++++++++-- provider_client.go | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d99d01ff2..0eec3e6dd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ -## v1.10.0 (2024-02-27) +## v1.11.0 (2024-03-07) + +This version reverts the inclusion of Context in the v1 branch. This inclusion +didn't add much value because no packages were using it; on the other hand, it +introduced a bug when using the Context property of the Provider client. + +## v1.10.0 (2024-02-27) **RETRACTED**: see https://github.com/gophercloud/gophercloud/issues/2969 * [GH-2893](https://github.com/gophercloud/gophercloud/pull/2893) [v1] authentication: Add WithContext functions * [GH-2894](https://github.com/gophercloud/gophercloud/pull/2894) [v1] pager: Add WithContext functions @@ -8,7 +14,7 @@ * [GH-2933](https://github.com/gophercloud/gophercloud/pull/2933) [v1] Fix AllowReauth reauthentication * [GH-2950](https://github.com/gophercloud/gophercloud/pull/2950) [v1] compute: Use volumeID, not attachmentID for volume attachments -## v1.9.0 (2024-02-02) +## v1.9.0 (2024-02-02) **RETRACTED**: see https://github.com/gophercloud/gophercloud/issues/2969 New features and improvements: diff --git a/provider_client.go b/provider_client.go index add4744ec5..1ff54b8197 100644 --- a/provider_client.go +++ b/provider_client.go @@ -14,7 +14,7 @@ import ( // DefaultUserAgent is the default User-Agent string set in the request header. const ( - DefaultUserAgent = "gophercloud/v1.10.0" + DefaultUserAgent = "gophercloud/v1.11.0" DefaultMaxBackoffRetries = 60 ) From 2a1086855ca48d2148f43bcd98d0507b4b456993 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 09:51:48 +0000 Subject: [PATCH 084/118] build(deps): bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] (cherry picked from commit d43efef34d48ae51f13fdf199ba8e2f225d95752) --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/functional-baremetal.yaml | 2 +- .github/workflows/functional-basic.yaml | 2 +- .github/workflows/functional-blockstorage.yaml | 2 +- .github/workflows/functional-clustering.yaml | 2 +- .github/workflows/functional-compute.yaml | 2 +- .github/workflows/functional-containerinfra.yaml | 2 +- .github/workflows/functional-dns.yaml | 2 +- .github/workflows/functional-fwaas_v2.yaml | 2 +- .github/workflows/functional-identity.yaml | 2 +- .github/workflows/functional-imageservice.yaml | 2 +- .github/workflows/functional-keymanager.yaml | 2 +- .github/workflows/functional-loadbalancer.yaml | 2 +- .github/workflows/functional-messaging.yaml | 2 +- .github/workflows/functional-networking.yaml | 2 +- .github/workflows/functional-objectstorage.yaml | 2 +- .github/workflows/functional-orchestration.yaml | 2 +- .github/workflows/functional-placement.yaml | 2 +- .github/workflows/functional-sharedfilesystems.yaml | 2 +- .github/workflows/gomod.yml | 2 +- .github/workflows/reauth-retests.yaml | 2 +- .github/workflows/semver-auto.yaml | 2 +- .github/workflows/unit.yml | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f423c1f7f4..9e1b8711dd 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v3 diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index 831a672442..1e224ffd45 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Ironic and run baremetal acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index c7331f42b8..06f0a5d0e5 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -40,7 +40,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with defaults and run basic acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index 721a9a5f6e..ad36cd47d3 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Cinder and run blockstorage acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-clustering.yaml b/.github/workflows/functional-clustering.yaml index 529c6e3833..823f8df3ea 100644 --- a/.github/workflows/functional-clustering.yaml +++ b/.github/workflows/functional-clustering.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Senlin and run clustering acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index cc6261b984..055b8bff17 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Nova and run compute acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index 335fcbbe51..e9106ab5d4 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -61,7 +61,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Magnum and run containerinfra acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index d01af4bb93..98a41410a1 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -38,7 +38,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Designate and run dns acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml index e2b2f5c04b..2665105be5 100644 --- a/.github/workflows/functional-fwaas_v2.yaml +++ b/.github/workflows/functional-fwaas_v2.yaml @@ -25,7 +25,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with enabled FWaaS_v2 and run networking acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml index 650f1fc0b8..51191bd86a 100644 --- a/.github/workflows/functional-identity.yaml +++ b/.github/workflows/functional-identity.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Keystone and run identity acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-imageservice.yaml b/.github/workflows/functional-imageservice.yaml index a99cdb175c..4c23ee8a0c 100644 --- a/.github/workflows/functional-imageservice.yaml +++ b/.github/workflows/functional-imageservice.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Glance and run imageservice acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml index 22668b3b7d..1bdff45801 100644 --- a/.github/workflows/functional-keymanager.yaml +++ b/.github/workflows/functional-keymanager.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Barbican and run keymanager acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml index 45ab11b657..5ca450a680 100644 --- a/.github/workflows/functional-loadbalancer.yaml +++ b/.github/workflows/functional-loadbalancer.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Octavia and run loadbalancer acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml index 70e195174f..41c023ee29 100644 --- a/.github/workflows/functional-messaging.yaml +++ b/.github/workflows/functional-messaging.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Zaqar and run messaging acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index c3968a04e4..bb89e1b463 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Neutron and run networking acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml index 30d07b877c..2826d6d8d9 100644 --- a/.github/workflows/functional-objectstorage.yaml +++ b/.github/workflows/functional-objectstorage.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Swift and run objectstorage acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml index 85dd87eaa2..7785e5faa1 100644 --- a/.github/workflows/functional-orchestration.yaml +++ b/.github/workflows/functional-orchestration.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Heat and run orchestration acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml index c02b7d61a5..bc04808b94 100644 --- a/.github/workflows/functional-placement.yaml +++ b/.github/workflows/functional-placement.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Placement and run placement acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml index 0750dc4893..36d272e9c5 100644 --- a/.github/workflows/functional-sharedfilesystems.yaml +++ b/.github/workflows/functional-sharedfilesystems.yaml @@ -37,7 +37,7 @@ jobs: name: Deploy OpenStack ${{ matrix.name }} with Manila and run sharedfilesystems acceptance tests steps: - name: Checkout Gophercloud - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: diff --git a/.github/workflows/gomod.yml b/.github/workflows/gomod.yml index 929bad77e9..8a17b797b3 100644 --- a/.github/workflows/gomod.yml +++ b/.github/workflows/gomod.yml @@ -7,7 +7,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-go@v4 with: go-version: '1' diff --git a/.github/workflows/reauth-retests.yaml b/.github/workflows/reauth-retests.yaml index ae1aa17994..0e18ca15ea 100644 --- a/.github/workflows/reauth-retests.yaml +++ b/.github/workflows/reauth-retests.yaml @@ -18,7 +18,7 @@ jobs: with: go-version: ${{ matrix.go-version }} - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run reauth retests run: | diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index 88a6ca9dc2..d23fff01d8 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -16,7 +16,7 @@ jobs: semver:unknown github_token: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 4a81289df4..3f3dd957cc 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -20,7 +20,7 @@ jobs: GO111MODULE: "on" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Go v1 uses: actions/setup-go@v4 From 99ee7678c567bcff8510a20dc545ca6cd054f0d3 Mon Sep 17 00:00:00 2001 From: Iury Gregory Melo Ferreira Date: Fri, 13 Oct 2023 10:02:13 -0400 Subject: [PATCH 085/118] Add workaround for baremetal jobs on ubuntu 20.04 This commit adds a workaround to baremetal jobs running on ubuntu 20.04 since they are failling when installing grub-efi-amd64-signed (cherry picked from commit b9a2337f792da82e945f08bd60ac2c77fc996551) --- .github/workflows/functional-baremetal.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index 1e224ffd45..8809bffb56 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -38,6 +38,14 @@ jobs: steps: - name: Checkout Gophercloud uses: actions/checkout@v4 + - name: Workaround for grub-efi-amd64-signed + run: sudo rm /var/cache/debconf/config.dat + shell: bash + if: matrix.ubuntu_version == '20.04' + - name: Ensure update and upgrade + run: sudo apt update && sudo apt -y upgrade + shell: bash + if: matrix.ubuntu_version == '20.04' - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: From 3b7ff58c048cbf4442cb2e8415d6459c8b5dd3c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 10:01:37 +0000 Subject: [PATCH 086/118] build(deps): bump actions/setup-go from 4 to 5 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] (cherry picked from commit ac6e5ab6a0b7718b38d80e5163be12e7c08ba7f0) --- .github/workflows/functional-baremetal.yaml | 2 +- .github/workflows/functional-basic.yaml | 2 +- .github/workflows/functional-blockstorage.yaml | 2 +- .github/workflows/functional-clustering.yaml | 2 +- .github/workflows/functional-compute.yaml | 2 +- .github/workflows/functional-containerinfra.yaml | 2 +- .github/workflows/functional-dns.yaml | 2 +- .github/workflows/functional-fwaas_v2.yaml | 2 +- .github/workflows/functional-identity.yaml | 2 +- .github/workflows/functional-imageservice.yaml | 2 +- .github/workflows/functional-keymanager.yaml | 2 +- .github/workflows/functional-loadbalancer.yaml | 2 +- .github/workflows/functional-messaging.yaml | 2 +- .github/workflows/functional-networking.yaml | 2 +- .github/workflows/functional-objectstorage.yaml | 2 +- .github/workflows/functional-orchestration.yaml | 2 +- .github/workflows/functional-placement.yaml | 2 +- .github/workflows/functional-sharedfilesystems.yaml | 2 +- .github/workflows/gomod.yml | 2 +- .github/workflows/reauth-retests.yaml | 2 +- .github/workflows/semver-auto.yaml | 2 +- .github/workflows/unit.yml | 4 ++-- 22 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index 8809bffb56..a26e65b1b6 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -86,7 +86,7 @@ jobs: SWIFT_TEMPURL_KEY=secretkey enabled_services: 'ir-api,ir-cond,s-account,s-container,s-object,s-proxy,q-svc,q-agt,q-dhcp,q-l3,q-meta,-cinder,-c-sch,-c-api,-c-vol,-c-bak,-ovn,-ovn-controller,-ovn-northd,-q-ovn-metadata-agent' - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index 06f0a5d0e5..3f8c7e6645 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -47,7 +47,7 @@ jobs: branch: ${{ matrix.openstack_version }} enabled_services: 's-account,s-container,s-object,s-proxy' - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index ad36cd47d3..9126fe0f2f 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -46,7 +46,7 @@ jobs: CINDER_ISCSI_HELPER=lioadm enabled_services: 's-account,s-container,s-object,s-proxy,c-bak' - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-clustering.yaml b/.github/workflows/functional-clustering.yaml index 823f8df3ea..25cc685cdf 100644 --- a/.github/workflows/functional-clustering.yaml +++ b/.github/workflows/functional-clustering.yaml @@ -47,7 +47,7 @@ jobs: enable_plugin zaqar https://github.com/openstack/zaqar ${{ matrix.openstack_version }} ZAQARCLIENT_BRANCH=${{ matrix.openstack_version }} - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index 055b8bff17..938814ef2c 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -45,7 +45,7 @@ jobs: conf_overrides: | CINDER_ISCSI_HELPER=lioadm - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index e9106ab5d4..b912ece82f 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -75,7 +75,7 @@ jobs: ${{ matrix.devstack_conf_overrides }} enabled_services: 'h-eng,h-api,h-api-cfn,h-api-cw' - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index 98a41410a1..a0c7e1ffe8 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -47,7 +47,7 @@ jobs: enable_plugin designate https://github.com/openstack/designate ${{ matrix.openstack_version }} enabled_services: 'designate,designate-central,designate-api,designate-worker,designate-producer,designate-mdns' - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml index 2665105be5..5a1cca929b 100644 --- a/.github/workflows/functional-fwaas_v2.yaml +++ b/.github/workflows/functional-fwaas_v2.yaml @@ -39,7 +39,7 @@ jobs: Q_TUNNEL_TYPES=vxlan,gre enabled_services: 'q-svc,q-agt,q-dhcp,q-l3,q-meta,q-fwaas-v2,-cinder,-horizon,-tempest,-swift,-c-sch,-c-api,-c-vol,-c-bak,-ovn,-ovn-controller,-ovn-northd,-q-ovn-metadata-agent' - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml index 51191bd86a..86df8daf8c 100644 --- a/.github/workflows/functional-identity.yaml +++ b/.github/workflows/functional-identity.yaml @@ -43,7 +43,7 @@ jobs: with: branch: ${{ matrix.openstack_version }} - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-imageservice.yaml b/.github/workflows/functional-imageservice.yaml index 4c23ee8a0c..6323b6a812 100644 --- a/.github/workflows/functional-imageservice.yaml +++ b/.github/workflows/functional-imageservice.yaml @@ -43,7 +43,7 @@ jobs: with: branch: ${{ matrix.openstack_version }} - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml index 1bdff45801..f09c185e84 100644 --- a/.github/workflows/functional-keymanager.yaml +++ b/.github/workflows/functional-keymanager.yaml @@ -46,7 +46,7 @@ jobs: enable_plugin barbican https://github.com/openstack/barbican ${{ matrix.openstack_version }} enabled_services: 'barbican-svc,barbican-retry,barbican-keystone-listener' - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml index 5ca450a680..33327edc39 100644 --- a/.github/workflows/functional-loadbalancer.yaml +++ b/.github/workflows/functional-loadbalancer.yaml @@ -47,7 +47,7 @@ jobs: enable_plugin neutron https://github.com/openstack/neutron ${{ matrix.openstack_version }} enabled_services: 'octavia,o-api,o-cw,o-hk,o-hm,o-da,neutron-qos' - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml index 41c023ee29..9d7366dced 100644 --- a/.github/workflows/functional-messaging.yaml +++ b/.github/workflows/functional-messaging.yaml @@ -46,7 +46,7 @@ jobs: enable_plugin zaqar https://github.com/openstack/zaqar ${{ matrix.openstack_version }} ZAQARCLIENT_BRANCH=${{ matrix.openstack_version }} - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index bb89e1b463..37e166e0d6 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -48,7 +48,7 @@ jobs: Q_ML2_PLUGIN_EXT_DRIVERS=qos,port_security,dns_domain_keywords enabled_services: 'neutron-dns,neutron-qos,neutron-segments,neutron-trunk,neutron-uplink-status-propagation,neutron-network-segment-range,neutron-port-forwarding' - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml index 2826d6d8d9..f6f6d6f81c 100644 --- a/.github/workflows/functional-objectstorage.yaml +++ b/.github/workflows/functional-objectstorage.yaml @@ -50,7 +50,7 @@ jobs: allow_object_versioning = true enabled_services: 's-account,s-container,s-object,s-proxy' - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml index 7785e5faa1..ea7c3fd0ce 100644 --- a/.github/workflows/functional-orchestration.yaml +++ b/.github/workflows/functional-orchestration.yaml @@ -46,7 +46,7 @@ jobs: enable_plugin heat https://github.com/openstack/heat ${{ matrix.openstack_version }} enabled_services: 'h-eng,h-api,h-api-cfn,h-api-cw' - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml index bc04808b94..a8b55c80ef 100644 --- a/.github/workflows/functional-placement.yaml +++ b/.github/workflows/functional-placement.yaml @@ -43,7 +43,7 @@ jobs: with: branch: ${{ matrix.openstack_version }} - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml index 36d272e9c5..26a53ed5aa 100644 --- a/.github/workflows/functional-sharedfilesystems.yaml +++ b/.github/workflows/functional-sharedfilesystems.yaml @@ -59,7 +59,7 @@ jobs: MANILA_CONFIGURE_DEFAULT_TYPES=True MANILA_INSTALL_TEMPEST_PLUGIN_SYSTEMWIDE=false - name: Checkout go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '^1.15' - name: Run Gophercloud acceptance tests diff --git a/.github/workflows/gomod.yml b/.github/workflows/gomod.yml index 8a17b797b3..43dc5c242b 100644 --- a/.github/workflows/gomod.yml +++ b/.github/workflows/gomod.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: '1' - run: if [ $(go mod tidy && git diff | wc -l) -gt 0 ]; then git diff && exit 1; fi diff --git a/.github/workflows/reauth-retests.yaml b/.github/workflows/reauth-retests.yaml index 0e18ca15ea..983102a048 100644 --- a/.github/workflows/reauth-retests.yaml +++ b/.github/workflows/reauth-retests.yaml @@ -14,7 +14,7 @@ jobs: steps: - name: Setup Go ${{ matrix.go-version }} - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index d23fff01d8..fa140c3889 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -37,7 +37,7 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} labels: semver:unknown - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: '1' diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 3f3dd957cc..cb981430c2 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup Go v1 - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: 1 @@ -34,7 +34,7 @@ jobs: - if: ${{ matrix.go-version != '1' }} name: Setup Go ${{ matrix.go-version }} - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} From dee7365da8ca61d289a3d875d75e365ac04b3403 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Mon, 4 Mar 2024 15:40:27 +0100 Subject: [PATCH 087/118] Drop CI coverage for Victoria-Yoga Yoga has entered, and the rest will soon enter, the unmaintained [1] phase. This means that the CI stability will be in the hands of a small group of volunteers and will no longer be the responsibility of the project teams. I don't believe the Gophercloud project can maintain CI jobs on these branches in the long run, hence removing them. [1] https://docs.openstack.org/project-team-guide/stable-branches.html#unmaintained (cherry picked from commit 5d4051c9bbbfed84e80cd8e267bd65781401ef4b) --- .github/workflows/functional-baremetal.yaml | 12 ---------- .github/workflows/functional-basic.yaml | 12 ---------- .../workflows/functional-blockstorage.yaml | 12 ---------- .github/workflows/functional-clustering.yaml | 12 ---------- .github/workflows/functional-compute.yaml | 12 ---------- .../workflows/functional-containerinfra.yaml | 24 ------------------- .github/workflows/functional-dns.yaml | 12 ---------- .github/workflows/functional-identity.yaml | 12 ---------- .../workflows/functional-imageservice.yaml | 12 ---------- .github/workflows/functional-keymanager.yaml | 12 ---------- .../workflows/functional-loadbalancer.yaml | 12 ---------- .github/workflows/functional-messaging.yaml | 12 ---------- .github/workflows/functional-networking.yaml | 12 ---------- .../workflows/functional-objectstorage.yaml | 12 ---------- .../workflows/functional-orchestration.yaml | 12 ---------- .github/workflows/functional-placement.yaml | 12 ---------- .../functional-sharedfilesystems.yaml | 12 ---------- 17 files changed, 216 deletions(-) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index a26e65b1b6..75a9652d61 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Ironic and run baremetal acceptance tests steps: diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index 3f8c7e6645..89f014ae53 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -24,18 +24,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with defaults and run basic acceptance tests steps: diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index 9126fe0f2f..ad190c5f0f 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Cinder and run blockstorage acceptance tests steps: diff --git a/.github/workflows/functional-clustering.yaml b/.github/workflows/functional-clustering.yaml index 25cc685cdf..808833d931 100644 --- a/.github/workflows/functional-clustering.yaml +++ b/.github/workflows/functional-clustering.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Senlin and run clustering acceptance tests steps: diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index 938814ef2c..280a05e7f1 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Nova and run compute acceptance tests steps: diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index b912ece82f..7d05589144 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -33,30 +33,6 @@ jobs: devstack_conf_overrides: | enable_plugin magnum https://github.com/openstack/magnum stable/zed MAGNUMCLIENT_BRANCH=stable/zed - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin magnum https://github.com/openstack/magnum stable/yoga - MAGNUMCLIENT_BRANCH=stable/yoga - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin magnum https://github.com/openstack/magnum xena-eol - MAGNUMCLIENT_BRANCH=xena-eol - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin magnum https://github.com/openstack/magnum wallaby-eol - MAGNUMCLIENT_BRANCH=wallaby-eol - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin magnum https://github.com/openstack/magnum victoria-eol - MAGNUMCLIENT_BRANCH=victoria-em runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Magnum and run containerinfra acceptance tests steps: diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index a0c7e1ffe8..80d188c55f 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -22,18 +22,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Designate and run dns acceptance tests steps: diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml index 86df8daf8c..8945ad35b6 100644 --- a/.github/workflows/functional-identity.yaml +++ b/.github/workflows/functional-identity.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Keystone and run identity acceptance tests steps: diff --git a/.github/workflows/functional-imageservice.yaml b/.github/workflows/functional-imageservice.yaml index 6323b6a812..cc763037c3 100644 --- a/.github/workflows/functional-imageservice.yaml +++ b/.github/workflows/functional-imageservice.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Glance and run imageservice acceptance tests steps: diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml index f09c185e84..d0eaaae69a 100644 --- a/.github/workflows/functional-keymanager.yaml +++ b/.github/workflows/functional-keymanager.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Barbican and run keymanager acceptance tests steps: diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml index 33327edc39..09061a32f4 100644 --- a/.github/workflows/functional-loadbalancer.yaml +++ b/.github/workflows/functional-loadbalancer.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Octavia and run loadbalancer acceptance tests steps: diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml index 9d7366dced..1023d3f31c 100644 --- a/.github/workflows/functional-messaging.yaml +++ b/.github/workflows/functional-messaging.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Zaqar and run messaging acceptance tests steps: diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index 37e166e0d6..51b0332187 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Neutron and run networking acceptance tests steps: diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml index f6f6d6f81c..f873e593c3 100644 --- a/.github/workflows/functional-objectstorage.yaml +++ b/.github/workflows/functional-objectstorage.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Swift and run objectstorage acceptance tests steps: diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml index ea7c3fd0ce..b238111c05 100644 --- a/.github/workflows/functional-orchestration.yaml +++ b/.github/workflows/functional-orchestration.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Heat and run orchestration acceptance tests steps: diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml index a8b55c80ef..f5b84618e5 100644 --- a/.github/workflows/functional-placement.yaml +++ b/.github/workflows/functional-placement.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Placement and run placement acceptance tests steps: diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml index 26a53ed5aa..be82a4f133 100644 --- a/.github/workflows/functional-sharedfilesystems.yaml +++ b/.github/workflows/functional-sharedfilesystems.yaml @@ -21,18 +21,6 @@ jobs: - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" - - name: "yoga" - openstack_version: "stable/yoga" - ubuntu_version: "20.04" - - name: "xena" - openstack_version: "stable/xena" - ubuntu_version: "20.04" - - name: "wallaby" - openstack_version: "stable/wallaby" - ubuntu_version: "20.04" - - name: "victoria" - openstack_version: "stable/victoria" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Manila and run sharedfilesystems acceptance tests steps: From ddd0f458a7857b5aaf0a9414aa4152828c01b074 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Mon, 4 Mar 2024 17:47:03 +0100 Subject: [PATCH 088/118] Use system scope when running baremetal tests Starting with 2024.1, some actions no longer work with a project scoped token. (cherry picked from commit 00636216663881e903c1c858e928ddbc1d2687fb) --- .github/workflows/functional-baremetal.yaml | 6 ++++++ script/stackenv | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index 75a9652d61..9a77785fc4 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -11,16 +11,20 @@ jobs: name: ["master"] openstack_version: ["master"] ubuntu_version: ["22.04"] + os_system_scope: ["all"] include: - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" + os_system_scope: "" - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" + os_system_scope: "" - name: "zed" openstack_version: "stable/zed" ubuntu_version: "20.04" + os_system_scope: "" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Ironic and run baremetal acceptance tests steps: @@ -83,6 +87,8 @@ jobs: DEVSTACK_PATH: ${{ github.workspace }}/devstack ACCEPTANCE_TESTS_FILTER: '^.*baremetal(.(?!noauth).*)?$' OS_BRANCH: ${{ matrix.openstack_version }} + # TODO(dtantsur): default to "all" when no longer supporting versions before 2024.1 + OS_SYSTEM_SCOPE: ${{ matrix.os_system_scope }} - name: Generate logs on failure run: ./script/collectlogs if: failure() diff --git a/script/stackenv b/script/stackenv index d51d311e74..ef6311c039 100644 --- a/script/stackenv +++ b/script/stackenv @@ -30,4 +30,8 @@ echo export OS_DOMAIN_ID=default >> openrc echo export OS_MAGNUM_IMAGE_ID="$_MAGNUM_IMAGE_ID" >> openrc echo export OS_MAGNUM_KEYPAIR=magnum >> openrc source openrc admin admin +if [[ "${OS_SYSTEM_SCOPE:-}" == "all" ]]; then + unset PROJECT_NAME + unset TENANT_NAME +fi popd From 25ef704a547ae6b0469db1dd5c9d159448bdda23 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Mon, 4 Mar 2024 16:04:39 +0100 Subject: [PATCH 089/118] Work around broken dnsmasq in the Ironic plugin (cherry picked from commit 888aa7be4c474e58a9477e43a7ae631b29f0e5a7) --- .github/workflows/functional-baremetal.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index 9a77785fc4..33271c4ebf 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -38,6 +38,9 @@ jobs: run: sudo apt update && sudo apt -y upgrade shell: bash if: matrix.ubuntu_version == '20.04' + - name: Work around broken dnsmasq + run: sudo apt-get purge -y dnsmasq-base + if: matrix.ubuntu_version == '22.04' - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: From 717b7f2abcd7bfdbf36268c35221932963fc2ad6 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Tue, 16 Jan 2024 10:33:38 +0100 Subject: [PATCH 090/118] Bump go_apidiff (cherry picked from commit 05b545790fe779b6d3a993ce3a3f65aab719f303) (cherry picked from commit d131ce6b192a45fb3bbfa64d4a685b4cea3e4e89) --- .github/workflows/semver-auto.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index fa140c3889..c042be134a 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -46,7 +46,7 @@ jobs: # if semver=major, this will return RC=1, so let's ignore the failure so label # can be set later. We check for actual errors in the next step. continue-on-error: true - uses: joelanford/go-apidiff@v0.7.0 + uses: joelanford/go-apidiff@002aa613b261e8d1547b516fb71793280f05bb78 # go-apidiff returns RC=1 when semver=major, which makes the workflow to return # a failure. Instead let's just return a failure if go-apidiff failed to run. From b29bd3f059484633bebea22e43a4322b47b7d23e Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Fri, 1 Mar 2024 11:25:50 +0100 Subject: [PATCH 091/118] baremetal: fix handling of the "fields" query argument Ironic expects a comma-separated string. Add a new feature to BuildQueryString to choose the format of slices. Closes: #2960 --- .../openstack/baremetal/v1/nodes_test.go | 32 +++++++++++++++++++ .../baremetal/v1/allocations/requests.go | 2 +- openstack/baremetal/v1/conductors/requests.go | 2 +- .../v1/conductors/testing/requests_test.go | 2 +- openstack/baremetal/v1/nodes/requests.go | 4 +-- .../v1/nodes/testing/requests_test.go | 2 +- openstack/baremetal/v1/ports/requests.go | 2 +- .../v1/ports/testing/requests_test.go | 2 +- params.go | 21 +++++++++--- 9 files changed, 57 insertions(+), 12 deletions(-) diff --git a/internal/acceptance/openstack/baremetal/v1/nodes_test.go b/internal/acceptance/openstack/baremetal/v1/nodes_test.go index af79bfd5d7..2df8c2075f 100644 --- a/internal/acceptance/openstack/baremetal/v1/nodes_test.go +++ b/internal/acceptance/openstack/baremetal/v1/nodes_test.go @@ -45,6 +45,38 @@ func TestNodesCreateDestroy(t *testing.T) { th.AssertEquals(t, found, true) } +func TestNodesFields(t *testing.T) { + clients.RequireLong(t) + + client, err := clients.NewBareMetalV1Client() + th.AssertNoErr(t, err) + client.Microversion = "1.38" + + node, err := CreateNode(t, client) + th.AssertNoErr(t, err) + defer DeleteNode(t, client, node) + err = nodes.List(client, nodes.ListOpts{ + Fields: []string{"uuid", "deploy_interface"}, + }).EachPage(func(page pagination.Page) (bool, error) { + nodeList, err := nodes.ExtractNodes(page) + if err != nil { + return false, err + } + + for _, n := range nodeList { + if n.UUID == "" || n.DeployInterface == "" { + t.Errorf("UUID or DeployInterface empty on %+v", n) + } + if n.BootInterface != "" { + t.Errorf("BootInterface was not fetched but is not empty on %+v", n) + } + } + + return true, nil + }) + th.AssertNoErr(t, err) +} + func TestNodesUpdate(t *testing.T) { clients.RequireLong(t) diff --git a/openstack/baremetal/v1/allocations/requests.go b/openstack/baremetal/v1/allocations/requests.go index dfb04ba942..1f0dd3bb86 100644 --- a/openstack/baremetal/v1/allocations/requests.go +++ b/openstack/baremetal/v1/allocations/requests.go @@ -80,7 +80,7 @@ type ListOpts struct { State AllocationState `q:"state"` // One or more fields to be returned in the response. - Fields []string `q:"fields"` + Fields []string `q:"fields" format:"comma-separated"` // Requests a page size of items. Limit int `q:"limit"` diff --git a/openstack/baremetal/v1/conductors/requests.go b/openstack/baremetal/v1/conductors/requests.go index f5bc63d63e..1e3541065c 100644 --- a/openstack/baremetal/v1/conductors/requests.go +++ b/openstack/baremetal/v1/conductors/requests.go @@ -19,7 +19,7 @@ type ListOptsBuilder interface { // for pagination. type ListOpts struct { // One or more fields to be returned in the response. - Fields []string `q:"fields"` + Fields []string `q:"fields" format:"comma-separated"` // Requests a page size of items. Limit int `q:"limit"` diff --git a/openstack/baremetal/v1/conductors/testing/requests_test.go b/openstack/baremetal/v1/conductors/testing/requests_test.go index b05495a5fd..9d9e5aa0d4 100644 --- a/openstack/baremetal/v1/conductors/testing/requests_test.go +++ b/openstack/baremetal/v1/conductors/testing/requests_test.go @@ -87,7 +87,7 @@ func TestListOpts(t *testing.T) { // Regular ListOpts can query, err := opts.ToConductorListQuery() - th.AssertEquals(t, query, "?fields=hostname&fields=alive") + th.AssertEquals(t, "?fields=hostname%2Calive", query) th.AssertNoErr(t, err) } diff --git a/openstack/baremetal/v1/nodes/requests.go b/openstack/baremetal/v1/nodes/requests.go index 2515bf1587..ffe98ee6de 100644 --- a/openstack/baremetal/v1/nodes/requests.go +++ b/openstack/baremetal/v1/nodes/requests.go @@ -97,7 +97,7 @@ type ListOpts struct { Fault string `q:"fault"` // One or more fields to be returned in the response. - Fields []string `q:"fields"` + Fields []string `q:"fields" format:"comma-separated"` // Requests a page size of items. Limit int `q:"limit"` @@ -653,7 +653,7 @@ type ListBIOSSettingsOpts struct { Detail bool `q:"detail"` // One or more fields to be returned in the response. - Fields []string `q:"fields"` + Fields []string `q:"fields" format:"comma-separated"` } // ToListBIOSSettingsOptsQuery formats a ListBIOSSettingsOpts into a query string diff --git a/openstack/baremetal/v1/nodes/testing/requests_test.go b/openstack/baremetal/v1/nodes/testing/requests_test.go index ba9e8f3ceb..815e7b28fc 100644 --- a/openstack/baremetal/v1/nodes/testing/requests_test.go +++ b/openstack/baremetal/v1/nodes/testing/requests_test.go @@ -83,7 +83,7 @@ func TestListOpts(t *testing.T) { // Regular ListOpts can query, err := opts.ToNodeListQuery() - th.AssertEquals(t, query, "?fields=name&fields=uuid") + th.AssertEquals(t, "?fields=name%2Cuuid", query) th.AssertNoErr(t, err) } diff --git a/openstack/baremetal/v1/ports/requests.go b/openstack/baremetal/v1/ports/requests.go index ed191649d6..33c872ef47 100644 --- a/openstack/baremetal/v1/ports/requests.go +++ b/openstack/baremetal/v1/ports/requests.go @@ -32,7 +32,7 @@ type ListOpts struct { Address string `q:"address"` // One or more fields to be returned in the response. - Fields []string `q:"fields"` + Fields []string `q:"fields" format:"comma-separated"` // Requests a page size of items. Limit int `q:"limit"` diff --git a/openstack/baremetal/v1/ports/testing/requests_test.go b/openstack/baremetal/v1/ports/testing/requests_test.go index cf9519b53d..06118bf2bf 100644 --- a/openstack/baremetal/v1/ports/testing/requests_test.go +++ b/openstack/baremetal/v1/ports/testing/requests_test.go @@ -80,7 +80,7 @@ func TestListOpts(t *testing.T) { // Regular ListOpts can query, err := opts.ToPortListQuery() - th.AssertEquals(t, query, "?fields=uuid&fields=address") + th.AssertEquals(t, "?fields=uuid%2Caddress", query) th.AssertNoErr(t, err) } diff --git a/params.go b/params.go index 17b200cd23..5abc2c5589 100644 --- a/params.go +++ b/params.go @@ -318,8 +318,15 @@ converted into query parameters based on a "q" tag. For example: will be converted into "?x_bar=AAA&lorem_ipsum=BBB". -The struct's fields may be strings, integers, or boolean values. Fields left at -their type's zero value will be omitted from the query. +The struct's fields may be strings, integers, slices, or boolean values. Fields +left at their type's zero value will be omitted from the query. + +Slice are handled in one of two ways: + + type struct Something { + Bar []string `q:"bar"` // E.g. ?bar=1&bar=2 + Baz []int `q:"baz" format="comma-separated"` // E.g. ?baz=1,2 + } */ func BuildQueryString(opts interface{}) (*url.URL, error) { optsValue := reflect.ValueOf(opts) @@ -358,16 +365,22 @@ func BuildQueryString(opts interface{}) (*url.URL, error) { case reflect.Bool: params.Add(tags[0], strconv.FormatBool(v.Bool())) case reflect.Slice: + var values []string switch v.Type().Elem() { case reflect.TypeOf(0): for i := 0; i < v.Len(); i++ { - params.Add(tags[0], strconv.FormatInt(v.Index(i).Int(), 10)) + values = append(values, strconv.FormatInt(v.Index(i).Int(), 10)) } default: for i := 0; i < v.Len(); i++ { - params.Add(tags[0], v.Index(i).String()) + values = append(values, v.Index(i).String()) } } + if sliceFormat := f.Tag.Get("format"); sliceFormat == "comma-separated" { + params.Add(tags[0], strings.Join(values, ",")) + } else { + params[tags[0]] = append(params[tags[0]], values...) + } case reflect.Map: if v.Type().Key().Kind() == reflect.String && v.Type().Elem().Kind() == reflect.String { var s []string From b867246755666352fb22bac5d4695f007246c08b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Sun, 10 Mar 2024 16:59:41 +0100 Subject: [PATCH 092/118] [CI] Fix portbiding tests Since https://review.opendev.org/c/openstack/neutron/+/909075, port-binding operation are restricted to the service role. Update the policies so that we can continue exercising these tests in CI. Fixes #2983 --- .github/workflows/functional-fwaas_v2.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml index 5a1cca929b..3c7711c80c 100644 --- a/.github/workflows/functional-fwaas_v2.yaml +++ b/.github/workflows/functional-fwaas_v2.yaml @@ -37,6 +37,10 @@ jobs: Q_ML2_PLUGIN_TYPE_DRIVERS=flat,gre,vlan,vxlan Q_ML2_TENANT_NETWORK_TYPE=vxlan Q_TUNNEL_TYPES=vxlan,gre + + [[post-config|/etc/neutron/policy.d/port_binding.yaml]] + "create_port:binding:profile": "rule:admin_only or rule:service_api" + "update_port:binding:profile": "rule:admin_only or rule:service_api" enabled_services: 'q-svc,q-agt,q-dhcp,q-l3,q-meta,q-fwaas-v2,-cinder,-horizon,-tempest,-swift,-c-sch,-c-api,-c-vol,-c-bak,-ovn,-ovn-controller,-ovn-northd,-q-ovn-metadata-agent' - name: Checkout go uses: actions/setup-go@v5 From c3b938f74d7f5ac331c6f19502ae4734e9d1f0ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Mon, 11 Mar 2024 14:34:50 +0100 Subject: [PATCH 093/118] Revert "[CI] Fix portbiding tests" This reverts commit a2f421e76ce4bc26d4972756a8b7d5a3ec1e1c60. --- .github/workflows/functional-fwaas_v2.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml index 3c7711c80c..5a1cca929b 100644 --- a/.github/workflows/functional-fwaas_v2.yaml +++ b/.github/workflows/functional-fwaas_v2.yaml @@ -37,10 +37,6 @@ jobs: Q_ML2_PLUGIN_TYPE_DRIVERS=flat,gre,vlan,vxlan Q_ML2_TENANT_NETWORK_TYPE=vxlan Q_TUNNEL_TYPES=vxlan,gre - - [[post-config|/etc/neutron/policy.d/port_binding.yaml]] - "create_port:binding:profile": "rule:admin_only or rule:service_api" - "update_port:binding:profile": "rule:admin_only or rule:service_api" enabled_services: 'q-svc,q-agt,q-dhcp,q-l3,q-meta,q-fwaas-v2,-cinder,-horizon,-tempest,-swift,-c-sch,-c-api,-c-vol,-c-bak,-ovn,-ovn-controller,-ovn-northd,-q-ovn-metadata-agent' - name: Checkout go uses: actions/setup-go@v5 From 5ef5fcfb02fd80a9981dbb7ae54b2c3cdb2d3908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Mon, 11 Mar 2024 14:37:25 +0100 Subject: [PATCH 094/118] [CI] Fix portbiding tests Since https://review.opendev.org/c/openstack/neutron/+/909075, port-binding operation are restricted to the service role. Update the policies so that we can continue exercising these tests in CI. Fixes #2983 --- .github/workflows/functional-networking.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index 51b0332187..d584391d86 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -26,6 +26,14 @@ jobs: steps: - name: Checkout Gophercloud uses: actions/checkout@v4 + - name: Create additional neutron policies + run: | + mkdir /tmp/neutron-policies + cat << EOF >> /tmp/neutron-policies/port_binding.yaml + --- + "create_port:binding:profile": "rule:admin_only or rule:service_api" + "update_port:binding:profile": "rule:admin_only or rule:service_api" + EOF - name: Deploy devstack uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd with: @@ -34,6 +42,10 @@ jobs: enable_plugin neutron-dynamic-routing https://github.com/openstack/neutron-dynamic-routing ${{ matrix.openstack_version }} enable_plugin neutron-vpnaas https://github.com/openstack/neutron-vpnaas ${{ matrix.openstack_version }} Q_ML2_PLUGIN_EXT_DRIVERS=qos,port_security,dns_domain_keywords + + [[post-config|\$NEUTRON_CONF]] + [oslo_policy] + policy_dirs = /tmp/neutron-policies enabled_services: 'neutron-dns,neutron-qos,neutron-segments,neutron-trunk,neutron-uplink-status-propagation,neutron-network-segment-range,neutron-port-forwarding' - name: Checkout go uses: actions/setup-go@v5 From 63fd8f5732f57cec3df8c86758d915505bd1ba36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 09:12:09 +0000 Subject: [PATCH 095/118] build(deps): bump EmilienM/devstack-action from 0.14 to 0.15 Bumps [EmilienM/devstack-action](https://github.com/emilienm/devstack-action) from 0.14 to 0.15. - [Release notes](https://github.com/emilienm/devstack-action/releases) - [Commits](https://github.com/emilienm/devstack-action/compare/c41f86d8df58b53c55f070207b6dfce656788cfd...e82a9cbead099cba72f99537e82a360c3e319c69) --- updated-dependencies: - dependency-name: EmilienM/devstack-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/functional-baremetal.yaml | 2 +- .github/workflows/functional-basic.yaml | 2 +- .github/workflows/functional-blockstorage.yaml | 2 +- .github/workflows/functional-clustering.yaml | 2 +- .github/workflows/functional-compute.yaml | 2 +- .github/workflows/functional-containerinfra.yaml | 2 +- .github/workflows/functional-dns.yaml | 2 +- .github/workflows/functional-fwaas_v2.yaml | 2 +- .github/workflows/functional-identity.yaml | 2 +- .github/workflows/functional-imageservice.yaml | 2 +- .github/workflows/functional-keymanager.yaml | 2 +- .github/workflows/functional-loadbalancer.yaml | 2 +- .github/workflows/functional-messaging.yaml | 2 +- .github/workflows/functional-networking.yaml | 2 +- .github/workflows/functional-objectstorage.yaml | 2 +- .github/workflows/functional-orchestration.yaml | 2 +- .github/workflows/functional-placement.yaml | 2 +- .github/workflows/functional-sharedfilesystems.yaml | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index 33271c4ebf..0672b53040 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -42,7 +42,7 @@ jobs: run: sudo apt-get purge -y dnsmasq-base if: matrix.ubuntu_version == '22.04' - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index 89f014ae53..aa3da06dc2 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -30,7 +30,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} enabled_services: 's-account,s-container,s-object,s-proxy' diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index ad190c5f0f..241eebcfb4 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-clustering.yaml b/.github/workflows/functional-clustering.yaml index 808833d931..a7554623ad 100644 --- a/.github/workflows/functional-clustering.yaml +++ b/.github/workflows/functional-clustering.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index 280a05e7f1..5d71efb068 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index 7d05589144..7dc8c4bfea 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -39,7 +39,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index 80d188c55f..979005c8e3 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -28,7 +28,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml index 5a1cca929b..99cdc1eb0b 100644 --- a/.github/workflows/functional-fwaas_v2.yaml +++ b/.github/workflows/functional-fwaas_v2.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml index 8945ad35b6..f393fae80f 100644 --- a/.github/workflows/functional-identity.yaml +++ b/.github/workflows/functional-identity.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} - name: Checkout go diff --git a/.github/workflows/functional-imageservice.yaml b/.github/workflows/functional-imageservice.yaml index cc763037c3..cf173bdc9a 100644 --- a/.github/workflows/functional-imageservice.yaml +++ b/.github/workflows/functional-imageservice.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} - name: Checkout go diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml index d0eaaae69a..f124a40959 100644 --- a/.github/workflows/functional-keymanager.yaml +++ b/.github/workflows/functional-keymanager.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml index 09061a32f4..fa0b82699f 100644 --- a/.github/workflows/functional-loadbalancer.yaml +++ b/.github/workflows/functional-loadbalancer.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml index 1023d3f31c..e8c5c3b770 100644 --- a/.github/workflows/functional-messaging.yaml +++ b/.github/workflows/functional-messaging.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index d584391d86..789c49eff8 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -35,7 +35,7 @@ jobs: "update_port:binding:profile": "rule:admin_only or rule:service_api" EOF - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml index f873e593c3..ac12bb77e3 100644 --- a/.github/workflows/functional-objectstorage.yaml +++ b/.github/workflows/functional-objectstorage.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml index b238111c05..6d217cb0d8 100644 --- a/.github/workflows/functional-orchestration.yaml +++ b/.github/workflows/functional-orchestration.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml index f5b84618e5..c064320e68 100644 --- a/.github/workflows/functional-placement.yaml +++ b/.github/workflows/functional-placement.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} - name: Checkout go diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml index be82a4f133..732833cc7d 100644 --- a/.github/workflows/functional-sharedfilesystems.yaml +++ b/.github/workflows/functional-sharedfilesystems.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout Gophercloud uses: actions/checkout@v4 - name: Deploy devstack - uses: EmilienM/devstack-action@c41f86d8df58b53c55f070207b6dfce656788cfd + uses: EmilienM/devstack-action@e82a9cbead099cba72f99537e82a360c3e319c69 with: branch: ${{ matrix.openstack_version }} conf_overrides: | From 7fc854b9113d5e3a80efec75400ef22e3ad0d4d6 Mon Sep 17 00:00:00 2001 From: Vladimir Ermakov Date: Mon, 18 Mar 2024 11:23:04 +0100 Subject: [PATCH 096/118] testhelper: mark all helpers with t.Helper Fixes #2996 Signed-off-by: Vladimir Ermakov --- testhelper/convenience.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/testhelper/convenience.go b/testhelper/convenience.go index 2ae247052b..1602431fe1 100644 --- a/testhelper/convenience.go +++ b/testhelper/convenience.go @@ -33,10 +33,12 @@ func yellow(str interface{}) string { } func logFatal(t *testing.T, str string) { + t.Helper() t.Fatalf(logBodyFmt, prefix(3), str) } func logError(t *testing.T, str string) { + t.Helper() t.Errorf(logBodyFmt, prefix(3), str) } @@ -214,6 +216,8 @@ func deepDiff(expected, actual interface{}, logDifference diffLogger) { // AssertEquals compares two arbitrary values and performs a comparison. If the // comparison fails, a fatal error is raised that will fail the test func AssertEquals(t *testing.T, expected, actual interface{}) { + t.Helper() + if expected != actual { logFatal(t, fmt.Sprintf("expected %s but got %s", green(expected), yellow(actual))) } @@ -221,6 +225,8 @@ func AssertEquals(t *testing.T, expected, actual interface{}) { // CheckEquals is similar to AssertEquals, except with a non-fatal error func CheckEquals(t *testing.T, expected, actual interface{}) { + t.Helper() + if expected != actual { logError(t, fmt.Sprintf("expected %s but got %s", green(expected), yellow(actual))) } @@ -229,6 +235,8 @@ func CheckEquals(t *testing.T, expected, actual interface{}) { // AssertDeepEquals - like Equals - performs a comparison - but on more complex // structures that requires deeper inspection func AssertDeepEquals(t *testing.T, expected, actual interface{}) { + t.Helper() + pre := prefix(2) differed := false @@ -247,6 +255,8 @@ func AssertDeepEquals(t *testing.T, expected, actual interface{}) { // CheckDeepEquals is similar to AssertDeepEquals, except with a non-fatal error func CheckDeepEquals(t *testing.T, expected, actual interface{}) { + t.Helper() + pre := prefix(2) deepDiff(expected, actual, func(path []string, expected, actual interface{}) { @@ -264,6 +274,8 @@ func isByteArrayEquals(t *testing.T, expectedBytes []byte, actualBytes []byte) b // AssertByteArrayEquals a convenience function for checking whether two byte arrays are equal func AssertByteArrayEquals(t *testing.T, expectedBytes []byte, actualBytes []byte) { + t.Helper() + if !isByteArrayEquals(t, expectedBytes, actualBytes) { logFatal(t, "The bytes differed.") } @@ -271,6 +283,8 @@ func AssertByteArrayEquals(t *testing.T, expectedBytes []byte, actualBytes []byt // CheckByteArrayEquals a convenience function for silent checking whether two byte arrays are equal func CheckByteArrayEquals(t *testing.T, expectedBytes []byte, actualBytes []byte) { + t.Helper() + if !isByteArrayEquals(t, expectedBytes, actualBytes) { logError(t, "The bytes differed.") } @@ -321,6 +335,8 @@ func isJSONEquals(t *testing.T, expectedJSON string, actual interface{}) bool { // This is useful for comparing structures that are built as nested map[string]interface{} values, // which are a pain to construct as literals. func AssertJSONEquals(t *testing.T, expectedJSON string, actual interface{}) { + t.Helper() + if !isJSONEquals(t, expectedJSON, actual) { logFatal(t, "The generated JSON structure differed.") } @@ -328,6 +344,8 @@ func AssertJSONEquals(t *testing.T, expectedJSON string, actual interface{}) { // CheckJSONEquals is similar to AssertJSONEquals, but nonfatal. func CheckJSONEquals(t *testing.T, expectedJSON string, actual interface{}) { + t.Helper() + if !isJSONEquals(t, expectedJSON, actual) { logError(t, "The generated JSON structure differed.") } @@ -336,6 +354,8 @@ func CheckJSONEquals(t *testing.T, expectedJSON string, actual interface{}) { // AssertNoErr is a convenience function for checking whether an error value is // an actual error func AssertNoErr(t *testing.T, e error) { + t.Helper() + if e != nil { logFatal(t, fmt.Sprintf("unexpected error %s", yellow(e.Error()))) } @@ -344,6 +364,8 @@ func AssertNoErr(t *testing.T, e error) { // AssertErr is a convenience function for checking whether an error value is // nil func AssertErr(t *testing.T, e error) { + t.Helper() + if e == nil { logFatal(t, fmt.Sprintf("expected error, got nil")) } @@ -351,6 +373,8 @@ func AssertErr(t *testing.T, e error) { // CheckNoErr is similar to AssertNoErr, except with a non-fatal error func CheckNoErr(t *testing.T, e error) { + t.Helper() + if e != nil { logError(t, fmt.Sprintf("unexpected error %s", yellow(e.Error()))) } @@ -364,6 +388,8 @@ func CheckNoErr(t *testing.T, e error) { // CheckErr panics if expected contains anything other than non-nil pointers to // either a type that implements error, or to any interface type. func CheckErr(t *testing.T, e error, expected ...interface{}) { + t.Helper() + if e == nil { logError(t, "expected error, got nil") return @@ -381,6 +407,8 @@ func CheckErr(t *testing.T, e error, expected ...interface{}) { // AssertIntLesserOrEqual verifies that first value is lesser or equal than second values func AssertIntLesserOrEqual(t *testing.T, v1 int, v2 int) { + t.Helper() + if !(v1 <= v2) { logFatal(t, fmt.Sprintf("The first value \"%v\" is greater than the second value \"%v\"", v1, v2)) } @@ -388,6 +416,8 @@ func AssertIntLesserOrEqual(t *testing.T, v1 int, v2 int) { // AssertIntGreaterOrEqual verifies that first value is greater or equal than second values func AssertIntGreaterOrEqual(t *testing.T, v1 int, v2 int) { + t.Helper() + if !(v1 >= v2) { logFatal(t, fmt.Sprintf("The first value \"%v\" is lesser than the second value \"%v\"", v1, v2)) } From 5dd732dbbe857704d5c9e3a8687a2670870fc36a Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Mon, 6 May 2024 10:34:30 -0400 Subject: [PATCH 097/118] CI: remove Zed from testing coverage This isn't maintained anymore, this could break anytime. --- .github/workflows/functional-baremetal.yaml | 4 ---- .github/workflows/functional-basic.yaml | 3 --- .github/workflows/functional-blockstorage.yaml | 3 --- .github/workflows/functional-clustering.yaml | 3 --- .github/workflows/functional-compute.yaml | 3 --- .github/workflows/functional-containerinfra.yaml | 6 ------ .github/workflows/functional-dns.yaml | 3 --- .github/workflows/functional-fwaas_v2.yaml | 3 --- .github/workflows/functional-identity.yaml | 3 --- .github/workflows/functional-imageservice.yaml | 3 --- .github/workflows/functional-keymanager.yaml | 3 --- .github/workflows/functional-loadbalancer.yaml | 3 --- .github/workflows/functional-messaging.yaml | 3 --- .github/workflows/functional-networking.yaml | 3 --- .github/workflows/functional-objectstorage.yaml | 3 --- .github/workflows/functional-orchestration.yaml | 3 --- .github/workflows/functional-placement.yaml | 3 --- .github/workflows/functional-sharedfilesystems.yaml | 3 --- 18 files changed, 58 deletions(-) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index 0672b53040..6330164d3b 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -21,10 +21,6 @@ jobs: openstack_version: "stable/2023.1" ubuntu_version: "22.04" os_system_scope: "" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" - os_system_scope: "" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Ironic and run baremetal acceptance tests steps: diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index aa3da06dc2..5e59a0b690 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -21,9 +21,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with defaults and run basic acceptance tests steps: diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index 241eebcfb4..c2894ec07f 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Cinder and run blockstorage acceptance tests steps: diff --git a/.github/workflows/functional-clustering.yaml b/.github/workflows/functional-clustering.yaml index a7554623ad..e6a7d34c55 100644 --- a/.github/workflows/functional-clustering.yaml +++ b/.github/workflows/functional-clustering.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Senlin and run clustering acceptance tests steps: diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index 5d71efb068..88eca81b11 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Nova and run compute acceptance tests steps: diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index 7dc8c4bfea..ff104b3619 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -27,12 +27,6 @@ jobs: devstack_conf_overrides: | enable_plugin magnum https://github.com/openstack/magnum stable/2023.1 MAGNUMCLIENT_BRANCH=stable/2023.1 - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" - devstack_conf_overrides: | - enable_plugin magnum https://github.com/openstack/magnum stable/zed - MAGNUMCLIENT_BRANCH=stable/zed runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Magnum and run containerinfra acceptance tests steps: diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index 979005c8e3..3040bd8091 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -19,9 +19,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Designate and run dns acceptance tests steps: diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml index 99cdc1eb0b..02662ba03e 100644 --- a/.github/workflows/functional-fwaas_v2.yaml +++ b/.github/workflows/functional-fwaas_v2.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "22.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with enabled FWaaS_v2 and run networking acceptance tests steps: diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml index f393fae80f..5b1140da49 100644 --- a/.github/workflows/functional-identity.yaml +++ b/.github/workflows/functional-identity.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Keystone and run identity acceptance tests steps: diff --git a/.github/workflows/functional-imageservice.yaml b/.github/workflows/functional-imageservice.yaml index cf173bdc9a..9541e3005d 100644 --- a/.github/workflows/functional-imageservice.yaml +++ b/.github/workflows/functional-imageservice.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Glance and run imageservice acceptance tests steps: diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml index f124a40959..29a7e1e8e4 100644 --- a/.github/workflows/functional-keymanager.yaml +++ b/.github/workflows/functional-keymanager.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Barbican and run keymanager acceptance tests steps: diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml index fa0b82699f..9c76f4d912 100644 --- a/.github/workflows/functional-loadbalancer.yaml +++ b/.github/workflows/functional-loadbalancer.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Octavia and run loadbalancer acceptance tests steps: diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml index e8c5c3b770..e6064ecf90 100644 --- a/.github/workflows/functional-messaging.yaml +++ b/.github/workflows/functional-messaging.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Zaqar and run messaging acceptance tests steps: diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index 789c49eff8..546b5b3006 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Neutron and run networking acceptance tests steps: diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml index ac12bb77e3..02391babf2 100644 --- a/.github/workflows/functional-objectstorage.yaml +++ b/.github/workflows/functional-objectstorage.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Swift and run objectstorage acceptance tests steps: diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml index 6d217cb0d8..7b0fcfb969 100644 --- a/.github/workflows/functional-orchestration.yaml +++ b/.github/workflows/functional-orchestration.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Heat and run orchestration acceptance tests steps: diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml index c064320e68..c99e86801f 100644 --- a/.github/workflows/functional-placement.yaml +++ b/.github/workflows/functional-placement.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Placement and run placement acceptance tests steps: diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml index 732833cc7d..8eb2fcfed0 100644 --- a/.github/workflows/functional-sharedfilesystems.yaml +++ b/.github/workflows/functional-sharedfilesystems.yaml @@ -18,9 +18,6 @@ jobs: - name: "antelope" openstack_version: "stable/2023.1" ubuntu_version: "22.04" - - name: "zed" - openstack_version: "stable/zed" - ubuntu_version: "20.04" runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} with Manila and run sharedfilesystems acceptance tests steps: From 357c644c8fa860d1fbcf1fbaeb6174e09764cbd4 Mon Sep 17 00:00:00 2001 From: nikParasyr Date: Mon, 22 Apr 2024 11:22:41 +0200 Subject: [PATCH 098/118] Add ci jobs for openstack caracal Openstack caracal has been released. Update functional workflows to add jobs that cover it --- .github/workflows/functional-baremetal.yaml | 4 ++++ .github/workflows/functional-basic.yaml | 3 +++ .github/workflows/functional-blockstorage.yaml | 3 +++ .github/workflows/functional-clustering.yaml | 4 ++++ .github/workflows/functional-compute.yaml | 3 +++ .github/workflows/functional-containerinfra.yaml | 6 ++++++ .github/workflows/functional-dns.yaml | 3 +++ .github/workflows/functional-fwaas_v2.yaml | 3 +++ .github/workflows/functional-identity.yaml | 3 +++ .github/workflows/functional-imageservice.yaml | 3 +++ .github/workflows/functional-keymanager.yaml | 3 +++ .github/workflows/functional-loadbalancer.yaml | 3 +++ .github/workflows/functional-messaging.yaml | 3 +++ .github/workflows/functional-networking.yaml | 3 +++ .github/workflows/functional-objectstorage.yaml | 3 +++ .github/workflows/functional-orchestration.yaml | 3 +++ .github/workflows/functional-placement.yaml | 3 +++ .github/workflows/functional-sharedfilesystems.yaml | 3 +++ 18 files changed, 59 insertions(+) diff --git a/.github/workflows/functional-baremetal.yaml b/.github/workflows/functional-baremetal.yaml index 0672b53040..4daf2d7f4b 100644 --- a/.github/workflows/functional-baremetal.yaml +++ b/.github/workflows/functional-baremetal.yaml @@ -13,6 +13,10 @@ jobs: ubuntu_version: ["22.04"] os_system_scope: ["all"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" + os_system_scope: "" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-basic.yaml b/.github/workflows/functional-basic.yaml index aa3da06dc2..61b9cbbe5d 100644 --- a/.github/workflows/functional-basic.yaml +++ b/.github/workflows/functional-basic.yaml @@ -15,6 +15,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-blockstorage.yaml b/.github/workflows/functional-blockstorage.yaml index 241eebcfb4..d4bc1fc978 100644 --- a/.github/workflows/functional-blockstorage.yaml +++ b/.github/workflows/functional-blockstorage.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-clustering.yaml b/.github/workflows/functional-clustering.yaml index a7554623ad..d31dc70717 100644 --- a/.github/workflows/functional-clustering.yaml +++ b/.github/workflows/functional-clustering.yaml @@ -12,6 +12,10 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: +## Senlin has not made a caracal release yet +# - name: "caracal" +# openstack_version: "stable/2024.1" +# ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-compute.yaml b/.github/workflows/functional-compute.yaml index 5d71efb068..23cc707a1a 100644 --- a/.github/workflows/functional-compute.yaml +++ b/.github/workflows/functional-compute.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-containerinfra.yaml b/.github/workflows/functional-containerinfra.yaml index 7dc8c4bfea..c55f2c157b 100644 --- a/.github/workflows/functional-containerinfra.yaml +++ b/.github/workflows/functional-containerinfra.yaml @@ -15,6 +15,12 @@ jobs: devstack_conf_overrides: | enable_plugin magnum https://github.com/openstack/magnum master MAGNUMCLIENT_BRANCH=master + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" + devstack_conf_overrides: | + enable_plugin magnum https://github.com/openstack/magnum stable/2024.1 + MAGNUMCLIENT_BRANCH=stable/2024.1 - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-dns.yaml b/.github/workflows/functional-dns.yaml index 979005c8e3..830e274bff 100644 --- a/.github/workflows/functional-dns.yaml +++ b/.github/workflows/functional-dns.yaml @@ -13,6 +13,9 @@ jobs: - name: "master" openstack_version: "master" ubuntu_version: "22.04" + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-fwaas_v2.yaml b/.github/workflows/functional-fwaas_v2.yaml index 99cdc1eb0b..901d17829a 100644 --- a/.github/workflows/functional-fwaas_v2.yaml +++ b/.github/workflows/functional-fwaas_v2.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-identity.yaml b/.github/workflows/functional-identity.yaml index f393fae80f..40fd53f8e3 100644 --- a/.github/workflows/functional-identity.yaml +++ b/.github/workflows/functional-identity.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-imageservice.yaml b/.github/workflows/functional-imageservice.yaml index cf173bdc9a..e5b6d6fe5d 100644 --- a/.github/workflows/functional-imageservice.yaml +++ b/.github/workflows/functional-imageservice.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-keymanager.yaml b/.github/workflows/functional-keymanager.yaml index f124a40959..6ab80a1b06 100644 --- a/.github/workflows/functional-keymanager.yaml +++ b/.github/workflows/functional-keymanager.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-loadbalancer.yaml b/.github/workflows/functional-loadbalancer.yaml index fa0b82699f..6b99107090 100644 --- a/.github/workflows/functional-loadbalancer.yaml +++ b/.github/workflows/functional-loadbalancer.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-messaging.yaml b/.github/workflows/functional-messaging.yaml index e8c5c3b770..a1fd8360e3 100644 --- a/.github/workflows/functional-messaging.yaml +++ b/.github/workflows/functional-messaging.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index 789c49eff8..b37c152def 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -12,6 +12,9 @@ jobs: - name: "master" openstack_version: "master" ubuntu_version: "22.04" + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-objectstorage.yaml b/.github/workflows/functional-objectstorage.yaml index ac12bb77e3..6a29cdb080 100644 --- a/.github/workflows/functional-objectstorage.yaml +++ b/.github/workflows/functional-objectstorage.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-orchestration.yaml b/.github/workflows/functional-orchestration.yaml index 6d217cb0d8..12d054b941 100644 --- a/.github/workflows/functional-orchestration.yaml +++ b/.github/workflows/functional-orchestration.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-placement.yaml b/.github/workflows/functional-placement.yaml index c064320e68..79ef2e152a 100644 --- a/.github/workflows/functional-placement.yaml +++ b/.github/workflows/functional-placement.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" diff --git a/.github/workflows/functional-sharedfilesystems.yaml b/.github/workflows/functional-sharedfilesystems.yaml index 732833cc7d..3ac9637c47 100644 --- a/.github/workflows/functional-sharedfilesystems.yaml +++ b/.github/workflows/functional-sharedfilesystems.yaml @@ -12,6 +12,9 @@ jobs: openstack_version: ["master"] ubuntu_version: ["22.04"] include: + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" From 43f860344acbcd10ee25a86e5300d1d0f155af53 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Mon, 27 May 2024 10:47:51 +0200 Subject: [PATCH 099/118] Prepare v1.12.0 --- CHANGELOG.md | 10 ++++++++++ provider_client.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0eec3e6dd6..a69454903f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## v1.12.0 (2024-05-27) + +* [GH-2979](https://github.com/gophercloud/gophercloud/pull/2979) [v1] CI backports +* [GH-2985](https://github.com/gophercloud/gophercloud/pull/2985) [v1] baremetal: fix handling of the "fields" query argument +* [GH-2989](https://github.com/gophercloud/gophercloud/pull/2989) [v1] [CI] Fix portbiding tests +* [GH-2992](https://github.com/gophercloud/gophercloud/pull/2992) [v1] [CI] Fix portbiding tests +* [GH-2993](https://github.com/gophercloud/gophercloud/pull/2993) [v1] build(deps): bump EmilienM/devstack-action from 0.14 to 0.15 +* [GH-2998](https://github.com/gophercloud/gophercloud/pull/2998) [v1] testhelper: mark all helpers with t.Helper +* [GH-3043](https://github.com/gophercloud/gophercloud/pull/3043) [v1] CI: remove Zed from testing coverage + ## v1.11.0 (2024-03-07) This version reverts the inclusion of Context in the v1 branch. This inclusion diff --git a/provider_client.go b/provider_client.go index 1ff54b8197..27cbc2ff71 100644 --- a/provider_client.go +++ b/provider_client.go @@ -14,7 +14,7 @@ import ( // DefaultUserAgent is the default User-Agent string set in the request header. const ( - DefaultUserAgent = "gophercloud/v1.11.0" + DefaultUserAgent = "gophercloud/v1.12.0" DefaultMaxBackoffRetries = 60 ) From 73074af6a7580f960198567f542ce1fb546bc43c Mon Sep 17 00:00:00 2001 From: Alban PRATS Date: Thu, 25 Jan 2024 10:03:44 -0500 Subject: [PATCH 100/118] Added tests for gateway qos_policy --- .../layer3/routers/testing/requests_test.go | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/openstack/networking/v2/extensions/layer3/routers/testing/requests_test.go b/openstack/networking/v2/extensions/layer3/routers/testing/requests_test.go index 81818e59d7..4f2de23b53 100644 --- a/openstack/networking/v2/extensions/layer3/routers/testing/requests_test.go +++ b/openstack/networking/v2/extensions/layer3/routers/testing/requests_test.go @@ -53,7 +53,8 @@ func TestList(t *testing.T) { "external_fixed_ips": [ {"ip_address": "192.0.2.17", "subnet_id": "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def"}, {"ip_address": "198.51.100.33", "subnet_id": "1d699529-bdfd-43f8-bcaa-bff00c547af2"} - ] + ], + "qos_policy_id": "6601bae5-f15a-4687-8be9-ddec9a2f8a8b" }, "name": "gateway", "admin_state_up": true, @@ -103,6 +104,7 @@ func TestList(t *testing.T) { {IPAddress: "192.0.2.17", SubnetID: "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def"}, {IPAddress: "198.51.100.33", SubnetID: "1d699529-bdfd-43f8-bcaa-bff00c547af2"}, }, + QoSPolicyID: "6601bae5-f15a-4687-8be9-ddec9a2f8a8b", }, AdminStateUp: true, Distributed: false, @@ -141,7 +143,8 @@ func TestCreate(t *testing.T) { "network_id":"8ca37218-28ff-41cb-9b10-039601ea7e6b", "external_fixed_ips": [ {"subnet_id": "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def"} - ] + ], + "qos_policy_id": "6601bae5-f15a-4687-8be9-ddec9a2f8a8b" }, "availability_zone_hints": ["zone1", "zone2"] } @@ -160,7 +163,8 @@ func TestCreate(t *testing.T) { "enable_snat": false, "external_fixed_ips": [ {"ip_address": "192.0.2.17", "subnet_id": "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def"} - ] + ], + "qos_policy_id": "6601bae5-f15a-4687-8be9-ddec9a2f8a8b" }, "name": "foo_router", "admin_state_up": false, @@ -175,6 +179,7 @@ func TestCreate(t *testing.T) { asu := false enableSNAT := false + qosID := "6601bae5-f15a-4687-8be9-ddec9a2f8a8b" efi := []routers.ExternalFixedIP{ { SubnetID: "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def", @@ -184,6 +189,7 @@ func TestCreate(t *testing.T) { NetworkID: "8ca37218-28ff-41cb-9b10-039601ea7e6b", EnableSNAT: &enableSNAT, ExternalFixedIPs: efi, + QoSPolicyID: qosID, } options := routers.CreateOpts{ Name: "foo_router", @@ -224,7 +230,8 @@ func TestGet(t *testing.T) { "network_id": "85d76829-6415-48ff-9c63-5c5ca8c61ac6", "external_fixed_ips": [ {"ip_address": "198.51.100.33", "subnet_id": "1d699529-bdfd-43f8-bcaa-bff00c547af2"} - ] + ], + "qos_policy_id": "6601bae5-f15a-4687-8be9-ddec9a2f8a8b" }, "routes": [ { @@ -252,6 +259,7 @@ func TestGet(t *testing.T) { ExternalFixedIPs: []routers.ExternalFixedIP{ {IPAddress: "198.51.100.33", SubnetID: "1d699529-bdfd-43f8-bcaa-bff00c547af2"}, }, + QoSPolicyID: "6601bae5-f15a-4687-8be9-ddec9a2f8a8b", }) th.AssertEquals(t, n.Name, "router1") th.AssertEquals(t, n.AdminStateUp, true) @@ -275,7 +283,8 @@ func TestUpdate(t *testing.T) { "router": { "name": "new_name", "external_gateway_info": { - "network_id": "8ca37218-28ff-41cb-9b10-039601ea7e6b" + "network_id": "8ca37218-28ff-41cb-9b10-039601ea7e6b", + "qos_policy_id": "01ba32e5-f15a-4687-8be9-ddec92a2f8a8" }, "routes": [ { @@ -298,7 +307,8 @@ func TestUpdate(t *testing.T) { "network_id": "8ca37218-28ff-41cb-9b10-039601ea7e6b", "external_fixed_ips": [ {"ip_address": "192.0.2.17", "subnet_id": "ab561bc4-1a8e-48f2-9fbd-376fcb1a1def"} - ] + ], + "qos_policy_id": "01ba32e5-f15a-4687-8be9-ddec92a2f8a8" }, "name": "new_name", "admin_state_up": true, @@ -316,7 +326,10 @@ func TestUpdate(t *testing.T) { `) }) - gwi := routers.GatewayInfo{NetworkID: "8ca37218-28ff-41cb-9b10-039601ea7e6b"} + gwi := routers.GatewayInfo{ + NetworkID: "8ca37218-28ff-41cb-9b10-039601ea7e6b", + QoSPolicyID: "01ba32e5-f15a-4687-8be9-ddec92a2f8a8", + } r := []routers.Route{{DestinationCIDR: "40.0.1.0/24", NextHop: "10.1.0.10"}} options := routers.UpdateOpts{Name: "new_name", GatewayInfo: &gwi, Routes: &r} From 89c670ff759db75804d897305a8536ec2eddcd29 Mon Sep 17 00:00:00 2001 From: Alban PRATS Date: Thu, 25 Jan 2024 09:24:33 -0500 Subject: [PATCH 101/118] Adding missing QoS field for router --- openstack/networking/v2/extensions/layer3/routers/results.go | 1 + 1 file changed, 1 insertion(+) diff --git a/openstack/networking/v2/extensions/layer3/routers/results.go b/openstack/networking/v2/extensions/layer3/routers/results.go index 0c93918991..1c93eab506 100644 --- a/openstack/networking/v2/extensions/layer3/routers/results.go +++ b/openstack/networking/v2/extensions/layer3/routers/results.go @@ -14,6 +14,7 @@ type GatewayInfo struct { NetworkID string `json:"network_id,omitempty"` EnableSNAT *bool `json:"enable_snat,omitempty"` ExternalFixedIPs []ExternalFixedIP `json:"external_fixed_ips,omitempty"` + QoSPolicyID string `json:"qos_policy_id,omitempty"` } // ExternalFixedIP is the IP address and subnet ID of the external gateway of a From e3b10b88e97aad237186f4a26ff25249d76627e1 Mon Sep 17 00:00:00 2001 From: kayrus Date: Mon, 1 Jul 2024 15:43:56 +0200 Subject: [PATCH 102/118] [networking]: add BGP VPNs support --- .github/workflows/functional-networking.yaml | 1 + .../v2/extensions/bgpvpns/bgpvpns.go | 27 + .../v2/extensions/bgpvpns/bgpvpns_test.go | 246 +++++++++ .../networking/v2/extensions/bgpvpns/doc.go | 2 + .../networking/v2/extensions/bgpvpns/doc.go | 66 +++ .../v2/extensions/bgpvpns/requests.go | 476 ++++++++++++++++ .../v2/extensions/bgpvpns/results.go | 517 ++++++++++++++++++ .../v2/extensions/bgpvpns/testing/doc.go | 2 + .../v2/extensions/bgpvpns/testing/fixture.go | 434 +++++++++++++++ .../bgpvpns/testing/requests_test.go | 513 +++++++++++++++++ .../networking/v2/extensions/bgpvpns/urls.go | 140 +++++ 11 files changed, 2424 insertions(+) create mode 100644 internal/acceptance/openstack/networking/v2/extensions/bgpvpns/bgpvpns.go create mode 100644 internal/acceptance/openstack/networking/v2/extensions/bgpvpns/bgpvpns_test.go create mode 100644 internal/acceptance/openstack/networking/v2/extensions/bgpvpns/doc.go create mode 100644 openstack/networking/v2/extensions/bgpvpns/doc.go create mode 100644 openstack/networking/v2/extensions/bgpvpns/requests.go create mode 100644 openstack/networking/v2/extensions/bgpvpns/results.go create mode 100644 openstack/networking/v2/extensions/bgpvpns/testing/doc.go create mode 100644 openstack/networking/v2/extensions/bgpvpns/testing/fixture.go create mode 100644 openstack/networking/v2/extensions/bgpvpns/testing/requests_test.go create mode 100644 openstack/networking/v2/extensions/bgpvpns/urls.go diff --git a/.github/workflows/functional-networking.yaml b/.github/workflows/functional-networking.yaml index 11f4d4df42..dc4066bcd9 100644 --- a/.github/workflows/functional-networking.yaml +++ b/.github/workflows/functional-networking.yaml @@ -41,6 +41,7 @@ jobs: conf_overrides: | enable_plugin neutron-dynamic-routing https://github.com/openstack/neutron-dynamic-routing ${{ matrix.openstack_version }} enable_plugin neutron-vpnaas https://github.com/openstack/neutron-vpnaas ${{ matrix.openstack_version }} + enable_plugin networking-bgpvpn https://github.com/openstack/networking-bgpvpn.git ${{ matrix.openstack_version }} Q_ML2_PLUGIN_EXT_DRIVERS=qos,port_security,dns_domain_keywords [[post-config|\$NEUTRON_CONF]] diff --git a/internal/acceptance/openstack/networking/v2/extensions/bgpvpns/bgpvpns.go b/internal/acceptance/openstack/networking/v2/extensions/bgpvpns/bgpvpns.go new file mode 100644 index 0000000000..e7dca49b80 --- /dev/null +++ b/internal/acceptance/openstack/networking/v2/extensions/bgpvpns/bgpvpns.go @@ -0,0 +1,27 @@ +package bgpvpns + +import ( + "testing" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" + "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/bgpvpns" + th "github.com/gophercloud/gophercloud/testhelper" +) + +func CreateBGPVPN(t *testing.T, client *gophercloud.ServiceClient) (*bgpvpns.BGPVPN, error) { + opts := bgpvpns.CreateOpts{ + Name: tools.RandomString("TESTACC-BGPVPN-", 10), + } + + t.Logf("Attempting to create BGP VPN: %s", opts.Name) + bgpVpn, err := bgpvpns.Create(client, opts).Extract() + if err != nil { + return bgpVpn, err + } + + th.AssertEquals(t, bgpVpn.Name, opts.Name) + t.Logf("Successfully created BGP VPN") + tools.PrintResource(t, bgpVpn) + return bgpVpn, err +} diff --git a/internal/acceptance/openstack/networking/v2/extensions/bgpvpns/bgpvpns_test.go b/internal/acceptance/openstack/networking/v2/extensions/bgpvpns/bgpvpns_test.go new file mode 100644 index 0000000000..4232812a94 --- /dev/null +++ b/internal/acceptance/openstack/networking/v2/extensions/bgpvpns/bgpvpns_test.go @@ -0,0 +1,246 @@ +//go:build acceptance || networking || bgp || bgpvpns + +package bgpvpns + +import ( + "testing" + + "github.com/gophercloud/gophercloud/internal/acceptance/clients" + networking "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2" + "github.com/gophercloud/gophercloud/internal/acceptance/openstack/networking/v2/extensions/layer3" + "github.com/gophercloud/gophercloud/internal/acceptance/tools" + "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/bgpvpns" + th "github.com/gophercloud/gophercloud/testhelper" +) + +func TestBGPVPNCRUD(t *testing.T) { + clients.RequireAdmin(t) + + client, err := clients.NewNetworkV2Client() + th.AssertNoErr(t, err) + + // Create a BGP VPN + bgpVpnCreated, err := CreateBGPVPN(t, client) + th.AssertNoErr(t, err) + + // Get a BGP VPN + bgpVpnGot, err := bgpvpns.Get(client, bgpVpnCreated.ID).Extract() + th.AssertNoErr(t, err) + th.AssertEquals(t, bgpVpnCreated.ID, bgpVpnGot.ID) + th.AssertEquals(t, bgpVpnCreated.Name, bgpVpnGot.Name) + + // Update a BGP VPN + newBGPVPNName := tools.RandomString("TESTACC-BGPVPN-", 10) + updateBGPOpts := bgpvpns.UpdateOpts{ + Name: &newBGPVPNName, + } + bgpVpnUpdated, err := bgpvpns.Update(client, bgpVpnGot.ID, updateBGPOpts).Extract() + th.AssertNoErr(t, err) + th.AssertEquals(t, newBGPVPNName, bgpVpnUpdated.Name) + t.Logf("Update BGP VPN, renamed from %s to %s", bgpVpnGot.Name, bgpVpnUpdated.Name) + + // List all BGP VPNs + allPages, err := bgpvpns.List(client, bgpvpns.ListOpts{}).AllPages() + th.AssertNoErr(t, err) + allVPNs, err := bgpvpns.ExtractBGPVPNs(allPages) + th.AssertNoErr(t, err) + + t.Logf("Retrieved BGP VPNs") + tools.PrintResource(t, allVPNs) + th.AssertIntGreaterOrEqual(t, len(allVPNs), 1) + + // Delete a BGP VPN + t.Logf("Attempting to delete BGP VPN: %s", bgpVpnUpdated.Name) + err = bgpvpns.Delete(client, bgpVpnUpdated.ID).ExtractErr() + th.AssertNoErr(t, err) + + _, err = bgpvpns.Get(client, bgpVpnGot.ID).Extract() + th.AssertErr(t, err) + t.Logf("BGP VPN %s deleted", bgpVpnUpdated.Name) +} + +func TestBGPVPNNetworkAssociationCRD(t *testing.T) { + clients.RequireAdmin(t) + + client, err := clients.NewNetworkV2Client() + th.AssertNoErr(t, err) + + // Create a BGP VPN + bgpVpnCreated, err := CreateBGPVPN(t, client) + th.AssertNoErr(t, err) + defer func() { + err = bgpvpns.Delete(client, bgpVpnCreated.ID).ExtractErr() + th.AssertNoErr(t, err) + }() + + // Create a Network + network, err := networking.CreateNetwork(t, client) + th.AssertNoErr(t, err) + defer networking.DeleteNetwork(t, client, network.ID) + + // Associate a Network with a BGP VPN + assocOpts := bgpvpns.CreateNetworkAssociationOpts{ + NetworkID: network.ID, + } + assoc, err := bgpvpns.CreateNetworkAssociation(client, bgpVpnCreated.ID, assocOpts).Extract() + th.AssertNoErr(t, err) + defer func() { + err = bgpvpns.DeleteNetworkAssociation(client, bgpVpnCreated.ID, assoc.ID).ExtractErr() + th.AssertNoErr(t, err) + }() + th.AssertEquals(t, network.ID, assoc.NetworkID) + + // Get a Network Association + assocGot, err := bgpvpns.GetNetworkAssociation(client, bgpVpnCreated.ID, assoc.ID).Extract() + th.AssertNoErr(t, err) + th.AssertEquals(t, network.ID, assocGot.NetworkID) + + // List all Network Associations + allPages, err := bgpvpns.ListNetworkAssociations(client, bgpVpnCreated.ID, bgpvpns.ListNetworkAssociationsOpts{}).AllPages() + th.AssertNoErr(t, err) + allAssocs, err := bgpvpns.ExtractNetworkAssociations(allPages) + th.AssertNoErr(t, err) + t.Logf("Retrieved Network Associations") + tools.PrintResource(t, allAssocs) + th.AssertIntGreaterOrEqual(t, len(allAssocs), 1) + + // Get BGP VPN with associations + getBgpVpn, err := bgpvpns.Get(client, bgpVpnCreated.ID).Extract() + th.AssertNoErr(t, err) + tools.PrintResource(t, getBgpVpn) +} + +func TestBGPVPNRouterAssociationCRUD(t *testing.T) { + clients.RequireAdmin(t) + + client, err := clients.NewNetworkV2Client() + th.AssertNoErr(t, err) + + // Create a BGP VPN + bgpVpnCreated, err := CreateBGPVPN(t, client) + th.AssertNoErr(t, err) + defer func() { + err = bgpvpns.Delete(client, bgpVpnCreated.ID).ExtractErr() + th.AssertNoErr(t, err) + }() + + // Create a Network + network, err := networking.CreateNetwork(t, client) + th.AssertNoErr(t, err) + defer networking.DeleteNetwork(t, client, network.ID) + + // Create a Router + routerCreated, err := layer3.CreateRouter(t, client, network.ID) + th.AssertNoErr(t, err) + defer layer3.DeleteRouter(t, client, routerCreated.ID) + + // Associate a Router with a BGP VPN + assocOpts := bgpvpns.CreateRouterAssociationOpts{ + RouterID: routerCreated.ID, + } + assoc, err := bgpvpns.CreateRouterAssociation(client, bgpVpnCreated.ID, assocOpts).Extract() + th.AssertNoErr(t, err) + defer func() { + err = bgpvpns.DeleteRouterAssociation(client, bgpVpnCreated.ID, assoc.ID).ExtractErr() + th.AssertNoErr(t, err) + }() + th.AssertEquals(t, routerCreated.ID, assoc.RouterID) + + // Get a Router Association + assocGot, err := bgpvpns.GetRouterAssociation(client, bgpVpnCreated.ID, assoc.ID).Extract() + th.AssertNoErr(t, err) + th.AssertEquals(t, routerCreated.ID, assocGot.RouterID) + + // Update a Router Association + assocUpdOpts := bgpvpns.UpdateRouterAssociationOpts{ + AdvertiseExtraRoutes: new(bool), + } + assocUpdate, err := bgpvpns.UpdateRouterAssociation(client, bgpVpnCreated.ID, assoc.ID, assocUpdOpts).Extract() + th.AssertNoErr(t, err) + th.AssertEquals(t, routerCreated.ID, assocUpdate.RouterID) + th.AssertEquals(t, false, assocUpdate.AdvertiseExtraRoutes) + + // List all Router Associations + allPages, err := bgpvpns.ListRouterAssociations(client, bgpVpnCreated.ID, bgpvpns.ListRouterAssociationsOpts{}).AllPages() + th.AssertNoErr(t, err) + allAssocs, err := bgpvpns.ExtractRouterAssociations(allPages) + th.AssertNoErr(t, err) + t.Logf("Retrieved Router Associations") + tools.PrintResource(t, allAssocs) + th.AssertIntGreaterOrEqual(t, len(allAssocs), 1) + + // Get BGP VPN with associations + getBgpVpn, err := bgpvpns.Get(client, bgpVpnCreated.ID).Extract() + th.AssertNoErr(t, err) + tools.PrintResource(t, getBgpVpn) +} + +func TestBGPVPNPortAssociationCRUD(t *testing.T) { + clients.RequireAdmin(t) + + client, err := clients.NewNetworkV2Client() + th.AssertNoErr(t, err) + + // Create a BGP VPN + bgpVpnCreated, err := CreateBGPVPN(t, client) + th.AssertNoErr(t, err) + defer func() { + err = bgpvpns.Delete(client, bgpVpnCreated.ID).ExtractErr() + th.AssertNoErr(t, err) + }() + + // Create a Network + network, err := networking.CreateNetwork(t, client) + th.AssertNoErr(t, err) + defer networking.DeleteNetwork(t, client, network.ID) + + // Create Subnet + subnet, err := networking.CreateSubnet(t, client, network.ID) + th.AssertNoErr(t, err) + defer networking.DeleteSubnet(t, client, subnet.ID) + + // Create port + port, err := networking.CreatePort(t, client, network.ID, subnet.ID) + th.AssertNoErr(t, err) + defer networking.DeletePort(t, client, port.ID) + + // Associate a Port with a BGP VPN + assocOpts := bgpvpns.CreatePortAssociationOpts{ + PortID: port.ID, + } + assoc, err := bgpvpns.CreatePortAssociation(client, bgpVpnCreated.ID, assocOpts).Extract() + th.AssertNoErr(t, err) + defer func() { + err = bgpvpns.DeletePortAssociation(client, bgpVpnCreated.ID, assoc.ID).ExtractErr() + th.AssertNoErr(t, err) + }() + th.AssertEquals(t, port.ID, assoc.PortID) + + // Get a Port Association + assocGot, err := bgpvpns.GetPortAssociation(client, bgpVpnCreated.ID, assoc.ID).Extract() + th.AssertNoErr(t, err) + th.AssertEquals(t, port.ID, assocGot.PortID) + + // Update a Port Association + assocUpdOpts := bgpvpns.UpdatePortAssociationOpts{ + AdvertiseFixedIPs: new(bool), + } + assocUpdate, err := bgpvpns.UpdatePortAssociation(client, bgpVpnCreated.ID, assoc.ID, assocUpdOpts).Extract() + th.AssertNoErr(t, err) + th.AssertEquals(t, port.ID, assocUpdate.PortID) + th.AssertEquals(t, false, assocUpdate.AdvertiseFixedIPs) + + // List all Port Associations + allPages, err := bgpvpns.ListPortAssociations(client, bgpVpnCreated.ID, bgpvpns.ListPortAssociationsOpts{}).AllPages() + th.AssertNoErr(t, err) + allAssocs, err := bgpvpns.ExtractPortAssociations(allPages) + th.AssertNoErr(t, err) + t.Logf("Retrieved Port Associations") + tools.PrintResource(t, allAssocs) + th.AssertIntGreaterOrEqual(t, len(allAssocs), 1) + + // Get BGP VPN with associations + getBgpVpn, err := bgpvpns.Get(client, bgpVpnCreated.ID).Extract() + th.AssertNoErr(t, err) + tools.PrintResource(t, getBgpVpn) +} diff --git a/internal/acceptance/openstack/networking/v2/extensions/bgpvpns/doc.go b/internal/acceptance/openstack/networking/v2/extensions/bgpvpns/doc.go new file mode 100644 index 0000000000..d6db7c50b2 --- /dev/null +++ b/internal/acceptance/openstack/networking/v2/extensions/bgpvpns/doc.go @@ -0,0 +1,2 @@ +// BGP VPN acceptance tests +package bgpvpns diff --git a/openstack/networking/v2/extensions/bgpvpns/doc.go b/openstack/networking/v2/extensions/bgpvpns/doc.go new file mode 100644 index 0000000000..cdb85dc101 --- /dev/null +++ b/openstack/networking/v2/extensions/bgpvpns/doc.go @@ -0,0 +1,66 @@ +package bgpvpns + +/* +Package bgpvpns contains the functionality for working with Neutron BGP VPNs. + +1. List BGP VPNs, a.k.a. GET /bgpvpn/bgpvpns + +Example: + + pages, err := bgpvpns.List(client).AllPages(context.TODO()) + if err != nil { + log.Panic(err) + } + allVPNs, err := bgpvpns.ExtractBGPVPNs(pages) + if err != nil { + log.Panic(err) + } + + for _, bgpvpn := range allVPNs { + log.Printf("%+v", bgpvpn) + } + +2. Get BGP VPN, a.k.a. GET /bgpvpn/bgpvpns/{id} + +Example: + p, err := bgpvpns.Get(context.TODO(), client, id).Extract() + if err != nil { + log.Panic(err) + } + log.Printf("%+v", *p) + +3. Create BGP VPN, a.k.a. POST /bgpvpn/bgpvpns + +Example: + opts := bgpvpns.CreateOpts{ + name: "gophercloud-testing-bgpvpn". + } + r, err := bgpvpns.Create(context.TODO(), client, opts).Extract() + if err != nil { + log.Panic(err) + } + log.Printf("%+v", *r) + +4. Delete BGP VPN, a.k.a. DELETE /bgpvpn/bgpvpns/{id} + +Example: + err := bgpvpns.Delete(context.TODO(), client, bgpVpnID).ExtractErr() + if err != nil { + log.Panic(err) + } + log.Printf("BGP VPN deleted") + + +5. Update BGP VPN, a.k.a. PUT /bgpvpn/bgpvpns/{id} + +Example: + nameUpdated := "bgpvpn-name-updated" + opts := bgpvpns.UpdateOpts{ + name: &nameUpdated, + } + p, err := bgpvpns.Update(context.TODO(), client, id, opts).Extract() + if err != nil { + log.Panic(err) + } + log.Printf("%+v", p) +*/ diff --git a/openstack/networking/v2/extensions/bgpvpns/requests.go b/openstack/networking/v2/extensions/bgpvpns/requests.go new file mode 100644 index 0000000000..dce09fde1b --- /dev/null +++ b/openstack/networking/v2/extensions/bgpvpns/requests.go @@ -0,0 +1,476 @@ +package bgpvpns + +import ( + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +// ListOptsBuilder allows extensions to add additional parameters to the List +// request. +type ListOptsBuilder interface { + ToBGPVPNListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through the API. +type ListOpts struct { + Fields []string `q:"fields"` + ProjectID string `q:"project_id"` + Networks []string `q:"networks"` + Routers []string `q:"routers"` + Ports []string `q:"ports"` + Limit int `q:"limit"` + Marker string `q:"marker"` +} + +// ToBGPVPNListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToBGPVPNListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// List the BGP VPNs +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listURL(c) + query, err := opts.ToBGPVPNListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + p := BGPVPNPage{pagination.MarkerPageBase{PageResult: r}} + p.MarkerPageBase.Owner = p + return p + }) +} + +// Get retrieve the specific BGP VPN by its uuid +func Get(c *gophercloud.ServiceClient, id string) (r GetResult) { + resp, err := c.Get(getURL(c, id), &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. +type CreateOptsBuilder interface { + ToBGPVPNCreateMap() (map[string]interface{}, error) +} + +// CreateOpts represents options used to create a BGP VPN. +type CreateOpts struct { + Name string `json:"name,omitempty"` + RouteDistinguishers []string `json:"route_distinguishers,omitempty"` + RouteTargets []string `json:"route_targets,omitempty"` + ImportTargets []string `json:"import_targets,omitempty"` + ExportTargets []string `json:"export_targets,omitempty"` + LocalPref int `json:"local_pref,omitempty"` + VNI int `json:"vni,omitempty"` + TenantID string `json:"tenant_id,omitempty"` + ProjectID string `json:"project_id,omitempty"` + Type string `json:"type,omitempty"` +} + +// ToBGPVPNCreateMap builds a request body from CreateOpts. +func (opts CreateOpts) ToBGPVPNCreateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "bgpvpn") +} + +// Create a BGP VPN +func Create(c *gophercloud.ServiceClient, opts CreateOpts) (r CreateResult) { + b, err := opts.ToBGPVPNCreateMap() + if err != nil { + r.Err = err + return + } + resp, err := c.Post(createURL(c), b, &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// Delete accepts a unique ID and deletes the BGP VPN associated with it. +func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) { + resp, err := c.Delete(deleteURL(c, id), nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// UpdateOptsBuilder allows extensions to add additional parameters to the +// Update request. +type UpdateOptsBuilder interface { + ToBGPVPNUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts represents options used to update a BGP VPN. +type UpdateOpts struct { + Name *string `json:"name,omitempty"` + RouteDistinguishers *[]string `json:"route_distinguishers,omitempty"` + RouteTargets *[]string `json:"route_targets,omitempty"` + ImportTargets *[]string `json:"import_targets,omitempty"` + ExportTargets *[]string `json:"export_targets,omitempty"` + LocalPref *int `json:"local_pref,omitempty"` +} + +// ToBGPVPNUpdateMap builds a request body from UpdateOpts. +func (opts UpdateOpts) ToBGPVPNUpdateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "bgpvpn") +} + +// Update accept a BGP VPN ID and an UpdateOpts and update the BGP VPN +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) (r UpdateResult) { + b, err := opts.ToBGPVPNUpdateMap() + if err != nil { + r.Err = err + return + } + resp, err := c.Put(updateURL(c, id), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// ListNetworkAssociationsOptsBuilder allows extensions to add additional +// parameters to the ListNetworkAssociations request. +type ListNetworkAssociationsOptsBuilder interface { + ToNetworkAssociationsListQuery() (string, error) +} + +// ListNetworkAssociationsOpts allows the filtering and sorting of paginated +// collections through the API. +type ListNetworkAssociationsOpts struct { + Fields []string `q:"fields"` + Limit int `q:"limit"` + Marker string `q:"marker"` +} + +// ToNetworkAssociationsListQuery formats a ListNetworkAssociationsOpts into a +// query string. +func (opts ListNetworkAssociationsOpts) ToNetworkAssociationsListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// ListNetworkAssociations pages over the network associations of a specified +// BGP VPN. +func ListNetworkAssociations(c *gophercloud.ServiceClient, id string, opts ListNetworkAssociationsOptsBuilder) pagination.Pager { + url := listNetworkAssociationsURL(c, id) + query, err := opts.ToNetworkAssociationsListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + p := NetworkAssociationPage{pagination.MarkerPageBase{PageResult: r}} + p.MarkerPageBase.Owner = p + return p + }) +} + +// CreateNetworkAssociationOptsBuilder allows extensions to add additional +// parameters to the CreateNetworkAssociation request. +type CreateNetworkAssociationOptsBuilder interface { + ToNetworkAssociationCreateMap() (map[string]interface{}, error) +} + +// CreateNetworkAssociationOpts represents options used to create a BGP VPN +// network association. +type CreateNetworkAssociationOpts struct { + NetworkID string `json:"network_id" required:"true"` + TenantID string `json:"tenant_id,omitempty"` + ProjectID string `json:"project_id,omitempty"` +} + +// ToNetworkAssociationCreateMap builds a request body from +// CreateNetworkAssociationOpts. +func (opts CreateNetworkAssociationOpts) ToNetworkAssociationCreateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "network_association") +} + +// CreateNetworkAssociation creates a new network association for a specified +// BGP VPN. +func CreateNetworkAssociation(client *gophercloud.ServiceClient, id string, opts CreateNetworkAssociationOptsBuilder) (r CreateNetworkAssociationResult) { + b, err := opts.ToNetworkAssociationCreateMap() + if err != nil { + r.Err = err + return + } + resp, err := client.Post(createNetworkAssociationURL(client, id), b, &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// GetNetworkAssociation retrieves a specific network association by BGP VPN id +// and network association id. +func GetNetworkAssociation(c *gophercloud.ServiceClient, bgpVpnID string, id string) (r GetNetworkAssociationResult) { + resp, err := c.Get(getNetworkAssociationURL(c, bgpVpnID, id), &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// DeleteNetworkAssociation deletes a specific network association by BGP VPN id +// and network association id. +func DeleteNetworkAssociation(c *gophercloud.ServiceClient, bgpVpnID string, id string) (r DeleteNetworkAssociationResult) { + resp, err := c.Delete(deleteNetworkAssociationURL(c, bgpVpnID, id), nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// ListRouterAssociationsOptsBuilder allows extensions to add additional +// parameters to the ListRouterAssociations request. +type ListRouterAssociationsOptsBuilder interface { + ToRouterAssociationsListQuery() (string, error) +} + +// ListRouterAssociationsOpts allows the filtering and sorting of paginated +// collections through the API. +type ListRouterAssociationsOpts struct { + Fields []string `q:"fields"` + Limit int `q:"limit"` + Marker string `q:"marker"` +} + +// ToRouterAssociationsListQuery formats a ListRouterAssociationsOpts into a +// query string. +func (opts ListRouterAssociationsOpts) ToRouterAssociationsListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// ListRouterAssociations pages over the router associations of a specified +// BGP VPN. +func ListRouterAssociations(c *gophercloud.ServiceClient, id string, opts ListRouterAssociationsOptsBuilder) pagination.Pager { + url := listRouterAssociationsURL(c, id) + query, err := opts.ToRouterAssociationsListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + p := RouterAssociationPage{pagination.MarkerPageBase{PageResult: r}} + p.MarkerPageBase.Owner = p + return p + }) +} + +// CreateRouterAssociationOptsBuilder allows extensions to add additional +// parameters to the CreateRouterAssociation request. +type CreateRouterAssociationOptsBuilder interface { + ToRouterAssociationCreateMap() (map[string]interface{}, error) +} + +// CreateRouterAssociationOpts represents options used to create a BGP VPN +// router association. +type CreateRouterAssociationOpts struct { + RouterID string `json:"router_id" required:"true"` + AdvertiseExtraRoutes *bool `json:"advertise_extra_routes,omitempty"` + TenantID string `json:"tenant_id,omitempty"` + ProjectID string `json:"project_id,omitempty"` +} + +// ToRouterAssociationCreateMap builds a request body from +// CreateRouterAssociationOpts. +func (opts CreateRouterAssociationOpts) ToRouterAssociationCreateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "router_association") +} + +// CreateRouterAssociation creates a new router association for a specified +// BGP VPN. +func CreateRouterAssociation(client *gophercloud.ServiceClient, id string, opts CreateRouterAssociationOptsBuilder) (r CreateRouterAssociationResult) { + b, err := opts.ToRouterAssociationCreateMap() + if err != nil { + r.Err = err + return + } + resp, err := client.Post(createRouterAssociationURL(client, id), b, &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// GetRouterAssociation retrieves a specific router association by BGP VPN id +// and router association id. +func GetRouterAssociation(c *gophercloud.ServiceClient, bgpVpnID string, id string) (r GetRouterAssociationResult) { + resp, err := c.Get(getRouterAssociationURL(c, bgpVpnID, id), &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// DeleteRouterAssociation deletes a specific router association by BGP VPN id +// and router association id. +func DeleteRouterAssociation(c *gophercloud.ServiceClient, bgpVpnID string, id string) (r DeleteRouterAssociationResult) { + resp, err := c.Delete(deleteRouterAssociationURL(c, bgpVpnID, id), nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// UpdateRouterAssociationOptsBuilder allows extensions to add additional +// parameters to the UpdateRouterAssociation request. +type UpdateRouterAssociationOptsBuilder interface { + ToRouterAssociationUpdateMap() (map[string]interface{}, error) +} + +// UpdateRouterAssociationOpts represents options used to update a BGP VPN +// router association. +type UpdateRouterAssociationOpts struct { + AdvertiseExtraRoutes *bool `json:"advertise_extra_routes,omitempty"` +} + +// ToRouterAssociationUpdateMap builds a request body from +// UpdateRouterAssociationOpts. +func (opts UpdateRouterAssociationOpts) ToRouterAssociationUpdateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "router_association") +} + +// UpdateRouterAssociation updates a router association for a specified BGP VPN. +func UpdateRouterAssociation(client *gophercloud.ServiceClient, bgpVpnID string, id string, opts UpdateRouterAssociationOptsBuilder) (r UpdateRouterAssociationResult) { + b, err := opts.ToRouterAssociationUpdateMap() + if err != nil { + r.Err = err + return + } + resp, err := client.Put(updateRouterAssociationURL(client, bgpVpnID, id), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// ListPortAssociationsOptsBuilder allows extensions to add additional +// parameters to the ListPortAssociations request. +type ListPortAssociationsOptsBuilder interface { + ToPortAssociationsListQuery() (string, error) +} + +// ListPortAssociationsOpts allows the filtering and sorting of paginated +// collections through the API. +type ListPortAssociationsOpts struct { + Fields []string `q:"fields"` + Limit int `q:"limit"` + Marker string `q:"marker"` +} + +// ToPortAssociationsListQuery formats a ListPortAssociationsOpts into a +// query string. +func (opts ListPortAssociationsOpts) ToPortAssociationsListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), nil +} + +// ListPortAssociations pages over the port associations of a specified +// BGP VPN. +func ListPortAssociations(c *gophercloud.ServiceClient, id string, opts ListPortAssociationsOptsBuilder) pagination.Pager { + url := listPortAssociationsURL(c, id) + query, err := opts.ToPortAssociationsListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + p := PortAssociationPage{pagination.MarkerPageBase{PageResult: r}} + p.MarkerPageBase.Owner = p + return p + }) +} + +// PortRoutes represents the routes to be advertised by a BGP VPN port +type PortRoutes struct { + Type string `json:"type" required:"true"` + Prefix string `json:"prefix,omitempty"` + BGPVPNID string `json:"bgpvpn_id,omitempty"` + LocalPref *int `json:"local_pref,omitempty"` +} + +// CreatePortAssociationOptsBuilder allows extensions to add additional +// parameters to the CreatePortAssociation request. +type CreatePortAssociationOptsBuilder interface { + ToPortAssociationCreateMap() (map[string]interface{}, error) +} + +// CreatePortAssociationOpts represents options used to create a BGP VPN +// port association. +type CreatePortAssociationOpts struct { + PortID string `json:"port_id" required:"true"` + Routes []PortRoutes `json:"routes,omitempty"` + AdvertiseFixedIPs *bool `json:"advertise_fixed_ips,omitempty"` + TenantID string `json:"tenant_id,omitempty"` + ProjectID string `json:"project_id,omitempty"` +} + +// ToPortAssociationCreateMap builds a request body from +// CreatePortAssociationOpts. +func (opts CreatePortAssociationOpts) ToPortAssociationCreateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "port_association") +} + +// CreatePortAssociation creates a new port association for a specified +// BGP VPN. +func CreatePortAssociation(client *gophercloud.ServiceClient, id string, opts CreatePortAssociationOptsBuilder) (r CreatePortAssociationResult) { + b, err := opts.ToPortAssociationCreateMap() + if err != nil { + r.Err = err + return + } + resp, err := client.Post(createPortAssociationURL(client, id), b, &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// GetPortAssociation retrieves a specific port association by BGP VPN id +// and port association id. +func GetPortAssociation(c *gophercloud.ServiceClient, bgpVpnID string, id string) (r GetPortAssociationResult) { + resp, err := c.Get(getPortAssociationURL(c, bgpVpnID, id), &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// DeletePortAssociation deletes a specific port association by BGP VPN id +// and port association id. +func DeletePortAssociation(c *gophercloud.ServiceClient, bgpVpnID string, id string) (r DeletePortAssociationResult) { + resp, err := c.Delete(deletePortAssociationURL(c, bgpVpnID, id), nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// UpdatePortAssociationOptsBuilder allows extensions to add additional +// parameters to the UpdatePortAssociation request. +type UpdatePortAssociationOptsBuilder interface { + ToPortAssociationUpdateMap() (map[string]interface{}, error) +} + +// UpdatePortAssociationOpts represents options used to update a BGP VPN +// port association. +type UpdatePortAssociationOpts struct { + Routes *[]PortRoutes `json:"routes,omitempty"` + AdvertiseFixedIPs *bool `json:"advertise_fixed_ips,omitempty"` +} + +// ToPortAssociationUpdateMap builds a request body from +// UpdatePortAssociationOpts. +func (opts UpdatePortAssociationOpts) ToPortAssociationUpdateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "port_association") +} + +// UpdatePortAssociation updates a port association for a specified BGP VPN. +func UpdatePortAssociation(client *gophercloud.ServiceClient, bgpVpnID string, id string, opts UpdatePortAssociationOptsBuilder) (r UpdatePortAssociationResult) { + b, err := opts.ToPortAssociationUpdateMap() + if err != nil { + r.Err = err + return + } + resp, err := client.Put(updatePortAssociationURL(client, bgpVpnID, id), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} diff --git a/openstack/networking/v2/extensions/bgpvpns/results.go b/openstack/networking/v2/extensions/bgpvpns/results.go new file mode 100644 index 0000000000..ae6512edca --- /dev/null +++ b/openstack/networking/v2/extensions/bgpvpns/results.go @@ -0,0 +1,517 @@ +package bgpvpns + +import ( + "net/url" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +const ( + invalidMarker = "-1" +) + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a BGP VPN resource. +func (r commonResult) Extract() (*BGPVPN, error) { + var s BGPVPN + err := r.ExtractInto(&s) + return &s, err +} + +func (r commonResult) ExtractInto(v interface{}) error { + return r.Result.ExtractIntoStructPtr(v, "bgpvpn") +} + +// BGPVPN represents an MPLS network with which Neutron routers and/or networks +// may be associated +type BGPVPN struct { + // The ID of the BGP VPN. + ID string `json:"id"` + + // The user meaningful name of the BGP VPN. + Name string `json:"name"` + + // Selection of the type of VPN and the technology behind it. Allowed + // values are l2 or l3. + Type string `json:"type"` + + // Indicates whether this BGP VPN is shared across tenants. + Shared bool `json:"shared"` + + // List of route distinguisher strings. If this parameter is specified, + // one of these RDs will be used to advertise VPN routes. + RouteDistinguishers []string `json:"route_distinguishers"` + + // Route Targets that will be both imported and used for export. + RouteTargets []string `json:"route_targets"` + + // Additional Route Targets that will be imported. + ImportTargets []string `json:"import_targets"` + + // Additional Route Targets that will be used for export. + ExportTargets []string `json:"export_targets"` + + // This read-only list of network IDs reflects the associations defined + // by Network association API resources. + Networks []string `json:"networks"` + + // This read-only list of router IDs reflects the associations defined + // by Router association API resources. + Routers []string `json:"routers"` + + // This read-only list of port IDs reflects the associations defined by + // Port association API resources (only present if the + // bgpvpn-routes-control API extension is enabled). + Ports []string `json:"ports"` + + // The default BGP LOCAL_PREF of routes that will be advertised to the + // BGPVPN (unless overridden per-route). + LocalPref *int `json:"local_pref"` + + // The globally-assigned VXLAN vni for the BGP VPN. + VNI int `json:"vni"` + + // The ID of the project. + TenantID string `json:"tenant_id"` + + // The ID of the project. + ProjectID string `json:"project_id"` +} + +// BGPVPNPage is the page returned by a pager when traversing over a +// collection of BGP VPNs. +type BGPVPNPage struct { + pagination.MarkerPageBase +} + +// NextPageURL generates the URL for the page of results after this one. +func (r BGPVPNPage) NextPageURL() (string, error) { + currentURL := r.URL + mark, err := r.Owner.LastMarker() + if err != nil { + return "", err + } + if mark == invalidMarker { + return "", nil + } + + q := currentURL.Query() + q.Set("marker", mark) + currentURL.RawQuery = q.Encode() + return currentURL.String(), nil +} + +// LastMarker returns the last offset in a ListResult. +func (r BGPVPNPage) LastMarker() (string, error) { + results, err := ExtractBGPVPNs(r) + if err != nil { + return invalidMarker, err + } + if len(results) == 0 { + return invalidMarker, nil + } + + u, err := url.Parse(r.URL.String()) + if err != nil { + return invalidMarker, err + } + queryParams := u.Query() + limit := queryParams.Get("limit") + + // Limit is not present, only one page required + if limit == "" { + return invalidMarker, nil + } + + return results[len(results)-1].ID, nil +} + +// IsEmpty checks whether a BGPPage struct is empty. +func (r BGPVPNPage) IsEmpty() (bool, error) { + if r.StatusCode == 204 { + return true, nil + } + + is, err := ExtractBGPVPNs(r) + return len(is) == 0, err +} + +// ExtractBGPVPNs accepts a Page struct, specifically a BGPVPNPage struct, +// and extracts the elements into a slice of BGPVPN structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractBGPVPNs(r pagination.Page) ([]BGPVPN, error) { + var s []BGPVPN + err := ExtractBGPVPNsInto(r, &s) + return s, err +} + +func ExtractBGPVPNsInto(r pagination.Page, v interface{}) error { + return r.(BGPVPNPage).Result.ExtractIntoSlicePtr(v, "bgpvpns") +} + +// GetResult represents the result of a get operation. Call its Extract +// method to interpret it as a BGPVPN. +type GetResult struct { + commonResult +} + +// CreateResult represents the result of a create operation. Call its Extract +// method to intepret it as a BGPVPN. +type CreateResult struct { + commonResult +} + +// DeleteResult represents the result of a delete operation. Call its +// ExtractErr method to determine if the request succeeded or failed. +type DeleteResult struct { + gophercloud.ErrResult +} + +// UpdateResult represents the result of an update operation. Call its Extract +// method to interpret it as a BGPVPN. +type UpdateResult struct { + commonResult +} + +type commonNetworkAssociationResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a BGP VPN resource. +func (r commonNetworkAssociationResult) Extract() (*NetworkAssociation, error) { + var s NetworkAssociation + err := r.ExtractInto(&s) + return &s, err +} + +func (r commonNetworkAssociationResult) ExtractInto(v interface{}) error { + return r.Result.ExtractIntoStructPtr(v, "network_association") +} + +// NetworkAssociation represents a BGP VPN network association object. +type NetworkAssociation struct { + ID string `json:"id"` + NetworkID string `json:"network_id"` + TenantID string `json:"tenant_id"` + ProjectID string `json:"project_id"` +} + +// NetworkAssociationPage is the page returned by a pager when traversing over a +// collection of network associations. +type NetworkAssociationPage struct { + pagination.MarkerPageBase +} + +// NextPageURL generates the URL for the page of results after this one. +func (r NetworkAssociationPage) NextPageURL() (string, error) { + currentURL := r.URL + mark, err := r.Owner.LastMarker() + if err != nil { + return "", err + } + if mark == invalidMarker { + return "", nil + } + + q := currentURL.Query() + q.Set("marker", mark) + currentURL.RawQuery = q.Encode() + return currentURL.String(), nil +} + +// LastMarker returns the last offset in a ListResult. +func (r NetworkAssociationPage) LastMarker() (string, error) { + results, err := ExtractNetworkAssociations(r) + if err != nil { + return invalidMarker, err + } + if len(results) == 0 { + return invalidMarker, nil + } + + u, err := url.Parse(r.URL.String()) + if err != nil { + return invalidMarker, err + } + queryParams := u.Query() + limit := queryParams.Get("limit") + + // Limit is not present, only one page required + if limit == "" { + return invalidMarker, nil + } + + return results[len(results)-1].ID, nil +} + +// IsEmpty checks whether a NetworkAssociationPage struct is empty. +func (r NetworkAssociationPage) IsEmpty() (bool, error) { + is, err := ExtractNetworkAssociations(r) + return len(is) == 0, err +} + +// ExtractNetworkAssociations accepts a Page struct, specifically a NetworkAssociationPage struct, +// and extracts the elements into a slice of NetworkAssociation structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractNetworkAssociations(r pagination.Page) ([]NetworkAssociation, error) { + var s []NetworkAssociation + err := ExtractNetworkAssociationsInto(r, &s) + return s, err +} + +func ExtractNetworkAssociationsInto(r pagination.Page, v interface{}) error { + return r.(NetworkAssociationPage).Result.ExtractIntoSlicePtr(v, "network_associations") +} + +// CreateNetworkAssociationResult represents the result of a create operation. Call its Extract +// method to interpret it as a NetworkAssociation. +type CreateNetworkAssociationResult struct { + commonNetworkAssociationResult +} + +// GetNetworkAssociationResult represents the result of a get operation. Call its Extract +// method to interpret it as a NetworkAssociation. +type GetNetworkAssociationResult struct { + commonNetworkAssociationResult +} + +// DeleteNetworkAssociationResult represents the result of a delete operation. Call its +// ExtractErr method to determine if the request succeeded or failed. +type DeleteNetworkAssociationResult struct { + gophercloud.ErrResult +} + +type commonRouterAssociationResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a BGP VPN resource. +func (r commonRouterAssociationResult) Extract() (*RouterAssociation, error) { + var s RouterAssociation + err := r.ExtractInto(&s) + return &s, err +} + +func (r commonRouterAssociationResult) ExtractInto(v interface{}) error { + return r.Result.ExtractIntoStructPtr(v, "router_association") +} + +// RouterAssociation represents a BGP VPN router association object. +type RouterAssociation struct { + ID string `json:"id"` + RouterID string `json:"router_id"` + TenantID string `json:"tenant_id"` + ProjectID string `json:"project_id"` + AdvertiseExtraRoutes bool `json:"advertise_extra_routes"` +} + +// RouterAssociationPage is the page returned by a pager when traversing over a +// collection of router associations. +type RouterAssociationPage struct { + pagination.MarkerPageBase +} + +// NextPageURL generates the URL for the page of results after this one. +func (r RouterAssociationPage) NextPageURL() (string, error) { + currentURL := r.URL + mark, err := r.Owner.LastMarker() + if err != nil { + return "", err + } + if mark == invalidMarker { + return "", nil + } + + q := currentURL.Query() + q.Set("marker", mark) + currentURL.RawQuery = q.Encode() + return currentURL.String(), nil +} + +// LastMarker returns the last offset in a ListResult. +func (r RouterAssociationPage) LastMarker() (string, error) { + results, err := ExtractRouterAssociations(r) + if err != nil { + return invalidMarker, err + } + if len(results) == 0 { + return invalidMarker, nil + } + + u, err := url.Parse(r.URL.String()) + if err != nil { + return invalidMarker, err + } + queryParams := u.Query() + limit := queryParams.Get("limit") + + // Limit is not present, only one page required + if limit == "" { + return invalidMarker, nil + } + + return results[len(results)-1].ID, nil +} + +// IsEmpty checks whether a RouterAssociationPage struct is empty. +func (r RouterAssociationPage) IsEmpty() (bool, error) { + is, err := ExtractRouterAssociations(r) + return len(is) == 0, err +} + +// ExtractRouterAssociations accepts a Page struct, specifically a RouterAssociationPage struct, +// and extracts the elements into a slice of RouterAssociation structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractRouterAssociations(r pagination.Page) ([]RouterAssociation, error) { + var s []RouterAssociation + err := ExtractRouterAssociationsInto(r, &s) + return s, err +} + +func ExtractRouterAssociationsInto(r pagination.Page, v interface{}) error { + return r.(RouterAssociationPage).Result.ExtractIntoSlicePtr(v, "router_associations") +} + +// CreateRouterAssociationResult represents the result of a create operation. Call its Extract +// method to interpret it as a RouterAssociation. +type CreateRouterAssociationResult struct { + commonRouterAssociationResult +} + +// GetRouterAssociationResult represents the result of a get operation. Call its Extract +// method to interpret it as a RouterAssociation. +type GetRouterAssociationResult struct { + commonRouterAssociationResult +} + +// DeleteRouterAssociationResult represents the result of a delete operation. Call its +// ExtractErr method to determine if the request succeeded or failed. +type DeleteRouterAssociationResult struct { + gophercloud.ErrResult +} + +// UpdateRouterAssociationResult represents the result of an update operation. Call its Extract +// method to interpret it as a RouterAssociation. +type UpdateRouterAssociationResult struct { + commonRouterAssociationResult +} + +type commonPortAssociationResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a BGP VPN resource. +func (r commonPortAssociationResult) Extract() (*PortAssociation, error) { + var s PortAssociation + err := r.ExtractInto(&s) + return &s, err +} + +func (r commonPortAssociationResult) ExtractInto(v interface{}) error { + return r.Result.ExtractIntoStructPtr(v, "port_association") +} + +// PortAssociation represents a BGP VPN port association object. +type PortAssociation struct { + ID string `json:"id"` + PortID string `json:"port_id"` + TenantID string `json:"tenant_id"` + ProjectID string `json:"project_id"` + Routes []PortRoutes `json:"routes"` + AdvertiseFixedIPs bool `json:"advertise_fixed_ips"` +} + +// PortAssociationPage is the page returned by a pager when traversing over a +// collection of port associations. +type PortAssociationPage struct { + pagination.MarkerPageBase +} + +// NextPageURL generates the URL for the page of results after this one. +func (r PortAssociationPage) NextPageURL() (string, error) { + currentURL := r.URL + mark, err := r.Owner.LastMarker() + if err != nil { + return "", err + } + if mark == invalidMarker { + return "", nil + } + + q := currentURL.Query() + q.Set("marker", mark) + currentURL.RawQuery = q.Encode() + return currentURL.String(), nil +} + +// LastMarker returns the last offset in a ListResult. +func (r PortAssociationPage) LastMarker() (string, error) { + results, err := ExtractPortAssociations(r) + if err != nil { + return invalidMarker, err + } + if len(results) == 0 { + return invalidMarker, nil + } + + u, err := url.Parse(r.URL.String()) + if err != nil { + return invalidMarker, err + } + queryParams := u.Query() + limit := queryParams.Get("limit") + + // Limit is not present, only one page required + if limit == "" { + return invalidMarker, nil + } + + return results[len(results)-1].ID, nil +} + +// IsEmpty checks whether a PortAssociationPage struct is empty. +func (r PortAssociationPage) IsEmpty() (bool, error) { + is, err := ExtractPortAssociations(r) + return len(is) == 0, err +} + +// ExtractPortAssociations accepts a Page struct, specifically a PortAssociationPage struct, +// and extracts the elements into a slice of PortAssociation structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractPortAssociations(r pagination.Page) ([]PortAssociation, error) { + var s []PortAssociation + err := ExtractPortAssociationsInto(r, &s) + return s, err +} + +func ExtractPortAssociationsInto(r pagination.Page, v interface{}) error { + return r.(PortAssociationPage).Result.ExtractIntoSlicePtr(v, "port_associations") +} + +// CreatePortAssociationResult represents the result of a create operation. Call its Extract +// method to interpret it as a PortAssociation. +type CreatePortAssociationResult struct { + commonPortAssociationResult +} + +// GetPortAssociationResult represents the result of a get operation. Call its Extract +// method to interpret it as a PortAssociation. +type GetPortAssociationResult struct { + commonPortAssociationResult +} + +// DeletePortAssociationResult represents the result of a delete operation. Call its +// ExtractErr method to determine if the request succeeded or failed. +type DeletePortAssociationResult struct { + gophercloud.ErrResult +} + +// UpdatePortAssociationResult represents the result of an update operation. Call its Extract +// method to interpret it as a PortAssociation. +type UpdatePortAssociationResult struct { + commonPortAssociationResult +} diff --git a/openstack/networking/v2/extensions/bgpvpns/testing/doc.go b/openstack/networking/v2/extensions/bgpvpns/testing/doc.go new file mode 100644 index 0000000000..7a770b9160 --- /dev/null +++ b/openstack/networking/v2/extensions/bgpvpns/testing/doc.go @@ -0,0 +1,2 @@ +// Package testing for bgpvpns +package testing diff --git a/openstack/networking/v2/extensions/bgpvpns/testing/fixture.go b/openstack/networking/v2/extensions/bgpvpns/testing/fixture.go new file mode 100644 index 0000000000..e331f6b249 --- /dev/null +++ b/openstack/networking/v2/extensions/bgpvpns/testing/fixture.go @@ -0,0 +1,434 @@ +package testing + +import "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/bgpvpns" + +const ListBGPVPNsResult = ` +{ + "bgpvpns": [ + { + "export_targets": [ + "64512:1666" + ], + "name": "", + "routers": [], + "route_distinguishers": [ + "64512:1777", + "64512:1888", + "64512:1999" + ], + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9", + "import_targets": [ + "64512:1555" + ], + "route_targets": [ + "64512:1444" + ], + "type": "l3", + "id": "0f9d472a-908f-40f5-8574-b4e8a63ccbf0", + "networks": [], + "local_pref": null, + "vni": 1000 + } + ] +} +` + +var BGPVPN = bgpvpns.BGPVPN{ + ID: "0f9d472a-908f-40f5-8574-b4e8a63ccbf0", + Name: "", + RouteDistinguishers: []string{"64512:1777", "64512:1888", "64512:1999"}, + RouteTargets: []string{"64512:1444"}, + ImportTargets: []string{"64512:1555"}, + ExportTargets: []string{"64512:1666"}, + LocalPref: nil, + VNI: 1000, + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", + Type: "l3", + Routers: []string{}, + Networks: []string{}, +} + +const GetBGPVPNResult = ` +{ + "bgpvpn": { + "id": "460ac411-3dfb-45bb-8116-ed1a7233d143", + "name": "foo", + "route_targets": ["64512:1444"], + "export_targets": [], + "import_targets": [], + "type": "l3", + "tenant_id": "f94ea398564d49dfb0d542f086c68ce7", + "project_id": "f94ea398564d49dfb0d542f086c68ce7", + "routers": [], + "route_distinguishers": [], + "networks": [ + "a4f2b8df-cb42-4893-a333-d0b5c36ade17" + ], + "local_pref": null, + "vni": 1000 + } +} +` + +var GetBGPVPN = bgpvpns.BGPVPN{ + ID: "460ac411-3dfb-45bb-8116-ed1a7233d143", + Name: "foo", + RouteDistinguishers: []string{}, + RouteTargets: []string{"64512:1444"}, + ImportTargets: []string{}, + ExportTargets: []string{}, + LocalPref: nil, + VNI: 1000, + TenantID: "f94ea398564d49dfb0d542f086c68ce7", + ProjectID: "f94ea398564d49dfb0d542f086c68ce7", + Type: "l3", + Routers: []string{}, + Networks: []string{"a4f2b8df-cb42-4893-a333-d0b5c36ade17"}, +} + +const CreateRequest = ` +{ + "bgpvpn": { + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "route_targets": ["64512:1444"], + "import_targets": ["64512:1555"], + "export_targets": ["64512:1666"], + "route_distinguishers": ["64512:1777", "64512:1888", "64512:1999"], + "type": "l3", + "vni": 1000 + } +} +` + +const CreateResponse = ` +{ + "bgpvpn": { + "export_targets": [ + "64512:1666" + ], + "name": "", + "routers": [], + "route_distinguishers": [ + "64512:1777", + "64512:1888", + "64512:1999" + ], + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9", + "import_targets": [ + "64512:1555" + ], + "route_targets": [ + "64512:1444" + ], + "type": "l3", + "id": "0f9d472a-908f-40f5-8574-b4e8a63ccbf0", + "networks": [], + "local_pref": null, + "vni": 1000 + } +} +` + +var CreateBGPVPN = bgpvpns.BGPVPN{ + ID: "0f9d472a-908f-40f5-8574-b4e8a63ccbf0", + RouteDistinguishers: []string{ + "64512:1777", + "64512:1888", + "64512:1999", + }, + RouteTargets: []string{"64512:1444"}, + ImportTargets: []string{"64512:1555"}, + ExportTargets: []string{"64512:1666"}, + LocalPref: nil, + VNI: 1000, + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", + Type: "l3", + Routers: []string{}, + Networks: []string{}, +} + +const UpdateBGPVPNRequest = ` +{ + "bgpvpn": { + "name": "foo", + "route_targets": ["64512:1444"], + "export_targets": [], + "import_targets": [] + } +} +` + +const UpdateBGPVPNResponse = ` +{ + "bgpvpn": { + "export_targets": [], + "name": "foo", + "routers": [], + "route_distinguishers": [ + "12345:1234" + ], + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "import_targets": [], + "route_targets": ["64512:1444"], + "type": "l3", + "id": "4d627abf-06dd-45ab-920b-8e61422bb984", + "networks": [], + "local_pref": null, + "vni": 1000 + } +} +` + +const ListNetworkAssociationsResult = ` +{ + "network_associations": [ + { + "id": "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + "network_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9" + } + ] +} +` + +var NetworkAssociation = bgpvpns.NetworkAssociation{ + ID: "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + NetworkID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", +} + +const GetNetworkAssociationResult = ` +{ + "network_association": { + "id": "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + "network_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9" + } +} +` + +var GetNetworkAssociation = bgpvpns.NetworkAssociation{ + ID: "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + NetworkID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", +} + +const CreateNetworkAssociationRequest = ` +{ + "network_association": { + "network_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd" + } +} +` +const CreateNetworkAssociationResponse = ` +{ + "network_association": { + "network_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9", + "id": "73238ca1-e05d-4c7a-b4d4-70407b4b8730" + } +} +` + +var CreateNetworkAssociation = bgpvpns.NetworkAssociation{ + ID: "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + NetworkID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", +} + +const ListRouterAssociationsResult = ` +{ + "router_associations": [ + { + "id": "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + "router_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9" + } + ] +} +` + +var RouterAssociation = bgpvpns.RouterAssociation{ + ID: "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + RouterID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", +} + +const GetRouterAssociationResult = ` +{ + "router_association": { + "id": "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + "router_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9" + } +} +` + +var GetRouterAssociation = bgpvpns.RouterAssociation{ + ID: "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + RouterID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", +} + +const CreateRouterAssociationRequest = ` +{ + "router_association": { + "router_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd" + } +} +` +const CreateRouterAssociationResponse = ` +{ + "router_association": { + "router_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9", + "id": "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + "advertise_extra_routes": true + } +} +` + +var CreateRouterAssociation = bgpvpns.RouterAssociation{ + ID: "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + RouterID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", + AdvertiseExtraRoutes: true, +} + +const UpdateRouterAssociationRequest = ` +{ + "router_association": { + "advertise_extra_routes": false + } +} +` +const UpdateRouterAssociationResponse = ` +{ + "router_association": { + "router_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9", + "id": "73238ca1-e05d-4c7a-b4d4-70407b4b8730" + } +} +` + +var UpdateRouterAssociation = bgpvpns.RouterAssociation{ + ID: "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + RouterID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", + AdvertiseExtraRoutes: false, +} + +const ListPortAssociationsResult = ` +{ + "port_associations": [ + { + "id": "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + "port_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9", + "advertise_fixed_ips": true + } + ] +} +` + +var PortAssociation = bgpvpns.PortAssociation{ + ID: "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + PortID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", + AdvertiseFixedIPs: true, +} + +const GetPortAssociationResult = ` +{ + "port_association": { + "id": "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + "port_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9", + "advertise_fixed_ips": true + } +} +` + +var GetPortAssociation = bgpvpns.PortAssociation{ + ID: "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + PortID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", + AdvertiseFixedIPs: true, +} + +const CreatePortAssociationRequest = ` +{ + "port_association": { + "port_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd" + } +} +` +const CreatePortAssociationResponse = ` +{ + "port_association": { + "port_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9", + "id": "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + "advertise_fixed_ips": true + } +} +` + +var CreatePortAssociation = bgpvpns.PortAssociation{ + ID: "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + PortID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", + AdvertiseFixedIPs: true, +} + +const UpdatePortAssociationRequest = ` +{ + "port_association": { + "advertise_fixed_ips": false + } +} +` +const UpdatePortAssociationResponse = ` +{ + "port_association": { + "port_id": "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + "tenant_id": "b7549121395844bea941bb92feb3fad9", + "project_id": "b7549121395844bea941bb92feb3fad9", + "id": "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + "advertise_fixed_ips": false + } +} +` + +var UpdatePortAssociation = bgpvpns.PortAssociation{ + ID: "73238ca1-e05d-4c7a-b4d4-70407b4b8730", + PortID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + TenantID: "b7549121395844bea941bb92feb3fad9", + ProjectID: "b7549121395844bea941bb92feb3fad9", + AdvertiseFixedIPs: false, +} diff --git a/openstack/networking/v2/extensions/bgpvpns/testing/requests_test.go b/openstack/networking/v2/extensions/bgpvpns/testing/requests_test.go new file mode 100644 index 0000000000..a338a7cd15 --- /dev/null +++ b/openstack/networking/v2/extensions/bgpvpns/testing/requests_test.go @@ -0,0 +1,513 @@ +package testing + +import ( + "fmt" + "net/http" + "testing" + + fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common" + "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/bgpvpns" + "github.com/gophercloud/gophercloud/pagination" + th "github.com/gophercloud/gophercloud/testhelper" +) + +func TestList(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + filterProjectID := []string{"b7549121395844bea941bb92feb3fad9"} + fields := []string{"id", "name"} + listOpts := bgpvpns.ListOpts{ + Fields: fields, + ProjectID: filterProjectID[0], + } + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns", + func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + r.ParseForm() + th.AssertDeepEquals(t, r.Form["fields"], fields) + th.AssertDeepEquals(t, r.Form["project_id"], filterProjectID) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ListBGPVPNsResult) + }) + count := 0 + + err := bgpvpns.List(fake.ServiceClient(), listOpts).EachPage( + func(page pagination.Page) (bool, error) { + count++ + actual, err := bgpvpns.ExtractBGPVPNs(page) + if err != nil { + t.Errorf("Failed to extract BGP VPNs: %v", err) + return false, nil + } + + expected := []bgpvpns.BGPVPN{BGPVPN} + th.CheckDeepEquals(t, expected, actual) + + return true, nil + }) + th.AssertNoErr(t, err) +} + +func TestGet(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, GetBGPVPNResult) + }) + + r, err := bgpvpns.Get(fake.ServiceClient(), bgpVpnID).Extract() + th.AssertNoErr(t, err) + th.CheckDeepEquals(t, GetBGPVPN, *r) +} + +func TestCreate(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, CreateRequest) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + fmt.Fprintf(w, CreateResponse) + }) + + opts := bgpvpns.CreateOpts{ + TenantID: "b7549121395844bea941bb92feb3fad9", + RouteTargets: []string{ + "64512:1444", + }, + ImportTargets: []string{ + "64512:1555", + }, + ExportTargets: []string{ + "64512:1666", + }, + RouteDistinguishers: []string{ + "64512:1777", + "64512:1888", + "64512:1999", + }, + Type: "l3", + VNI: 1000, + } + + r, err := bgpvpns.Create(fake.ServiceClient(), opts).Extract() + th.AssertNoErr(t, err) + th.AssertDeepEquals(t, CreateBGPVPN, *r) +} + +func TestDelete(t *testing.T) { + bgpVpnID := "0f9d472a-908f-40f5-8574-b4e8a63ccbf0" + th.SetupHTTP() + defer th.TeardownHTTP() + + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Accept", "application/json") + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusNoContent) + }) + + err := bgpvpns.Delete(fake.ServiceClient(), bgpVpnID).ExtractErr() + th.AssertNoErr(t, err) +} + +func TestUpdate(t *testing.T) { + bgpVpnID := "4d627abf-06dd-45ab-920b-8e61422bb984" + th.SetupHTTP() + defer th.TeardownHTTP() + + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, UpdateBGPVPNRequest) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + fmt.Fprintf(w, UpdateBGPVPNResponse) + }) + + name := "foo" + routeTargets := []string{"64512:1444"} + emptyTarget := []string{} + opts := bgpvpns.UpdateOpts{ + Name: &name, + RouteTargets: &routeTargets, + ImportTargets: &emptyTarget, + ExportTargets: &emptyTarget, + } + + r, err := bgpvpns.Update(fake.ServiceClient(), bgpVpnID, opts).Extract() + th.AssertNoErr(t, err) + th.AssertDeepEquals(t, *opts.Name, r.Name) +} + +func TestListNetworkAssociations(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + fields := []string{"id", "name"} + listOpts := bgpvpns.ListNetworkAssociationsOpts{ + Fields: fields, + } + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/network_associations", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + r.ParseForm() + th.AssertDeepEquals(t, fields, r.Form["fields"]) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ListNetworkAssociationsResult) + }) + + count := 0 + err := bgpvpns.ListNetworkAssociations(fake.ServiceClient(), bgpVpnID, listOpts).EachPage( + func(page pagination.Page) (bool, error) { + count++ + actual, err := bgpvpns.ExtractNetworkAssociations(page) + if err != nil { + t.Errorf("Failed to extract network associations: %v", err) + return false, nil + } + + expected := []bgpvpns.NetworkAssociation{NetworkAssociation} + th.CheckDeepEquals(t, expected, actual) + + return true, nil + }) + + th.AssertNoErr(t, err) + th.AssertEquals(t, 1, count) +} + +func TestCreateNetworkAssociation(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/network_associations", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, CreateNetworkAssociationRequest) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + fmt.Fprintf(w, CreateNetworkAssociationResponse) + }) + + opts := bgpvpns.CreateNetworkAssociationOpts{ + NetworkID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + } + r, err := bgpvpns.CreateNetworkAssociation(fake.ServiceClient(), bgpVpnID, opts).Extract() + th.AssertNoErr(t, err) + th.AssertDeepEquals(t, CreateNetworkAssociation, *r) +} + +func TestGetNetworkAssociation(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + networkAssociationID := "73238ca1-e05d-4c7a-b4d4-70407b4b8730" + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/network_associations/"+networkAssociationID, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, GetNetworkAssociationResult) + }) + + r, err := bgpvpns.GetNetworkAssociation(fake.ServiceClient(), bgpVpnID, networkAssociationID).Extract() + th.AssertNoErr(t, err) + th.CheckDeepEquals(t, GetNetworkAssociation, *r) +} + +func TestDeleteNetworkAssociation(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + networkAssociationID := "73238ca1-e05d-4c7a-b4d4-70407b4b8730" + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/network_associations/"+networkAssociationID, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusNoContent) + }) + + err := bgpvpns.DeleteNetworkAssociation(fake.ServiceClient(), bgpVpnID, networkAssociationID).ExtractErr() + th.AssertNoErr(t, err) +} + +func TestListRouterAssociations(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + fields := []string{"id", "name"} + listOpts := bgpvpns.ListRouterAssociationsOpts{ + Fields: fields, + } + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/router_associations", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + r.ParseForm() + th.AssertDeepEquals(t, fields, r.Form["fields"]) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ListRouterAssociationsResult) + }) + + count := 0 + err := bgpvpns.ListRouterAssociations(fake.ServiceClient(), bgpVpnID, listOpts).EachPage( + func(page pagination.Page) (bool, error) { + count++ + actual, err := bgpvpns.ExtractRouterAssociations(page) + if err != nil { + t.Errorf("Failed to extract router associations: %v", err) + return false, nil + } + + expected := []bgpvpns.RouterAssociation{RouterAssociation} + th.CheckDeepEquals(t, expected, actual) + + return true, nil + }) + + th.AssertNoErr(t, err) + th.AssertEquals(t, 1, count) +} + +func TestCreateRouterAssociation(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/router_associations", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, CreateRouterAssociationRequest) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + fmt.Fprintf(w, CreateRouterAssociationResponse) + }) + + opts := bgpvpns.CreateRouterAssociationOpts{ + RouterID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + } + r, err := bgpvpns.CreateRouterAssociation(fake.ServiceClient(), bgpVpnID, opts).Extract() + th.AssertNoErr(t, err) + th.AssertDeepEquals(t, CreateRouterAssociation, *r) +} + +func TestGetRouterAssociation(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + routerAssociationID := "73238ca1-e05d-4c7a-b4d4-70407b4b8730" + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/router_associations/"+routerAssociationID, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, GetRouterAssociationResult) + }) + + r, err := bgpvpns.GetRouterAssociation(fake.ServiceClient(), bgpVpnID, routerAssociationID).Extract() + th.AssertNoErr(t, err) + th.CheckDeepEquals(t, GetRouterAssociation, *r) +} + +func TestUpdateRouterAssociation(t *testing.T) { + bgpVpnID := "4d627abf-06dd-45ab-920b-8e61422bb984" + routerAssociationID := "73238ca1-e05d-4c7a-b4d4-70407b4b8730" + th.SetupHTTP() + defer th.TeardownHTTP() + + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/router_associations/"+routerAssociationID, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, UpdateRouterAssociationRequest) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, UpdateRouterAssociationResponse) + }) + + opts := bgpvpns.UpdateRouterAssociationOpts{ + AdvertiseExtraRoutes: new(bool), + } + r, err := bgpvpns.UpdateRouterAssociation(fake.ServiceClient(), bgpVpnID, routerAssociationID, opts).Extract() + th.AssertNoErr(t, err) + th.AssertDeepEquals(t, UpdateRouterAssociation, *r) +} + +func TestDeleteRouterAssociation(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + routerAssociationID := "73238ca1-e05d-4c7a-b4d4-70407b4b8730" + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/router_associations/"+routerAssociationID, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusNoContent) + }) + + err := bgpvpns.DeleteRouterAssociation(fake.ServiceClient(), bgpVpnID, routerAssociationID).ExtractErr() + th.AssertNoErr(t, err) +} + +func TestListPortAssociations(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + fields := []string{"id", "name"} + listOpts := bgpvpns.ListPortAssociationsOpts{ + Fields: fields, + } + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/port_associations", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + + r.ParseForm() + th.AssertDeepEquals(t, fields, r.Form["fields"]) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, ListPortAssociationsResult) + }) + + count := 0 + err := bgpvpns.ListPortAssociations(fake.ServiceClient(), bgpVpnID, listOpts).EachPage( + func(page pagination.Page) (bool, error) { + count++ + actual, err := bgpvpns.ExtractPortAssociations(page) + if err != nil { + t.Errorf("Failed to extract port associations: %v", err) + return false, nil + } + + expected := []bgpvpns.PortAssociation{PortAssociation} + th.CheckDeepEquals(t, expected, actual) + + return true, nil + }) + + th.AssertNoErr(t, err) + th.AssertEquals(t, 1, count) +} + +func TestCreatePortAssociation(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/port_associations", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, CreatePortAssociationRequest) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + fmt.Fprintf(w, CreatePortAssociationResponse) + }) + + opts := bgpvpns.CreatePortAssociationOpts{ + PortID: "8c5d88dc-60ac-4b02-a65a-36b65888ddcd", + } + r, err := bgpvpns.CreatePortAssociation(fake.ServiceClient(), bgpVpnID, opts).Extract() + th.AssertNoErr(t, err) + th.AssertDeepEquals(t, CreatePortAssociation, *r) +} + +func TestGetPortAssociation(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + portAssociationID := "73238ca1-e05d-4c7a-b4d4-70407b4b8730" + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/port_associations/"+portAssociationID, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, GetPortAssociationResult) + }) + + r, err := bgpvpns.GetPortAssociation(fake.ServiceClient(), bgpVpnID, portAssociationID).Extract() + th.AssertNoErr(t, err) + th.CheckDeepEquals(t, GetPortAssociation, *r) +} + +func TestUpdatePortAssociation(t *testing.T) { + bgpVpnID := "4d627abf-06dd-45ab-920b-8e61422bb984" + portAssociationID := "73238ca1-e05d-4c7a-b4d4-70407b4b8730" + th.SetupHTTP() + defer th.TeardownHTTP() + + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/port_associations/"+portAssociationID, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, UpdatePortAssociationRequest) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, UpdatePortAssociationResponse) + }) + + opts := bgpvpns.UpdatePortAssociationOpts{ + AdvertiseFixedIPs: new(bool), + } + r, err := bgpvpns.UpdatePortAssociation(fake.ServiceClient(), bgpVpnID, portAssociationID, opts).Extract() + th.AssertNoErr(t, err) + th.AssertDeepEquals(t, UpdatePortAssociation, *r) +} + +func TestDeletePortAssociation(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + bgpVpnID := "460ac411-3dfb-45bb-8116-ed1a7233d143" + portAssociationID := "73238ca1-e05d-4c7a-b4d4-70407b4b8730" + th.Mux.HandleFunc("/v2.0/bgpvpn/bgpvpns/"+bgpVpnID+"/port_associations/"+portAssociationID, func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + w.WriteHeader(http.StatusNoContent) + }) + + err := bgpvpns.DeletePortAssociation(fake.ServiceClient(), bgpVpnID, portAssociationID).ExtractErr() + th.AssertNoErr(t, err) +} diff --git a/openstack/networking/v2/extensions/bgpvpns/urls.go b/openstack/networking/v2/extensions/bgpvpns/urls.go new file mode 100644 index 0000000000..b2377581fa --- /dev/null +++ b/openstack/networking/v2/extensions/bgpvpns/urls.go @@ -0,0 +1,140 @@ +package bgpvpns + +import "github.com/gophercloud/gophercloud" + +const urlBase = "bgpvpn/bgpvpns" + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id} +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(urlBase, id) +} + +// return /v2.0/bgpvpn/bgpvpns +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(urlBase) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id} +func getURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} + +// return /v2.0/bgpvpn/bgpvpns +func listURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +} + +// return /v2.0/bgpvpn/bgpvpns +func createURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id} +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id} +func updateURL(c *gophercloud.ServiceClient, id string) string { + return resourceURL(c, id) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/network_associations +func networkAssociationsURL(c *gophercloud.ServiceClient, bgpVpnID string) string { + return c.ServiceURL(urlBase, bgpVpnID, "network_associations") +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/network_associations/{network-association-id} +func networkAssociationResourceURL(c *gophercloud.ServiceClient, bgpVpnID string, id string) string { + return c.ServiceURL(urlBase, bgpVpnID, "network_associations", id) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/network_associations +func listNetworkAssociationsURL(c *gophercloud.ServiceClient, bgpVpnID string) string { + return networkAssociationsURL(c, bgpVpnID) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/network_associations +func createNetworkAssociationURL(c *gophercloud.ServiceClient, bgpVpnID string) string { + return networkAssociationsURL(c, bgpVpnID) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/network_associations/{network-association-id} +func getNetworkAssociationURL(c *gophercloud.ServiceClient, bgpVpnID string, id string) string { + return networkAssociationResourceURL(c, bgpVpnID, id) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/network_associations/{network-association-id} +func deleteNetworkAssociationURL(c *gophercloud.ServiceClient, bgpVpnID string, id string) string { + return networkAssociationResourceURL(c, bgpVpnID, id) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/router_associations +func routerAssociationsURL(c *gophercloud.ServiceClient, bgpVpnID string) string { + return c.ServiceURL(urlBase, bgpVpnID, "router_associations") +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/router_associations/{router-association-id} +func routerAssociationResourceURL(c *gophercloud.ServiceClient, bgpVpnID string, id string) string { + return c.ServiceURL(urlBase, bgpVpnID, "router_associations", id) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/router_associations +func listRouterAssociationsURL(c *gophercloud.ServiceClient, bgpVpnID string) string { + return routerAssociationsURL(c, bgpVpnID) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/router_associations +func createRouterAssociationURL(c *gophercloud.ServiceClient, bgpVpnID string) string { + return routerAssociationsURL(c, bgpVpnID) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/router_associations/{router-association-id} +func getRouterAssociationURL(c *gophercloud.ServiceClient, bgpVpnID string, id string) string { + return routerAssociationResourceURL(c, bgpVpnID, id) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/router_associations/{router-association-id} +func updateRouterAssociationURL(c *gophercloud.ServiceClient, bgpVpnID string, id string) string { + return routerAssociationResourceURL(c, bgpVpnID, id) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/router_associations/{router-association-id} +func deleteRouterAssociationURL(c *gophercloud.ServiceClient, bgpVpnID string, id string) string { + return routerAssociationResourceURL(c, bgpVpnID, id) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/port_associations +func portAssociationsURL(c *gophercloud.ServiceClient, bgpVpnID string) string { + return c.ServiceURL(urlBase, bgpVpnID, "port_associations") +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/port_associations/{port-association-id} +func portAssociationResourceURL(c *gophercloud.ServiceClient, bgpVpnID string, id string) string { + return c.ServiceURL(urlBase, bgpVpnID, "port_associations", id) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/port_associations +func listPortAssociationsURL(c *gophercloud.ServiceClient, bgpVpnID string) string { + return portAssociationsURL(c, bgpVpnID) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/port_associations +func createPortAssociationURL(c *gophercloud.ServiceClient, bgpVpnID string) string { + return portAssociationsURL(c, bgpVpnID) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/port_associations/{port-association-id} +func getPortAssociationURL(c *gophercloud.ServiceClient, bgpVpnID string, id string) string { + return portAssociationResourceURL(c, bgpVpnID, id) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/port_associations/{port-association-id} +func updatePortAssociationURL(c *gophercloud.ServiceClient, bgpVpnID string, id string) string { + return portAssociationResourceURL(c, bgpVpnID, id) +} + +// return /v2.0/bgpvpn/bgpvpns/{bgpvpn-id}/port_associations/{port-association-id} +func deletePortAssociationURL(c *gophercloud.ServiceClient, bgpVpnID string, id string) string { + return portAssociationResourceURL(c, bgpVpnID, id) +} From 62aae9033fdd565de8a7b1fba2e6db88d88c23bb Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Mon, 8 Jul 2024 15:39:58 +0200 Subject: [PATCH 103/118] Prepare v1.13.0 --- CHANGELOG.md | 6 ++++++ provider_client.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a69454903f..8f579884c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v1.13.0 (2024-07-08) + +* [GH-3044](https://github.com/gophercloud/gophercloud/pull/3044) [v1] Add ci jobs for openstack caracal +* [GH-3073](https://github.com/gophercloud/gophercloud/pull/3073) [v1] Adding missing QoS field for router +* [GH-3080](https://github.com/gophercloud/gophercloud/pull/3080) [networking]: add BGP VPNs support (backport to 1.x) + ## v1.12.0 (2024-05-27) * [GH-2979](https://github.com/gophercloud/gophercloud/pull/2979) [v1] CI backports diff --git a/provider_client.go b/provider_client.go index 27cbc2ff71..5b9381b9b1 100644 --- a/provider_client.go +++ b/provider_client.go @@ -14,7 +14,7 @@ import ( // DefaultUserAgent is the default User-Agent string set in the request header. const ( - DefaultUserAgent = "gophercloud/v1.12.0" + DefaultUserAgent = "gophercloud/v1.13.0" DefaultMaxBackoffRetries = 60 ) From ef613a02c96adb29c57ad5cedc060c7d57059ccc Mon Sep 17 00:00:00 2001 From: kayrus Date: Tue, 9 Jul 2024 21:18:32 +0200 Subject: [PATCH 104/118] [neutron]: introduce Description argument for the portforwarding --- .../networking/v2/extensions/layer3/layer3.go | 2 ++ .../extensions/layer3/portforwardings_test.go | 3 +++ .../layer3/portforwarding/requests.go | 20 +++++++++---------- .../layer3/portforwarding/results.go | 4 ++++ 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/internal/acceptance/openstack/networking/v2/extensions/layer3/layer3.go b/internal/acceptance/openstack/networking/v2/extensions/layer3/layer3.go index 8e4f5e8590..b00b86b2a6 100644 --- a/internal/acceptance/openstack/networking/v2/extensions/layer3/layer3.go +++ b/internal/acceptance/openstack/networking/v2/extensions/layer3/layer3.go @@ -73,7 +73,9 @@ func CreatePortForwarding(t *testing.T, client *gophercloud.ServiceClient, fipID fixedIP := portFixedIPs[0] internalIP := fixedIP.IPAddress + pfDescription := "Test description" createOpts := &portforwarding.CreateOpts{ + Description: pfDescription, Protocol: "tcp", InternalPort: 25, ExternalPort: 2230, diff --git a/internal/acceptance/openstack/networking/v2/extensions/layer3/portforwardings_test.go b/internal/acceptance/openstack/networking/v2/extensions/layer3/portforwardings_test.go index f5ae90b252..e495ef37ce 100644 --- a/internal/acceptance/openstack/networking/v2/extensions/layer3/portforwardings_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/layer3/portforwardings_test.go @@ -53,6 +53,7 @@ func TestLayer3PortForwardingsCreateDelete(t *testing.T) { pf, err := CreatePortForwarding(t, client, fip.ID, port.ID, port.FixedIPs) th.AssertNoErr(t, err) + th.AssertEquals(t, pf.Description, "Test description") defer DeletePortForwarding(t, client, fip.ID, pf.ID) tools.PrintResource(t, pf) @@ -60,6 +61,7 @@ func TestLayer3PortForwardingsCreateDelete(t *testing.T) { th.AssertNoErr(t, err) updateOpts := portforwarding.UpdateOpts{ + Description: new(string), Protocol: "udp", InternalPort: 30, ExternalPort: 678, @@ -70,6 +72,7 @@ func TestLayer3PortForwardingsCreateDelete(t *testing.T) { newPf, err = portforwarding.Get(client, fip.ID, pf.ID).Extract() th.AssertNoErr(t, err) + th.AssertEquals(t, newPf.Description, "") allPages, err := portforwarding.List(client, portforwarding.ListOpts{}, fip.ID).AllPages() th.AssertNoErr(t, err) diff --git a/openstack/networking/v2/extensions/layer3/portforwarding/requests.go b/openstack/networking/v2/extensions/layer3/portforwarding/requests.go index 9081bc3549..0ff314aa90 100644 --- a/openstack/networking/v2/extensions/layer3/portforwarding/requests.go +++ b/openstack/networking/v2/extensions/layer3/portforwarding/requests.go @@ -16,6 +16,7 @@ type ListOptsBuilder interface { // either `asc' or `desc'. Marker and Limit are used for pagination. type ListOpts struct { ID string `q:"id"` + Description string `q:"description"` InternalPortID string `q:"internal_port_id"` ExternalPort string `q:"external_port"` InternalIPAddress string `q:"internal_ip_address"` @@ -61,6 +62,7 @@ func Get(c *gophercloud.ServiceClient, floatingIpId string, pfId string) (r GetR // CreateOpts contains all the values needed to create a new port forwarding // resource. All attributes are required. type CreateOpts struct { + Description string `json:"description,omitempty"` InternalPortID string `json:"internal_port_id"` InternalIPAddress string `json:"internal_ip_address"` InternalPort int `json:"internal_port"` @@ -95,22 +97,18 @@ func Create(c *gophercloud.ServiceClient, floatingIpId string, opts CreateOptsBu // UpdateOpts contains the values used when updating a port forwarding resource. type UpdateOpts struct { - InternalPortID string `json:"internal_port_id,omitempty"` - InternalIPAddress string `json:"internal_ip_address,omitempty"` - InternalPort int `json:"internal_port,omitempty"` - ExternalPort int `json:"external_port,omitempty"` - Protocol string `json:"protocol,omitempty"` + Description *string `json:"description,omitempty"` + InternalPortID string `json:"internal_port_id,omitempty"` + InternalIPAddress string `json:"internal_ip_address,omitempty"` + InternalPort int `json:"internal_port,omitempty"` + ExternalPort int `json:"external_port,omitempty"` + Protocol string `json:"protocol,omitempty"` } // ToPortForwardingUpdateMap allows UpdateOpts to satisfy the UpdateOptsBuilder // interface func (opts UpdateOpts) ToPortForwardingUpdateMap() (map[string]interface{}, error) { - b, err := gophercloud.BuildRequestBody(opts, "port_forwarding") - if err != nil { - return nil, err - } - - return b, nil + return gophercloud.BuildRequestBody(opts, "port_forwarding") } // UpdateOptsBuilder allows extensions to add additional parameters to the diff --git a/openstack/networking/v2/extensions/layer3/portforwarding/results.go b/openstack/networking/v2/extensions/layer3/portforwarding/results.go index 70bd097336..db19e1b329 100644 --- a/openstack/networking/v2/extensions/layer3/portforwarding/results.go +++ b/openstack/networking/v2/extensions/layer3/portforwarding/results.go @@ -9,6 +9,10 @@ type PortForwarding struct { // The ID of the floating IP port forwarding ID string `json:"id"` + // A text describing the rule, which helps users to manage/find easily + // theirs rules. + Description string `json:"description"` + // The ID of the Neutron port associated to the floating IP port forwarding. InternalPortID string `json:"internal_port_id"` From 7d47899eb9ceefcdf1f428626eb7458d4d60d8a4 Mon Sep 17 00:00:00 2001 From: kayrus Date: Tue, 9 Jul 2024 21:05:40 +0200 Subject: [PATCH 105/118] [neutron]: introduce Stateful argument for the security groups --- .../openstack/networking/v2/extensions/security_test.go | 3 +++ .../networking/v2/extensions/security/groups/requests.go | 7 +++++++ .../networking/v2/extensions/security/groups/results.go | 3 +++ 3 files changed, 13 insertions(+) diff --git a/internal/acceptance/openstack/networking/v2/extensions/security_test.go b/internal/acceptance/openstack/networking/v2/extensions/security_test.go index aaf772e7d5..dcbc68a255 100644 --- a/internal/acceptance/openstack/networking/v2/extensions/security_test.go +++ b/internal/acceptance/openstack/networking/v2/extensions/security_test.go @@ -20,6 +20,7 @@ func TestSecurityGroupsCreateUpdateDelete(t *testing.T) { group, err := CreateSecurityGroup(t, client) th.AssertNoErr(t, err) defer DeleteSecurityGroup(t, client, group.ID) + th.AssertEquals(t, group.Stateful, true) rule, err := CreateSecurityGroupRule(t, client, group.ID) th.AssertNoErr(t, err) @@ -32,6 +33,7 @@ func TestSecurityGroupsCreateUpdateDelete(t *testing.T) { updateOpts := groups.UpdateOpts{ Name: name, Description: &description, + Stateful: new(bool), } newGroup, err := groups.Update(client, group.ID, updateOpts).Extract() @@ -40,6 +42,7 @@ func TestSecurityGroupsCreateUpdateDelete(t *testing.T) { tools.PrintResource(t, newGroup) th.AssertEquals(t, newGroup.Name, name) th.AssertEquals(t, newGroup.Description, description) + th.AssertEquals(t, newGroup.Stateful, false) listOpts := groups.ListOpts{} allPages, err := groups.List(client, listOpts).AllPages() diff --git a/openstack/networking/v2/extensions/security/groups/requests.go b/openstack/networking/v2/extensions/security/groups/requests.go index 566a730eaf..645f87cfa9 100644 --- a/openstack/networking/v2/extensions/security/groups/requests.go +++ b/openstack/networking/v2/extensions/security/groups/requests.go @@ -14,6 +14,7 @@ type ListOpts struct { ID string `q:"id"` Name string `q:"name"` Description string `q:"description"` + Stateful *bool `q:"stateful"` TenantID string `q:"tenant_id"` ProjectID string `q:"project_id"` Limit int `q:"limit"` @@ -61,6 +62,9 @@ type CreateOpts struct { // Describes the security group. Description string `json:"description,omitempty"` + + // Stateful indicates if the security group is stateful or stateless. + Stateful *bool `json:"stateful,omitempty"` } // ToSecGroupCreateMap builds a request body from CreateOpts. @@ -95,6 +99,9 @@ type UpdateOpts struct { // Describes the security group. Description *string `json:"description,omitempty"` + + // Stateful indicates if the security group is stateful or stateless. + Stateful *bool `json:"stateful,omitempty"` } // ToSecGroupUpdateMap builds a request body from UpdateOpts. diff --git a/openstack/networking/v2/extensions/security/groups/results.go b/openstack/networking/v2/extensions/security/groups/results.go index 2027037de2..f892bcb5c2 100644 --- a/openstack/networking/v2/extensions/security/groups/results.go +++ b/openstack/networking/v2/extensions/security/groups/results.go @@ -25,6 +25,9 @@ type SecGroup struct { // traffic entering and leaving the group. Rules []rules.SecGroupRule `json:"security_group_rules"` + // Indicates if the security group is stateful or stateless. + Stateful bool `json:"stateful"` + // TenantID is the project owner of the security group. TenantID string `json:"tenant_id"` From d5e435bc77d7bcb66fae20bdae097502d3894126 Mon Sep 17 00:00:00 2001 From: Pablo COLSON Date: Mon, 8 Jul 2024 20:21:49 +0200 Subject: [PATCH 106/118] [networking]: subnet add field dns_publish_fixed_ip --- openstack/networking/v2/subnets/requests.go | 49 +- openstack/networking/v2/subnets/results.go | 3 + .../v2/subnets/testing/fixtures_test.go | 795 +++++++++--------- .../v2/subnets/testing/requests_test.go | 9 +- 4 files changed, 442 insertions(+), 414 deletions(-) diff --git a/openstack/networking/v2/subnets/requests.go b/openstack/networking/v2/subnets/requests.go index 2e87907587..50b2bfea1b 100644 --- a/openstack/networking/v2/subnets/requests.go +++ b/openstack/networking/v2/subnets/requests.go @@ -19,27 +19,28 @@ type ListOptsBuilder interface { // by a particular subnet attribute. SortDir sets the direction, and is either // `asc' or `desc'. Marker and Limit are used for pagination. type ListOpts struct { - Name string `q:"name"` - Description string `q:"description"` - EnableDHCP *bool `q:"enable_dhcp"` - NetworkID string `q:"network_id"` - TenantID string `q:"tenant_id"` - ProjectID string `q:"project_id"` - IPVersion int `q:"ip_version"` - GatewayIP string `q:"gateway_ip"` - CIDR string `q:"cidr"` - IPv6AddressMode string `q:"ipv6_address_mode"` - IPv6RAMode string `q:"ipv6_ra_mode"` - ID string `q:"id"` - SubnetPoolID string `q:"subnetpool_id"` - Limit int `q:"limit"` - Marker string `q:"marker"` - SortKey string `q:"sort_key"` - SortDir string `q:"sort_dir"` - Tags string `q:"tags"` - TagsAny string `q:"tags-any"` - NotTags string `q:"not-tags"` - NotTagsAny string `q:"not-tags-any"` + Name string `q:"name"` + Description string `q:"description"` + DNSPublishFixedIP *bool `q:"dns_publish_fixed_ip"` + EnableDHCP *bool `q:"enable_dhcp"` + NetworkID string `q:"network_id"` + TenantID string `q:"tenant_id"` + ProjectID string `q:"project_id"` + IPVersion int `q:"ip_version"` + GatewayIP string `q:"gateway_ip"` + CIDR string `q:"cidr"` + IPv6AddressMode string `q:"ipv6_address_mode"` + IPv6RAMode string `q:"ipv6_ra_mode"` + ID string `q:"id"` + SubnetPoolID string `q:"subnetpool_id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` + Tags string `q:"tags"` + TagsAny string `q:"tags-any"` + NotTags string `q:"not-tags"` + NotTagsAny string `q:"not-tags-any"` } // ToSubnetListQuery formats a ListOpts into a query string. @@ -122,6 +123,9 @@ type CreateOpts struct { // DNSNameservers are the nameservers to be set via DHCP. DNSNameservers []string `json:"dns_nameservers,omitempty"` + // DNSPublishFixedIP will either enable or disable the publication of fixed IPs to the DNS + DNSPublishFixedIP *bool `json:"dns_publish_fixed_ip,omitempty"` + // ServiceTypes are the service types associated with the subnet. ServiceTypes []string `json:"service_types,omitempty"` @@ -197,6 +201,9 @@ type UpdateOpts struct { // DNSNameservers are the nameservers to be set via DHCP. DNSNameservers *[]string `json:"dns_nameservers,omitempty"` + // DNSPublishFixedIP will either enable or disable the publication of fixed IPs to the DNS + DNSPublishFixedIP *bool `json:"dns_publish_fixed_ip,omitempty"` + // ServiceTypes are the service types associated with the subnet. ServiceTypes *[]string `json:"service_types,omitempty"` diff --git a/openstack/networking/v2/subnets/results.go b/openstack/networking/v2/subnets/results.go index cd09b6f6e6..422eb428bf 100644 --- a/openstack/networking/v2/subnets/results.go +++ b/openstack/networking/v2/subnets/results.go @@ -83,6 +83,9 @@ type Subnet struct { // DNS name servers used by hosts in this subnet. DNSNameservers []string `json:"dns_nameservers"` + // Specifies whether the fixed IP addresses are published to the DNS. + DNSPublishFixedIP bool `json:"dns_publish_fixed_ip"` + // Service types associated with the subnet. ServiceTypes []string `json:"service_types"` diff --git a/openstack/networking/v2/subnets/testing/fixtures_test.go b/openstack/networking/v2/subnets/testing/fixtures_test.go index af8512e549..f9811fd549 100644 --- a/openstack/networking/v2/subnets/testing/fixtures_test.go +++ b/openstack/networking/v2/subnets/testing/fixtures_test.go @@ -6,90 +6,94 @@ import ( const SubnetListResult = ` { - "subnets": [ - { - "name": "private-subnet", - "enable_dhcp": true, - "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", - "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", - "dns_nameservers": [], - "allocation_pools": [ - { - "start": "10.0.0.2", - "end": "10.0.0.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": "10.0.0.1", - "cidr": "10.0.0.0/24", - "id": "08eae331-0402-425a-923c-34f7cfe39c1b" - }, - { - "name": "my_subnet", - "enable_dhcp": true, - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", - "tenant_id": "4fd44f30292945e481c7b8a0c8908869", - "dns_nameservers": [], - "allocation_pools": [ - { - "start": "192.0.0.2", - "end": "192.255.255.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": "192.0.0.1", - "cidr": "192.0.0.0/8", - "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0b" - }, - { - "name": "my_gatewayless_subnet", - "enable_dhcp": true, - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", - "tenant_id": "4fd44f30292945e481c7b8a0c8908869", - "dns_nameservers": [], - "allocation_pools": [ - { - "start": "192.168.1.2", - "end": "192.168.1.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": null, - "cidr": "192.168.1.0/24", - "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0c" - }, - { - "name": "my_subnet_with_subnetpool", - "enable_dhcp": false, - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", - "tenant_id": "4fd44f30292945e481c7b8a0c8908869", - "dns_nameservers": [], - "allocation_pools": [ - { - "start": "10.11.12.2", - "end": "10.11.12.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": null, - "cidr": "10.11.12.0/24", - "id": "38186a51-f373-4bbc-838b-6eaa1aa13eac", - "subnetpool_id": "b80340c7-9960-4f67-a99c-02501656284b" - } - ] + "subnets": [ + { + "name": "private-subnet", + "enable_dhcp": true, + "dns_publish_fixed_ip": true, + "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", + "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", + "dns_nameservers": [], + "allocation_pools": [ + { + "start": "10.0.0.2", + "end": "10.0.0.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": "10.0.0.1", + "cidr": "10.0.0.0/24", + "id": "08eae331-0402-425a-923c-34f7cfe39c1b" + }, + { + "name": "my_subnet", + "enable_dhcp": true, + "dns_publish_fixed_ip": true, + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", + "tenant_id": "4fd44f30292945e481c7b8a0c8908869", + "dns_nameservers": [], + "allocation_pools": [ + { + "start": "192.0.0.2", + "end": "192.255.255.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": "192.0.0.1", + "cidr": "192.0.0.0/8", + "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0b" + }, + { + "name": "my_gatewayless_subnet", + "enable_dhcp": true, + "dns_publish_fixed_ip": true, + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", + "tenant_id": "4fd44f30292945e481c7b8a0c8908869", + "dns_nameservers": [], + "allocation_pools": [ + { + "start": "192.168.1.2", + "end": "192.168.1.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": null, + "cidr": "192.168.1.0/24", + "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0c" + }, + { + "name": "my_subnet_with_subnetpool", + "enable_dhcp": false, + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", + "tenant_id": "4fd44f30292945e481c7b8a0c8908869", + "dns_nameservers": [], + "allocation_pools": [ + { + "start": "10.11.12.2", + "end": "10.11.12.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": null, + "cidr": "10.11.12.0/24", + "id": "38186a51-f373-4bbc-838b-6eaa1aa13eac", + "subnetpool_id": "b80340c7-9960-4f67-a99c-02501656284b" + } + ] } ` var Subnet1 = subnets.Subnet{ - Name: "private-subnet", - EnableDHCP: true, - NetworkID: "db193ab3-96e3-4cb3-8fc5-05f4296d0324", - TenantID: "26a7980765d0414dbc1fc1f88cdb7e6e", - DNSNameservers: []string{}, + Name: "private-subnet", + EnableDHCP: true, + NetworkID: "db193ab3-96e3-4cb3-8fc5-05f4296d0324", + TenantID: "26a7980765d0414dbc1fc1f88cdb7e6e", + DNSNameservers: []string{}, + DNSPublishFixedIP: true, AllocationPools: []subnets.AllocationPool{ { Start: "10.0.0.2", @@ -104,11 +108,13 @@ var Subnet1 = subnets.Subnet{ } var Subnet2 = subnets.Subnet{ - Name: "my_subnet", - EnableDHCP: true, - NetworkID: "d32019d3-bc6e-4319-9c1d-6722fc136a22", - TenantID: "4fd44f30292945e481c7b8a0c8908869", - DNSNameservers: []string{}, + Name: "my_subnet", + EnableDHCP: true, + + NetworkID: "d32019d3-bc6e-4319-9c1d-6722fc136a22", + TenantID: "4fd44f30292945e481c7b8a0c8908869", + DNSNameservers: []string{}, + DNSPublishFixedIP: true, AllocationPools: []subnets.AllocationPool{ { Start: "192.0.0.2", @@ -123,11 +129,12 @@ var Subnet2 = subnets.Subnet{ } var Subnet3 = subnets.Subnet{ - Name: "my_gatewayless_subnet", - EnableDHCP: true, - NetworkID: "d32019d3-bc6e-4319-9c1d-6722fc136a23", - TenantID: "4fd44f30292945e481c7b8a0c8908869", - DNSNameservers: []string{}, + Name: "my_gatewayless_subnet", + EnableDHCP: true, + NetworkID: "d32019d3-bc6e-4319-9c1d-6722fc136a23", + TenantID: "4fd44f30292945e481c7b8a0c8908869", + DNSNameservers: []string{}, + DNSPublishFixedIP: true, AllocationPools: []subnets.AllocationPool{ { Start: "192.168.1.2", @@ -142,11 +149,12 @@ var Subnet3 = subnets.Subnet{ } var Subnet4 = subnets.Subnet{ - Name: "my_subnet_with_subnetpool", - EnableDHCP: false, - NetworkID: "d32019d3-bc6e-4319-9c1d-6722fc136a23", - TenantID: "4fd44f30292945e481c7b8a0c8908869", - DNSNameservers: []string{}, + Name: "my_subnet_with_subnetpool", + EnableDHCP: false, + NetworkID: "d32019d3-bc6e-4319-9c1d-6722fc136a23", + TenantID: "4fd44f30292945e481c7b8a0c8908869", + DNSNameservers: []string{}, + DNSPublishFixedIP: false, AllocationPools: []subnets.AllocationPool{ { Start: "10.11.12.2", @@ -163,409 +171,414 @@ var Subnet4 = subnets.Subnet{ const SubnetGetResult = ` { - "subnet": { - "name": "my_subnet", - "enable_dhcp": true, - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", - "tenant_id": "4fd44f30292945e481c7b8a0c8908869", - "dns_nameservers": [], - "allocation_pools": [ - { - "start": "192.0.0.2", - "end": "192.255.255.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": "192.0.0.1", - "cidr": "192.0.0.0/8", - "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0b", - "subnetpool_id": "b80340c7-9960-4f67-a99c-02501656284b" - } + "subnet": { + "name": "my_subnet", + "enable_dhcp": true, + "dns_publish_fixed_ip": true, + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", + "tenant_id": "4fd44f30292945e481c7b8a0c8908869", + "dns_nameservers": [], + "allocation_pools": [ + { + "start": "192.0.0.2", + "end": "192.255.255.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": "192.0.0.1", + "cidr": "192.0.0.0/8", + "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0b", + "subnetpool_id": "b80340c7-9960-4f67-a99c-02501656284b" + } } ` const SubnetCreateRequest = ` { - "subnet": { - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", - "ip_version": 4, - "gateway_ip": "192.168.199.1", - "cidr": "192.168.199.0/24", - "dns_nameservers": ["foo"], - "service_types": ["network:routed"], - "allocation_pools": [ - { - "start": "192.168.199.2", - "end": "192.168.199.254" - } - ], - "host_routes": [{"destination":"","nexthop": "bar"}], - "subnetpool_id": "b80340c7-9960-4f67-a99c-02501656284b" - } + "subnet": { + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", + "ip_version": 4, + "dns_publish_fixed_ip": true, + "gateway_ip": "192.168.199.1", + "cidr": "192.168.199.0/24", + "dns_nameservers": ["foo"], + "service_types": ["network:routed"], + "allocation_pools": [ + { + "start": "192.168.199.2", + "end": "192.168.199.254" + } + ], + "host_routes": [{"destination":"","nexthop": "bar"}], + "subnetpool_id": "b80340c7-9960-4f67-a99c-02501656284b" + } } ` const SubnetCreateResult = ` { - "subnet": { - "name": "", - "enable_dhcp": true, - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", - "tenant_id": "4fd44f30292945e481c7b8a0c8908869", - "dns_nameservers": ["foo"], - "service_types": ["network:routed"], - "allocation_pools": [ - { - "start": "192.168.199.2", - "end": "192.168.199.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": "192.168.199.1", - "cidr": "192.168.199.0/24", - "id": "3b80198d-4f7b-4f77-9ef5-774d54e17126", - "subnetpool_id": "b80340c7-9960-4f67-a99c-02501656284b" - } + "subnet": { + "name": "", + "enable_dhcp": true, + "dns_publish_fixed_ip": true, + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", + "tenant_id": "4fd44f30292945e481c7b8a0c8908869", + "dns_nameservers": ["foo"], + "service_types": ["network:routed"], + "allocation_pools": [ + { + "start": "192.168.199.2", + "end": "192.168.199.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": "192.168.199.1", + "cidr": "192.168.199.0/24", + "id": "3b80198d-4f7b-4f77-9ef5-774d54e17126", + "subnetpool_id": "b80340c7-9960-4f67-a99c-02501656284b" + } } ` const SubnetCreateWithNoGatewayRequest = ` { - "subnet": { - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", - "ip_version": 4, - "cidr": "192.168.1.0/24", - "gateway_ip": null, - "allocation_pools": [ - { - "start": "192.168.1.2", - "end": "192.168.1.254" - } - ] - } + "subnet": { + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", + "ip_version": 4, + "cidr": "192.168.1.0/24", + "gateway_ip": null, + "allocation_pools": [ + { + "start": "192.168.1.2", + "end": "192.168.1.254" + } + ] + } } ` const SubnetCreateWithNoGatewayResponse = ` { - "subnet": { - "name": "", - "enable_dhcp": true, - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", - "tenant_id": "4fd44f30292945e481c7b8a0c8908869", - "allocation_pools": [ - { - "start": "192.168.1.2", - "end": "192.168.1.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": null, - "cidr": "192.168.1.0/24", - "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0c" - } + "subnet": { + "name": "", + "enable_dhcp": true, + "dns_publish_fixed_ip": true, + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", + "tenant_id": "4fd44f30292945e481c7b8a0c8908869", + "allocation_pools": [ + { + "start": "192.168.1.2", + "end": "192.168.1.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": null, + "cidr": "192.168.1.0/24", + "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0c" + } } ` const SubnetCreateWithDefaultGatewayRequest = ` { - "subnet": { - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", - "ip_version": 4, - "cidr": "192.168.1.0/24", - "allocation_pools": [ - { - "start": "192.168.1.2", - "end": "192.168.1.254" - } - ] - } + "subnet": { + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", + "ip_version": 4, + "cidr": "192.168.1.0/24", + "allocation_pools": [ + { + "start": "192.168.1.2", + "end": "192.168.1.254" + } + ] + } } ` const SubnetCreateWithDefaultGatewayResponse = ` { - "subnet": { - "name": "", - "enable_dhcp": true, - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", - "tenant_id": "4fd44f30292945e481c7b8a0c8908869", - "allocation_pools": [ - { - "start": "192.168.1.2", - "end": "192.168.1.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": "192.168.1.1", - "cidr": "192.168.1.0/24", - "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0c" - } + "subnet": { + "name": "", + "enable_dhcp": true, + "dns_publish_fixed_ip": true, + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a23", + "tenant_id": "4fd44f30292945e481c7b8a0c8908869", + "allocation_pools": [ + { + "start": "192.168.1.2", + "end": "192.168.1.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": "192.168.1.1", + "cidr": "192.168.1.0/24", + "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0c" + } } ` const SubnetCreateWithIPv6RaAddressModeRequest = ` { - "subnet": { - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", - "ip_version": 6, - "gateway_ip": "2001:db8:0:a::1", - "cidr": "2001:db8:0:a:0:0:0:0/64", - "ipv6_address_mode": "slaac", - "ipv6_ra_mode": "slaac" - } + "subnet": { + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", + "ip_version": 6, + "gateway_ip": "2001:db8:0:a::1", + "cidr": "2001:db8:0:a:0:0:0:0/64", + "ipv6_address_mode": "slaac", + "ipv6_ra_mode": "slaac" + } } ` const SubnetCreateWithIPv6RaAddressModeResponse = ` { - "subnet": { - "name": "", - "enable_dhcp": true, - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", - "tenant_id": "4fd44f30292945e481c7b8a0c8908869", - "dns_nameservers": [], - "host_routes": [], - "ip_version": 6, - "gateway_ip": "2001:db8:0:a::1", - "cidr": "2001:db8:0:a:0:0:0:0/64", - "id": "3b80198d-4f7b-4f77-9ef5-774d54e17126", - "ipv6_address_mode": "slaac", - "ipv6_ra_mode": "slaac" - } + "subnet": { + "name": "", + "enable_dhcp": true, + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", + "tenant_id": "4fd44f30292945e481c7b8a0c8908869", + "dns_nameservers": [], + "host_routes": [], + "ip_version": 6, + "gateway_ip": "2001:db8:0:a::1", + "cidr": "2001:db8:0:a:0:0:0:0/64", + "id": "3b80198d-4f7b-4f77-9ef5-774d54e17126", + "ipv6_address_mode": "slaac", + "ipv6_ra_mode": "slaac" + } } ` const SubnetCreateRequestWithNoCIDR = ` { - "subnet": { - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", - "ip_version": 4, - "dns_nameservers": ["foo"], - "host_routes": [{"destination":"","nexthop": "bar"}], - "subnetpool_id": "b80340c7-9960-4f67-a99c-02501656284b" - } + "subnet": { + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", + "ip_version": 4, + "dns_nameservers": ["foo"], + "host_routes": [{"destination":"","nexthop": "bar"}], + "subnetpool_id": "b80340c7-9960-4f67-a99c-02501656284b" + } } ` const SubnetCreateRequestWithPrefixlen = ` { - "subnet": { - "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", - "ip_version": 4, - "dns_nameservers": ["foo"], - "host_routes": [{"destination":"","nexthop": "bar"}], - "subnetpool_id": "b80340c7-9960-4f67-a99c-02501656284b", - "prefixlen": 12 - } + "subnet": { + "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", + "ip_version": 4, + "dns_nameservers": ["foo"], + "host_routes": [{"destination":"","nexthop": "bar"}], + "subnetpool_id": "b80340c7-9960-4f67-a99c-02501656284b", + "prefixlen": 12 + } } ` const SubnetUpdateRequest = ` { - "subnet": { - "name": "my_new_subnet", - "dns_nameservers": ["foo"], - "host_routes": [{"destination":"","nexthop": "bar"}] - } + "subnet": { + "name": "my_new_subnet", + "dns_nameservers": ["foo"], + "host_routes": [{"destination":"","nexthop": "bar"}] + } } ` const SubnetUpdateResponse = ` { - "subnet": { - "name": "my_new_subnet", - "enable_dhcp": true, - "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", - "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", - "dns_nameservers": [], - "allocation_pools": [ - { - "start": "10.0.0.2", - "end": "10.0.0.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": "10.0.0.1", - "cidr": "10.0.0.0/24", - "id": "08eae331-0402-425a-923c-34f7cfe39c1b" - } + "subnet": { + "name": "my_new_subnet", + "enable_dhcp": true, + "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", + "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", + "dns_nameservers": [], + "allocation_pools": [ + { + "start": "10.0.0.2", + "end": "10.0.0.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": "10.0.0.1", + "cidr": "10.0.0.0/24", + "id": "08eae331-0402-425a-923c-34f7cfe39c1b" + } } ` const SubnetUpdateGatewayRequest = ` { - "subnet": { - "name": "my_new_subnet", - "gateway_ip": "10.0.0.1" - } + "subnet": { + "name": "my_new_subnet", + "gateway_ip": "10.0.0.1" + } } ` const SubnetUpdateGatewayResponse = ` { - "subnet": { - "name": "my_new_subnet", - "enable_dhcp": true, - "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", - "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", - "dns_nameservers": [], - "allocation_pools": [ - { - "start": "10.0.0.2", - "end": "10.0.0.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": "10.0.0.1", - "cidr": "10.0.0.0/24", - "id": "08eae331-0402-425a-923c-34f7cfe39c1b" - } + "subnet": { + "name": "my_new_subnet", + "enable_dhcp": true, + "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", + "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", + "dns_nameservers": [], + "allocation_pools": [ + { + "start": "10.0.0.2", + "end": "10.0.0.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": "10.0.0.1", + "cidr": "10.0.0.0/24", + "id": "08eae331-0402-425a-923c-34f7cfe39c1b" + } } ` const SubnetUpdateRemoveGatewayRequest = ` { - "subnet": { - "name": "my_new_subnet", - "gateway_ip": null - } + "subnet": { + "name": "my_new_subnet", + "gateway_ip": null + } } ` const SubnetUpdateRemoveGatewayResponse = ` { - "subnet": { - "name": "my_new_subnet", - "enable_dhcp": true, - "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", - "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", - "dns_nameservers": [], - "allocation_pools": [ - { - "start": "10.0.0.2", - "end": "10.0.0.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": null, - "cidr": "10.0.0.0/24", - "id": "08eae331-0402-425a-923c-34f7cfe39c1b" - } + "subnet": { + "name": "my_new_subnet", + "enable_dhcp": true, + "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", + "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", + "dns_nameservers": [], + "allocation_pools": [ + { + "start": "10.0.0.2", + "end": "10.0.0.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": null, + "cidr": "10.0.0.0/24", + "id": "08eae331-0402-425a-923c-34f7cfe39c1b" + } } ` const SubnetUpdateHostRoutesRequest = ` { - "subnet": { - "name": "my_new_subnet", - "host_routes": [ - { - "destination": "192.168.1.1/24", - "nexthop": "bar" - } - ] - } + "subnet": { + "name": "my_new_subnet", + "host_routes": [ + { + "destination": "192.168.1.1/24", + "nexthop": "bar" + } + ] + } } ` const SubnetUpdateHostRoutesResponse = ` { - "subnet": { - "name": "my_new_subnet", - "enable_dhcp": true, - "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", - "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", - "dns_nameservers": [], - "allocation_pools": [ - { - "start": "10.0.0.2", - "end": "10.0.0.254" - } - ], - "ip_version": 4, - "gateway_ip": "10.0.0.1", - "host_routes": [ - { - "destination": "192.168.1.1/24", - "nexthop": "bar" - } - ], - "cidr": "10.0.0.0/24", - "id": "08eae331-0402-425a-923c-34f7cfe39c1b" - } + "subnet": { + "name": "my_new_subnet", + "enable_dhcp": true, + "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", + "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", + "dns_nameservers": [], + "allocation_pools": [ + { + "start": "10.0.0.2", + "end": "10.0.0.254" + } + ], + "ip_version": 4, + "gateway_ip": "10.0.0.1", + "host_routes": [ + { + "destination": "192.168.1.1/24", + "nexthop": "bar" + } + ], + "cidr": "10.0.0.0/24", + "id": "08eae331-0402-425a-923c-34f7cfe39c1b" + } } ` const SubnetUpdateRemoveHostRoutesRequest = ` { - "subnet": { - "host_routes": [] - } + "subnet": { + "host_routes": [] + } } ` const SubnetUpdateRemoveHostRoutesResponse = ` { - "subnet": { - "name": "my_new_subnet", - "enable_dhcp": true, - "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", - "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", - "dns_nameservers": [], - "allocation_pools": [ - { - "start": "10.0.0.2", - "end": "10.0.0.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": null, - "cidr": "10.0.0.0/24", - "id": "08eae331-0402-425a-923c-34f7cfe39c1b" - } + "subnet": { + "name": "my_new_subnet", + "enable_dhcp": true, + "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", + "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", + "dns_nameservers": [], + "allocation_pools": [ + { + "start": "10.0.0.2", + "end": "10.0.0.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": null, + "cidr": "10.0.0.0/24", + "id": "08eae331-0402-425a-923c-34f7cfe39c1b" + } } ` const SubnetUpdateAllocationPoolRequest = ` { - "subnet": { - "name": "my_new_subnet", - "allocation_pools": [ - { - "start": "10.1.0.2", - "end": "10.1.0.254" - } - ] - } + "subnet": { + "name": "my_new_subnet", + "allocation_pools": [ + { + "start": "10.1.0.2", + "end": "10.1.0.254" + } + ] + } } ` const SubnetUpdateAllocationPoolResponse = ` { - "subnet": { - "name": "my_new_subnet", - "enable_dhcp": true, - "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", - "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", - "dns_nameservers": [], - "allocation_pools": [ - { - "start": "10.1.0.2", - "end": "10.1.0.254" - } - ], - "host_routes": [], - "ip_version": 4, - "gateway_ip": "10.0.0.1", - "cidr": "10.0.0.0/24", - "id": "08eae331-0402-425a-923c-34f7cfe39c1b" - } + "subnet": { + "name": "my_new_subnet", + "enable_dhcp": true, + "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", + "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", + "dns_nameservers": [], + "allocation_pools": [ + { + "start": "10.1.0.2", + "end": "10.1.0.254" + } + ], + "host_routes": [], + "ip_version": 4, + "gateway_ip": "10.0.0.1", + "cidr": "10.0.0.0/24", + "id": "08eae331-0402-425a-923c-34f7cfe39c1b" + } } ` diff --git a/openstack/networking/v2/subnets/testing/requests_test.go b/openstack/networking/v2/subnets/testing/requests_test.go index 7e82d5855d..a87da46236 100644 --- a/openstack/networking/v2/subnets/testing/requests_test.go +++ b/openstack/networking/v2/subnets/testing/requests_test.go @@ -106,6 +106,7 @@ func TestCreate(t *testing.T) { }) var gatewayIP = "192.168.199.1" + var dnsPublishFixedIP = true opts := subnets.CreateOpts{ NetworkID: "d32019d3-bc6e-4319-9c1d-6722fc136a22", IPVersion: 4, @@ -117,8 +118,9 @@ func TestCreate(t *testing.T) { End: "192.168.199.254", }, }, - DNSNameservers: []string{"foo"}, - ServiceTypes: []string{"network:routed"}, + DNSNameservers: []string{"foo"}, + DNSPublishFixedIP: &dnsPublishFixedIP, + ServiceTypes: []string{"network:routed"}, HostRoutes: []subnets.HostRoute{ {NextHop: "bar"}, }, @@ -128,6 +130,7 @@ func TestCreate(t *testing.T) { th.AssertNoErr(t, err) th.AssertEquals(t, s.Name, "") + th.AssertEquals(t, s.DNSPublishFixedIP, true) th.AssertEquals(t, s.EnableDHCP, true) th.AssertEquals(t, s.NetworkID, "d32019d3-bc6e-4319-9c1d-6722fc136a22") th.AssertEquals(t, s.TenantID, "4fd44f30292945e481c7b8a0c8908869") @@ -318,6 +321,7 @@ func TestCreateWithNoCIDR(t *testing.T) { th.AssertNoErr(t, err) th.AssertEquals(t, s.Name, "") + th.AssertEquals(t, s.DNSPublishFixedIP, true) th.AssertEquals(t, s.EnableDHCP, true) th.AssertEquals(t, s.NetworkID, "d32019d3-bc6e-4319-9c1d-6722fc136a22") th.AssertEquals(t, s.TenantID, "4fd44f30292945e481c7b8a0c8908869") @@ -367,6 +371,7 @@ func TestCreateWithPrefixlen(t *testing.T) { th.AssertNoErr(t, err) th.AssertEquals(t, s.Name, "") + th.AssertEquals(t, s.DNSPublishFixedIP, true) th.AssertEquals(t, s.EnableDHCP, true) th.AssertEquals(t, s.NetworkID, "d32019d3-bc6e-4319-9c1d-6722fc136a22") th.AssertEquals(t, s.TenantID, "4fd44f30292945e481c7b8a0c8908869") From 97865489a0410fd6a6f9e52ca1e0d56eba9c4480 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Thu, 18 Jul 2024 09:32:49 +0200 Subject: [PATCH 107/118] [v1] actions: Add a label to hold merging Add a check that fails when the PR has the 'hold' label. --- .github/workflows/check-pr-labels.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/check-pr-labels.yaml diff --git a/.github/workflows/check-pr-labels.yaml b/.github/workflows/check-pr-labels.yaml new file mode 100644 index 0000000000..ea8068f602 --- /dev/null +++ b/.github/workflows/check-pr-labels.yaml @@ -0,0 +1,18 @@ +name: Ready +on: + pull_request_target: + types: + - opened + - labeled + +jobs: + hold: + if: github.event.pull_request.merged == false + runs-on: ubuntu-latest + steps: + - if: > + contains(github.event.pull_request.labels.*.name, 'hold') + run: 'false' + - if: > + !contains(github.event.pull_request.labels.*.name, 'hold') + run: 'true' From d16d09daf0bbf1a2348c5f9ae6c3a40fd9896b19 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Thu, 18 Jul 2024 10:34:03 +0200 Subject: [PATCH 108/118] actions: Correctly refresh hold state Before adding these trigger types, the `hold` job was often skipped, unnecessarily blocking the Pull request. --- .github/workflows/check-pr-labels.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check-pr-labels.yaml b/.github/workflows/check-pr-labels.yaml index ea8068f602..4fbb7fc0b8 100644 --- a/.github/workflows/check-pr-labels.yaml +++ b/.github/workflows/check-pr-labels.yaml @@ -2,8 +2,11 @@ name: Ready on: pull_request_target: types: - - opened - labeled + - opened + - reopened + - synchronize + - unlabeled jobs: hold: From ba5b868cb8b8382d6fa7391596bb86ac10bc95c0 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Thu, 18 Jul 2024 16:04:44 +0200 Subject: [PATCH 109/118] [v1] actions: Refactor the semver assessment Using `gh` lets us drop two external dependencies, and condensate the steps a bit. After this change: * new pushes in the PR won't trigger relabeling if the assessment is unchanged * failures in the workflow will be notified as comments in the PR rather than via the `semver:unknown` label The next natural step is to set this job as mandatory, to that a failure to assess semver will block merging. --- .github/labels.yaml | 27 ++++++++++++ .github/workflows/semver-auto.yaml | 71 ++++++++++++++++-------------- 2 files changed, 64 insertions(+), 34 deletions(-) create mode 100644 .github/labels.yaml diff --git a/.github/labels.yaml b/.github/labels.yaml new file mode 100644 index 0000000000..3069b5bd6b --- /dev/null +++ b/.github/labels.yaml @@ -0,0 +1,27 @@ +- color: '30ABB9' + description: This PR will be backported to v1 + name: backport-v1 +- color: 'E99695' + description: This PR will be backported to v2 + name: backport-v2 +- color: '0366d6' + description: Pull requests that update a dependency file + name: dependencies +- color: '000000' + description: Pull requests that update GitHub Actions code + name: github_actions +- color: 'BCF611' + description: A good issue for first-time contributors + name: good first issue +- color: '9E1957' + description: Breaking change + name: semver:major +- color: 'FBCA04' + description: Backwards-compatible change + name: semver:minor +- color: '6E7624' + description: No API change + name: semver:patch +- color: 'D73A4A' + description: Do not merge + name: hold diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/semver-auto.yaml index c042be134a..eb92701452 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/semver-auto.yaml @@ -1,21 +1,15 @@ -name: Add PR semver labels +name: Add semver labels on: pull_request_target: - types: [opened, synchronize, reopened] + types: + - opened + - synchronize + - reopened + jobs: go-apidiff: runs-on: ubuntu-latest steps: - - name: Remove the semver labels - uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 - with: - labels: | - semver:patch - semver:minor - semver:major - semver:unknown - github_token: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/checkout@v4 with: fetch-depth: 0 @@ -30,13 +24,6 @@ jobs: env: GIT_SEQUENCE_EDITOR: '/usr/bin/true' - - name: Add semver:unknown label - if: failure() - uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - labels: semver:unknown - - uses: actions/setup-go@v5 with: go-version: '1' @@ -54,23 +41,39 @@ jobs: if: steps.go-apidiff.outcome != 'success' && steps.go-apidiff.outputs.semver-type != 'major' run: exit 1 - - name: Add semver:patch label + - name: Add label semver:patch if: steps.go-apidiff.outputs.semver-type == 'patch' - uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - labels: semver:patch + run: gh pr edit "$NUMBER" --add-label "semver:patch" --remove-label "semver:major,semver:minor" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.pull_request.number }} - - name: Add semver:minor label + - name: Add label semver:minor if: steps.go-apidiff.outputs.semver-type == 'minor' - uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - labels: semver:minor + run: gh pr edit "$NUMBER" --add-label "semver:minor" --remove-label "semver:major,semver:patch" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.pull_request.number }} - - name: Add semver:major label + - name: Add label semver:major if: steps.go-apidiff.outputs.semver-type == 'major' - uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - labels: semver:major + run: gh pr edit "$NUMBER" --add-label "semver:major" --remove-label "semver:minor,semver:patch" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.pull_request.number }} + + - name: Report failure + if: failure() + run: | + gh pr edit "$NUMBER" --remove-label "semver:major,semver:minor,semver:patch" + gh issue comment "$NUMBER" --body "$BODY" + exit 1 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.pull_request.number }} + BODY: > + Failed to assess the semver bump. See [logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details. From c44b06d30d1e6eb646ee919738b0aa40b5e3ef8b Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Mon, 22 Jul 2024 10:15:35 +0200 Subject: [PATCH 110/118] Add needinfo label Includes a Github action that automatically removes the `needinfo` label when the original author adds a comment. --- .github/labels.yaml | 3 +++ .github/workflows/label-issue.yaml | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 .github/workflows/label-issue.yaml diff --git a/.github/labels.yaml b/.github/labels.yaml index 3069b5bd6b..a266cf1678 100644 --- a/.github/labels.yaml +++ b/.github/labels.yaml @@ -25,3 +25,6 @@ - color: 'D73A4A' description: Do not merge name: hold +- color: 'F9D0C4' + description: Additional information requested + name: needinfo diff --git a/.github/workflows/label-issue.yaml b/.github/workflows/label-issue.yaml new file mode 100644 index 0000000000..723f4cd04e --- /dev/null +++ b/.github/workflows/label-issue.yaml @@ -0,0 +1,17 @@ +name: Label issue +on: + issue_comment: + types: + - created + +jobs: + clear_needinfo: + name: Clear needinfo + if: ${{ github.event.issue.user.login }} == ${{ github.event.comment.user.login }} + runs-on: ubuntu-latest + steps: + - run: gh pr edit "$NUMBER" --remove-label "needinfo" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.pull_request.number }} From a203b5e9afe6f6614593194cb1e6edaa458d6fdb Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Fri, 19 Jul 2024 12:07:37 +0200 Subject: [PATCH 111/118] actions: Label PRs based on the paths of files being changed To facilitate PR assignment and ultimately reviews, label the PRs based on what they touch. --- .github/labeler.yml | 144 ++++++++++++++++++ .github/labels.yaml | 95 +++++++++++- .../{semver-auto.yaml => label-pr.yaml} | 12 +- 3 files changed, 243 insertions(+), 8 deletions(-) create mode 100644 .github/labeler.yml rename .github/workflows/{semver-auto.yaml => label-pr.yaml} (94%) diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000000..a07b39fe3e --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,144 @@ +edit:dependencies: +- changed-files: + - any-glob-to-any-file: + - 'go.mod' + - 'go.sum' + - '.github/dependabot.yml' +edit:actions: +- changed-files: + - any-glob-to-any-file: + - '.github/**' +edit:gophercloud: +- changed-files: + - any-glob-to-any-file: + - '*.go' + - 'testing/**' + - 'pagination/**' +edit:openstack: +- changed-files: + - any-glob-to-any-file: + - 'openstack/*' + - 'openstack/testing/**' +edit:baremetal: +- changed-files: + - any-glob-to-any-file: + - 'openstack/baremetal/**' + - 'internal/acceptance/openstack/baremetal/**' +edit:baremetalintrospection: +- changed-files: + - any-glob-to-any-file: + - 'openstack/baremetalintrospection/**' +edit:blockstorage: +- changed-files: + - any-glob-to-any-file: + - 'openstack/blockstorage/**' + - 'internal/acceptance/openstack/blockstorage/**' +edit:common: +- changed-files: + - any-glob-to-any-file: + - 'openstack/common/**' +edit:compute: +- changed-files: + - any-glob-to-any-file: + - 'openstack/compute/**' + - 'internal/acceptance/openstack/compute/**' +edit:config: +- changed-files: + - any-glob-to-any-file: + - 'openstack/config/**' +edit:container: +- changed-files: + - any-glob-to-any-file: + - 'openstack/container/**' + - 'internal/acceptance/openstack/container/**' +edit:containerinfra: +- changed-files: + - any-glob-to-any-file: + - 'openstack/containerinfra/**' + - 'internal/acceptance/openstack/containerinfra/**' +edit:db: +- changed-files: + - any-glob-to-any-file: + - 'openstack/db/**' + - 'internal/acceptance/openstack/db/**' +edit:dns: +- changed-files: + - any-glob-to-any-file: + - 'openstack/dns/**' + - 'internal/acceptance/openstack/dns/**' +edit:identity: +- changed-files: + - any-glob-to-any-file: + - 'openstack/identity/**' + - 'internal/acceptance/openstack/identity/**' +edit:image: +- changed-files: + - any-glob-to-any-file: + - 'openstack/image/**' + - 'internal/acceptance/openstack/image/**' +edit:keymanager: +- changed-files: + - any-glob-to-any-file: + - 'openstack/keymanager/**' + - 'internal/acceptance/openstack/keymanager/**' +edit:loadbalancer: +- changed-files: + - any-glob-to-any-file: + - 'openstack/loadbalancer/**' + - 'internal/acceptance/openstack/loadbalancer/**' +edit:messaging: +- changed-files: + - any-glob-to-any-file: + - 'openstack/messaging/**' + - 'internal/acceptance/openstack/messaging/**' +edit:networking: +- changed-files: + - any-glob-to-any-file: + - 'openstack/networking/**' + - 'internal/acceptance/openstack/networking/**' +edit:objectstorage: +- changed-files: + - any-glob-to-any-file: + - 'openstack/objectstorage/**' + - 'internal/acceptance/openstack/objectstorage/**' +edit:orchestration: +- changed-files: + - any-glob-to-any-file: + - 'openstack/orchestration/**' + - 'internal/acceptance/openstack/orchestration/**' +edit:placement: +- changed-files: + - any-glob-to-any-file: + - 'openstack/placement/**' + - 'internal/acceptance/openstack/placement/**' +edit:sharedfilesystems: +- changed-files: + - any-glob-to-any-file: + - 'openstack/sharedfilesystems/**' + - 'internal/acceptance/openstack/sharedfilesystems/**' +edit:testinfra: +- changed-files: + - any-glob-to-any-file: + - 'testhelper/**' + - 'internal/acceptance/*' + - 'internal/acceptance/openstack/*' + - 'internal/acceptance/clients/**' + - 'internal/acceptance/tools/**' + - '.github/workflows/functional-*.yaml' + - '.github/workflows/unit.yaml' + - '.github/workflows/lint.yaml' + - 'script/**' +edit:utils: +- changed-files: + - any-glob-to-any-file: + - 'openstack/utils/**' +edit:workflow: +- changed-files: + - any-glob-to-any-file: + - 'openstack/workflow/**' + - 'internal/acceptance/openstack/workflow/**' + +v1: +- base-branch: 'v1' +v2: +- base-branch: 'v2' diff --git a/.github/labels.yaml b/.github/labels.yaml index a266cf1678..4f888b4d4f 100644 --- a/.github/labels.yaml +++ b/.github/labels.yaml @@ -4,12 +4,6 @@ - color: 'E99695' description: This PR will be backported to v2 name: backport-v2 -- color: '0366d6' - description: Pull requests that update a dependency file - name: dependencies -- color: '000000' - description: Pull requests that update GitHub Actions code - name: github_actions - color: 'BCF611' description: A good issue for first-time contributors name: good first issue @@ -28,3 +22,92 @@ - color: 'F9D0C4' description: Additional information requested name: needinfo + +- color: '30ABB9' + description: This PR targets v1 + name: v1 +- color: 'E99695' + description: This PR targets v2 + name: v2 + +- color: '000000' + description: This PR updates dependencies + name: edit:dependencies +- color: '000000' + description: This PR updates GitHub Actions code + name: edit:actions +- color: '000000' + description: This PR updates common Gophercloud code + name: edit:gophercloud +- color: '000000' + description: This PR updates common OpenStack code + name: edit:openstack +- color: '000000' + description: This PR updates baremetal code + name: edit:baremetal +- color: '000000' + description: This PR updates baremetalintrospection code + name: edit:baremetalintrospection +- color: '000000' + description: This PR updates blockstorage code + name: edit:blockstorage +- color: '000000' + description: This PR updates common code + name: edit:common +- color: '000000' + description: This PR updates compute code + name: edit:compute +- color: '000000' + description: This PR updates config code + name: edit:config +- color: '000000' + description: This PR updates container code + name: edit:container +- color: '000000' + description: This PR updates containerinfra code + name: edit:containerinfra +- color: '000000' + description: This PR updates db code + name: edit:db +- color: '000000' + description: This PR updates dns code + name: edit:dns +- color: '000000' + description: This PR updates identity code + name: edit:identity +- color: '000000' + description: This PR updates image code + name: edit:image +- color: '000000' + description: This PR updates keymanager code + name: edit:keymanager +- color: '000000' + description: This PR updates loadbalancer code + name: edit:loadbalancer +- color: '000000' + description: This PR updates messaging code + name: edit:messaging +- color: '000000' + description: This PR updates networking code + name: edit:networking +- color: '000000' + description: This PR updates objectstorage code + name: edit:objectstorage +- color: '000000' + description: This PR updates orchestration code + name: edit:orchestration +- color: '000000' + description: This PR updates placement code + name: edit:placement +- color: '000000' + description: This PR updates sharedfilesystems code + name: edit:sharedfilesystems +- color: '000000' + description: This PR updates testing code + name: edit:testing +- color: '000000' + description: This PR updates utils code + name: edit:utils +- color: '000000' + description: This PR updates workflow code + name: edit:workflow diff --git a/.github/workflows/semver-auto.yaml b/.github/workflows/label-pr.yaml similarity index 94% rename from .github/workflows/semver-auto.yaml rename to .github/workflows/label-pr.yaml index eb92701452..44d46b0e15 100644 --- a/.github/workflows/semver-auto.yaml +++ b/.github/workflows/label-pr.yaml @@ -1,4 +1,4 @@ -name: Add semver labels +name: Label PR on: pull_request_target: types: @@ -7,7 +7,7 @@ on: - reopened jobs: - go-apidiff: + semver: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -77,3 +77,11 @@ jobs: NUMBER: ${{ github.event.pull_request.number }} BODY: > Failed to assess the semver bump. See [logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details. + + edits: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v5 From 3de5904601d880f513e51b41b6663b83fd34ce13 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 24 Jul 2024 11:31:09 +0200 Subject: [PATCH 112/118] Prepare v1.14.0 --- CHANGELOG.md | 6 ++++++ provider_client.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f579884c6..dc38bf5871 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v1.14.0 (2024-07-24) + +* [GH-3095](https://github.com/gophercloud/gophercloud/pull/3095) [neutron]: introduce Description argument for the portforwarding +* [GH-3098](https://github.com/gophercloud/gophercloud/pull/3098) [neutron]: introduce Stateful argument for the security groups +* [GH-3099](https://github.com/gophercloud/gophercloud/pull/3099) [networking]: subnet add field dns_publish_fixed_ip + ## v1.13.0 (2024-07-08) * [GH-3044](https://github.com/gophercloud/gophercloud/pull/3044) [v1] Add ci jobs for openstack caracal diff --git a/provider_client.go b/provider_client.go index 5b9381b9b1..6e57f48843 100644 --- a/provider_client.go +++ b/provider_client.go @@ -14,7 +14,7 @@ import ( // DefaultUserAgent is the default User-Agent string set in the request header. const ( - DefaultUserAgent = "gophercloud/v1.13.0" + DefaultUserAgent = "gophercloud/v1.14.0" DefaultMaxBackoffRetries = 60 ) From 4ffa3ead1e9aa1345e84cd9849df543997b2676a Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Mon, 29 Jul 2024 09:56:05 +0200 Subject: [PATCH 113/118] Fix security group rule "any protocol" Before this patch, Gophercloud attempted to create a security group rule that would be applied regardless of the protocol by passing the literal `"any"` as the rule protocol. Despite being correct according to [the documentation][1], Neutron rejects the value `"any"` with an HTTP status code of `400 Bad Request`. This change replaces the value of `ProtocolAny` to be the empty string `""`, which has the effect of creating a rule that applies to any protocol. cf: [Neutron bug 2074056][2] [1]: https://docs.openstack.org/api-ref/network/v2/#create-security-group-rule [2]: https://bugs.launchpad.net/neutron/+bug/2074056 --- openstack/networking/v2/extensions/security/rules/requests.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openstack/networking/v2/extensions/security/rules/requests.go b/openstack/networking/v2/extensions/security/rules/requests.go index 364f7f5c98..480b1510ca 100644 --- a/openstack/networking/v2/extensions/security/rules/requests.go +++ b/openstack/networking/v2/extensions/security/rules/requests.go @@ -75,7 +75,7 @@ const ( ProtocolUDP RuleProtocol = "udp" ProtocolUDPLite RuleProtocol = "udplite" ProtocolVRRP RuleProtocol = "vrrp" - ProtocolAny RuleProtocol = "any" + ProtocolAny RuleProtocol = "" ) // CreateOptsBuilder allows extensions to add additional parameters to the From 815c7c865234569fc771729e04e016280da86c47 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Wed, 18 Sep 2024 13:52:21 +0200 Subject: [PATCH 114/118] Prepare v1.14.1 --- CHANGELOG.md | 4 ++++ provider_client.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc38bf5871..b19b5e7753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v1.14.1 (2024-09-18) + +* [GH-3162](https://github.com/gophercloud/gophercloud/pull/3162) Fix security group rule "any protocol" + ## v1.14.0 (2024-07-24) * [GH-3095](https://github.com/gophercloud/gophercloud/pull/3095) [neutron]: introduce Description argument for the portforwarding diff --git a/provider_client.go b/provider_client.go index 6e57f48843..7e25882c87 100644 --- a/provider_client.go +++ b/provider_client.go @@ -14,7 +14,7 @@ import ( // DefaultUserAgent is the default User-Agent string set in the request header. const ( - DefaultUserAgent = "gophercloud/v1.14.0" + DefaultUserAgent = "gophercloud/v1.14.1" DefaultMaxBackoffRetries = 60 ) From 2d138b999e1fc5d3e10f639b93d652004ef7cf28 Mon Sep 17 00:00:00 2001 From: Pierre Prinetti Date: Mon, 21 Oct 2024 12:04:40 +0200 Subject: [PATCH 115/118] Fix clear-needinfo The gh tool must be set to operate on an issue rather than on a PR. --- .github/workflows/label-issue.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/label-issue.yaml b/.github/workflows/label-issue.yaml index 723f4cd04e..a1fbff16e0 100644 --- a/.github/workflows/label-issue.yaml +++ b/.github/workflows/label-issue.yaml @@ -9,9 +9,11 @@ jobs: name: Clear needinfo if: ${{ github.event.issue.user.login }} == ${{ github.event.comment.user.login }} runs-on: ubuntu-latest + permissions: + issues: write steps: - - run: gh pr edit "$NUMBER" --remove-label "needinfo" + - run: gh issue edit "$NUMBER" --remove-label "needinfo" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} - NUMBER: ${{ github.event.pull_request.number }} + NUMBER: ${{ github.event.issue.number }} From e4705e0c497a855af677732d17ca5d6836654bfc Mon Sep 17 00:00:00 2001 From: Pavlo Shchelokovskyy Date: Wed, 15 Jan 2025 15:28:38 +0200 Subject: [PATCH 116/118] Fix JSON field name hints in APIVersion structs `son:"status"` is not a valid hint for JSON (de/en)coder. --- openstack/loadbalancer/v2/apiversions/results.go | 2 +- openstack/networking/v2/apiversions/results.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openstack/loadbalancer/v2/apiversions/results.go b/openstack/loadbalancer/v2/apiversions/results.go index dce4aa5d14..a363e0d5bb 100644 --- a/openstack/loadbalancer/v2/apiversions/results.go +++ b/openstack/loadbalancer/v2/apiversions/results.go @@ -5,7 +5,7 @@ import "github.com/gophercloud/gophercloud/pagination" // APIVersion represents an API version for load balancer. It contains // the status of the API, and its unique ID. type APIVersion struct { - Status string `son:"status"` + Status string `json:"status"` ID string `json:"id"` } diff --git a/openstack/networking/v2/apiversions/results.go b/openstack/networking/v2/apiversions/results.go index ad9d092fa0..93163047ae 100644 --- a/openstack/networking/v2/apiversions/results.go +++ b/openstack/networking/v2/apiversions/results.go @@ -7,7 +7,7 @@ import ( // APIVersion represents an API version for Neutron. It contains the status of // the API, and its unique ID. type APIVersion struct { - Status string `son:"status"` + Status string `json:"status"` ID string `json:"id"` } From a2139377f6fcf311236bd8c1ec2f0f74d9f6873f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Andr=C3=A9?= Date: Tue, 4 Feb 2025 09:58:05 +0100 Subject: [PATCH 117/118] Add permissions to the label-issue workflow It needs write permissions on PRs as well otherwise it fails to runs. --- .github/workflows/label-issue.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/label-issue.yaml b/.github/workflows/label-issue.yaml index a1fbff16e0..45ab4cbe34 100644 --- a/.github/workflows/label-issue.yaml +++ b/.github/workflows/label-issue.yaml @@ -11,6 +11,7 @@ jobs: runs-on: ubuntu-latest permissions: issues: write + pull-requests: write steps: - run: gh issue edit "$NUMBER" --remove-label "needinfo" env: From a5c1f085f980bfea2259d4ef284a509b081f47c7 Mon Sep 17 00:00:00 2001 From: Zhiwei Huang Date: Wed, 20 Mar 2024 16:15:13 +0800 Subject: [PATCH 118/118] Update the doc of openstack.AuthOptionsFromEnv function If OS_PROJECT_NAME is set, it requires the domain to be set as well to get unique project entity on the identity service (keystone). Signed-off-by: Zhiwei Huang --- openstack/auth_env.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openstack/auth_env.go b/openstack/auth_env.go index 7c6d06f0c3..79b73022ff 100644 --- a/openstack/auth_env.go +++ b/openstack/auth_env.go @@ -24,8 +24,8 @@ OS_PROJECT_NAME and the latter are expected against a v3 auth api. If OS_PROJECT_ID and OS_PROJECT_NAME are set, they will still be referred as "tenant" in Gophercloud. -If OS_PROJECT_NAME is set, it requires OS_PROJECT_ID to be set as well to -handle projects not on the default domain. +If OS_PROJECT_NAME is set, it requires OS_DOMAIN_ID or OS_DOMAIN_NAME to be +set as well to handle projects not on the default domain. To use this function, first set the OS_* environment variables (for example, by sourcing an `openrc` file), then: