Repository: metal3-io/baremetal-operator
Pull request #1569 (2024-02-29 09:15:21)

⚠️ Update to gophercloud 2.0.0-beta2
Although the current version is specified as 1.5.1, it's actually
a commit somewhere in the 2.0 branch. This change brings us to
a more specific version.

2.0.0-beta2 introduced a requirement on Context for all calls.

Signed-off-by: Dmitry Tantsur <dtantsur@protonmail.com>


Patch:
diff --git a/cmd/get-hardware-details/main.go b/cmd/get-hardware-details/main.go
index f51cfcef..39f4631a 100644
--- a/cmd/get-hardware-details/main.go
+++ b/cmd/get-hardware-details/main.go
@@ -3,6 +3,7 @@
 package main
 
 import (
+	"context"
 	"encoding/json"
 	"fmt"
 	"net"
@@ -10,7 +11,7 @@ import (
 	"os"
 	"strings"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"k8s.io/klog/v2"
 
 	"github.com/metal3-io/baremetal-operator/pkg/provisioner/ironic/clients"
@@ -59,7 +60,7 @@ func main() {
 		os.Exit(1)
 	}
 
-	introData := nodes.GetInventory(ironic, opts.NodeID)
+	introData := nodes.GetInventory(context.TODO(), ironic, opts.NodeID)
 	data, err := introData.Extract()
 	if err != nil {
 		fmt.Printf("could not get inspection data: %s", err)
diff --git a/go.mod b/go.mod
index 8ffcd886..48d399b2 100644
--- a/go.mod
+++ b/go.mod
@@ -1,11 +1,11 @@
 module github.com/metal3-io/baremetal-operator
 
-go 1.21
+go 1.21.6
 
 require (
 	github.com/go-logr/logr v1.4.1
 	github.com/google/safetext v0.0.0-20230106111101-7156a760e523
-	github.com/gophercloud/gophercloud v1.5.1-0.20231117122435-08456f7fe42e
+	github.com/gophercloud/gophercloud/v2 v2.0.0-beta.2
 	github.com/metal3-io/baremetal-operator/apis v0.5.0
 	github.com/metal3-io/baremetal-operator/pkg/hardwareutils v0.5.0
 	github.com/onsi/gomega v1.31.1
@@ -62,7 +62,7 @@ require (
 	go.uber.org/multierr v1.11.0 // indirect
 	golang.org/x/net v0.19.0 // indirect
 	golang.org/x/oauth2 v0.12.0 // indirect
-	golang.org/x/sys v0.15.0 // indirect
+	golang.org/x/sys v0.17.0 // indirect
 	golang.org/x/term v0.15.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	golang.org/x/time v0.3.0 // indirect
diff --git a/go.sum b/go.sum
index b9c72cbb..851367f7 100644
--- a/go.sum
+++ b/go.sum
@@ -53,8 +53,8 @@ github.com/google/safetext v0.0.0-20230106111101-7156a760e523 h1:i4NsbmB9pD5+Ggp
 github.com/google/safetext v0.0.0-20230106111101-7156a760e523/go.mod h1:mJNEy0r5YPHC7ChQffpOszlGB4L1iqjXWpIEKcFpr9s=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/gophercloud/gophercloud v1.5.1-0.20231117122435-08456f7fe42e h1:acHzJUXVfS+GImmi+yyM2+AOiaO94Z4KaTTFVU6Ov9U=
-github.com/gophercloud/gophercloud v1.5.1-0.20231117122435-08456f7fe42e/go.mod h1:ecnaHbFxBunc2UeAONDQbkQacv6WP1syeZ02TgAB7kA=
+github.com/gophercloud/gophercloud/v2 v2.0.0-beta.2 h1:JWv6L7eg3+aIS57n11YlVvtn1pVCKpVlMo24ANj/OVc=
+github.com/gophercloud/gophercloud/v2 v2.0.0-beta.2/go.mod h1:Sy5GHwY4iazyaRf94rzL/VxJToVWn8WnIH+1cXqoAks=
 github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
 github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -165,8 +165,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
+golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
 golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
diff --git a/pkg/provisioner/ironic/clients/client.go b/pkg/provisioner/ironic/clients/client.go
index e175b1f0..859ee591 100644
--- a/pkg/provisioner/ironic/clients/client.go
+++ b/pkg/provisioner/ironic/clients/client.go
@@ -6,9 +6,9 @@ import (
 	"os"
 	"time"
 
-	"github.com/gophercloud/gophercloud"
-	"github.com/gophercloud/gophercloud/openstack/baremetal/httpbasic"
-	"github.com/gophercloud/gophercloud/openstack/baremetal/noauth"
+	"github.com/gophercloud/gophercloud/v2"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/httpbasic"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/noauth"
 	"go.etcd.io/etcd/client/pkg/v3/transport"
 )
 
diff --git a/pkg/provisioner/ironic/clients/features.go b/pkg/provisioner/ironic/clients/features.go
index 888c7a21..44e4c3f0 100644
--- a/pkg/provisioner/ironic/clients/features.go
+++ b/pkg/provisioner/ironic/clients/features.go
@@ -1,11 +1,12 @@
 package clients
 
 import (
+	"context"
 	"fmt"
 
 	"github.com/go-logr/logr"
-	"github.com/gophercloud/gophercloud"
-	"github.com/gophercloud/gophercloud/openstack/utils"
+	"github.com/gophercloud/gophercloud/v2"
+	"github.com/gophercloud/gophercloud/v2/openstack/utils"
 )
 
 // AvailableFeatures represents features that Ironic API provides.
@@ -21,8 +22,8 @@ type AvailableFeatures struct {
 // Version 1.81 allows retrival of Node inventory.
 const baseline = "1.81"
 
-func GetAvailableFeatures(client *gophercloud.ServiceClient) (features AvailableFeatures, err error) {
-	mvs, err := utils.GetSupportedMicroversions(client)
+func GetAvailableFeatures(ctx context.Context, client *gophercloud.ServiceClient) (features AvailableFeatures, err error) {
+	mvs, err := utils.GetSupportedMicroversions(ctx, client)
 	if err != nil {
 		return
 	}
diff --git a/pkg/provisioner/ironic/dependencies.go b/pkg/provisioner/ironic/dependencies.go
index c1c62e90..45ad62b9 100644
--- a/pkg/provisioner/ironic/dependencies.go
+++ b/pkg/provisioner/ironic/dependencies.go
@@ -1,8 +1,10 @@
 package ironic
 
 import (
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/drivers"
-	"github.com/gophercloud/gophercloud/pagination"
+	"context"
+
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/drivers"
+	"github.com/gophercloud/gophercloud/v2/pagination"
 
 	"github.com/metal3-io/baremetal-operator/pkg/provisioner/ironic/clients"
 )
@@ -11,7 +13,7 @@ import (
 func (p *ironicProvisioner) TryInit() (ready bool, err error) {
 	p.debugLog.Info("verifying ironic provisioner dependencies")
 
-	p.availableFeatures, err = clients.GetAvailableFeatures(p.client)
+	p.availableFeatures, err = clients.GetAvailableFeatures(p.ctx, p.client)
 	if err != nil {
 		p.log.Info("error caught while checking endpoint, will retry", "endpoint", p.client.Endpoint, "error", err)
 		return false, nil
@@ -34,7 +36,7 @@ func (p *ironicProvisioner) checkIronicConductor() (ready bool, err error) {
 	}
 
 	driverCount := 0
-	pager.EachPage(func(page pagination.Page) (bool, error) {
+	pager.EachPage(p.ctx, func(_ context.Context, page pagination.Page) (bool, error) {
 		actual, driverErr := drivers.ExtractDrivers(page)
 		if driverErr != nil {
 			return false, driverErr
diff --git a/pkg/provisioner/ironic/factory.go b/pkg/provisioner/ironic/factory.go
index 8189e1e4..65c6e4ad 100644
--- a/pkg/provisioner/ironic/factory.go
+++ b/pkg/provisioner/ironic/factory.go
@@ -10,7 +10,7 @@ import (
 	"strings"
 
 	"github.com/go-logr/logr"
-	"github.com/gophercloud/gophercloud"
+	"github.com/gophercloud/gophercloud/v2"
 
 	"github.com/metal3-io/baremetal-operator/pkg/provisioner"
 	"github.com/metal3-io/baremetal-operator/pkg/provisioner/ironic/clients"
diff --git a/pkg/provisioner/ironic/hardwaredetails/hardwaredetails.go b/pkg/provisioner/ironic/hardwaredetails/hardwaredetails.go
index c1821977..0445ee51 100644
--- a/pkg/provisioner/ironic/hardwaredetails/hardwaredetails.go
+++ b/pkg/provisioner/ironic/hardwaredetails/hardwaredetails.go
@@ -7,9 +7,9 @@ import (
 	"strings"
 
 	"github.com/go-logr/logr"
-	"github.com/gophercloud/gophercloud/openstack/baremetal/inventory"
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
-	"github.com/gophercloud/gophercloud/openstack/baremetalintrospection/v1/introspection"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/inventory"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetalintrospection/v1/introspection"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
 )
diff --git a/pkg/provisioner/ironic/ironic.go b/pkg/provisioner/ironic/ironic.go
index d1160fdb..6e600f04 100644
--- a/pkg/provisioner/ironic/ironic.go
+++ b/pkg/provisioner/ironic/ironic.go
@@ -13,10 +13,10 @@ import (
 	"github.com/pkg/errors"
 	"golang.org/x/exp/slices"
 
-	"github.com/gophercloud/gophercloud"
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/drivers"
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/ports"
+	"github.com/gophercloud/gophercloud/v2"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/drivers"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/ports"
 
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
@@ -127,7 +127,7 @@ func (p *ironicProvisioner) validateNode(ironicNode *nodes.Node) (errorMessage s
 	var validationErrors []string
 
 	p.log.Info("validating node settings in ironic")
-	validateResult, err := nodes.Validate(p.client, ironicNode.UUID).Extract()
+	validateResult, err := nodes.Validate(p.ctx, p.client, ironicNode.UUID).Extract()
 	if err != nil {
 		return "", err // do not wrap error so we can check type in caller
 	}
@@ -161,7 +161,7 @@ func (p *ironicProvisioner) listAllPorts(address string) ([]ports.Port, error) {
 
 	pager := ports.List(p.client, opts)
 
-	allPages, err := pager.AllPages()
+	allPages, err := pager.AllPages(p.ctx)
 
 	if err != nil {
 		return allPorts, err
@@ -175,7 +175,7 @@ func (p *ironicProvisioner) getNode() (*nodes.Node, error) {
 		return nil, provisioner.ErrNeedsRegistration
 	}
 
-	ironicNode, err := nodes.Get(p.client, p.nodeID).Extract()
+	ironicNode, err := nodes.Get(p.ctx, p.client, p.nodeID).Extract()
 	switch err.(type) {
 	case nil:
 		p.debugLog.Info("found existing node by ID")
@@ -199,7 +199,7 @@ func (p *ironicProvisioner) nodeHasAssignedPort(ironicNode *nodes.Node) (bool, e
 
 	pager := ports.List(p.client, opts)
 
-	allPages, err := pager.AllPages()
+	allPages, err := pager.AllPages(p.ctx)
 	if err != nil {
 		return false, errors.Wrap(err, "failed to page over list of ports")
 	}
@@ -250,7 +250,7 @@ func (p *ironicProvisioner) findExistingHost(bootMACAddress string) (ironicNode
 
 	for _, nodeName := range nodeSearchList {
 		p.debugLog.Info("looking for existing node by name", "name", nodeName)
-		ironicNode, err = nodes.Get(p.client, nodeName).Extract()
+		ironicNode, err = nodes.Get(p.ctx, p.client, nodeName).Extract()
 		switch err.(type) {
 		case nil:
 			p.debugLog.Info("found existing node by name", "name", nodeName, "node", ironicNode.UUID)
@@ -275,7 +275,7 @@ func (p *ironicProvisioner) findExistingHost(bootMACAddress string) (ironicNode
 
 	if len(allPorts) > 0 {
 		nodeUUID := allPorts[0].NodeUUID
-		ironicNode, err = nodes.Get(p.client, nodeUUID).Extract()
+		ironicNode, err = nodes.Get(p.ctx, p.client, nodeUUID).Extract()
 		switch err.(type) {
 		case nil:
 			p.debugLog.Info("found existing node by MAC", "MAC", bootMACAddress, "node", ironicNode.UUID, "name", ironicNode.Name)
@@ -308,6 +308,7 @@ func (p *ironicProvisioner) createPXEEnabledNodePort(uuid, macAddress string) er
 	enable := true
 
 	_, err := ports.Create(
+		p.ctx,
 		p.client,
 		ports.CreateOpts{
 			NodeUUID:   uuid,
@@ -322,7 +323,7 @@ func (p *ironicProvisioner) createPXEEnabledNodePort(uuid, macAddress string) er
 }
 
 func (p *ironicProvisioner) getInspectInterface(bmcAccess bmc.AccessDetails) (string, error) {
-	driver, err := drivers.GetDriverDetails(p.client, bmcAccess.Driver()).Extract()
+	driver, err := drivers.GetDriverDetails(p.ctx, p.client, bmcAccess.Driver()).Extract()
 	if err != nil {
 		return "", fmt.Errorf("cannot load information about driver %s: %w", bmcAccess.Driver(), err)
 	}
@@ -413,7 +414,7 @@ func (p *ironicProvisioner) ValidateManagementAccess(data provisioner.Management
 			nodeCreateOpts.FirmwareInterface = bmcAccess.FirmwareInterface()
 		}
 
-		ironicNode, err = nodes.Create(p.client, nodeCreateOpts).Extract()
+		ironicNode, err = nodes.Create(p.ctx, p.client, nodeCreateOpts).Extract()
 		switch err.(type) {
 		case nil:
 			p.publisher("Registered", "Registered new host")
@@ -762,7 +763,7 @@ func (p *ironicProvisioner) tryUpdateNode(ironicNode *nodes.Node, updater *nodeU
 	}
 
 	p.log.Info("updating node settings in ironic", "updateCount", len(updater.Updates))
-	updatedNode, err = nodes.Update(p.client, ironicNode.UUID, updater.Updates).Extract()
+	updatedNode, err = nodes.Update(p.ctx, p.client, ironicNode.UUID, updater.Updates).Extract()
 	switch err.(type) {
 	case nil:
 		success = true
@@ -795,7 +796,7 @@ func (p *ironicProvisioner) tryChangeNodeProvisionState(ironicNode *nodes.Node,
 		return
 	}
 
-	changeResult := nodes.ChangeProvisionState(p.client, ironicNode.UUID, opts)
+	changeResult := nodes.ChangeProvisionState(p.ctx, p.client, ironicNode.UUID, opts)
 	switch changeResult.Err.(type) {
 	case nil:
 		success = true
@@ -912,7 +913,7 @@ func (p *ironicProvisioner) InspectHardware(data provisioner.InspectData, restar
 	}
 
 	p.log.Info("getting hardware details from inspection")
-	response := nodes.GetInventory(p.client, ironicNode.UUID)
+	response := nodes.GetInventory(p.ctx, p.client, ironicNode.UUID)
 	introData, err := response.Extract()
 	if err != nil {
 		if _, isNotFound := err.(gophercloud.ErrDefault404); isNotFound {
@@ -1117,9 +1118,9 @@ func (p *ironicProvisioner) GetFirmwareSettings(includeSchema bool) (settings me
 	var biosListErr error
 	if includeSchema {
 		opts := nodes.ListBIOSSettingsOpts{Detail: true}
-		settingsList, biosListErr = nodes.ListBIOSSettings(p.client, ironicNode.UUID, opts).Extract()
+		settingsList, biosListErr = nodes.ListBIOSSettings(p.ctx, p.client, ironicNode.UUID, opts).Extract()
 	} else {
-		settingsList, biosListErr = nodes.ListBIOSSettings(p.client, ironicNode.UUID, nil).Extract()
+		settingsList, biosListErr = nodes.ListBIOSSettings(p.ctx, p.client, ironicNode.UUID, nil).Extract()
 	}
 	if biosListErr != nil {
 		return nil, nil, errors.Wrap(biosListErr,
@@ -1704,9 +1705,9 @@ func (p *ironicProvisioner) Provision(data provisioner.ProvisionData, forceReboo
 func (p *ironicProvisioner) setMaintenanceFlag(ironicNode *nodes.Node, value bool, reason string) (result provisioner.Result, err error) {
 	p.log.Info("updating maintenance in ironic", "newValue", value, "reason", reason)
 	if value {
-		err = nodes.SetMaintenance(p.client, ironicNode.UUID, nodes.MaintenanceOpts{Reason: reason}).ExtractErr()
+		err = nodes.SetMaintenance(p.ctx, p.client, ironicNode.UUID, nodes.MaintenanceOpts{Reason: reason}).ExtractErr()
 	} else {
-		err = nodes.UnsetMaintenance(p.client, ironicNode.UUID).ExtractErr()
+		err = nodes.UnsetMaintenance(p.ctx, p.client, ironicNode.UUID).ExtractErr()
 	}
 
 	switch err.(type) {
@@ -1873,7 +1874,7 @@ func (p *ironicProvisioner) Delete() (result provisioner.Result, err error) {
 	}
 
 	p.log.Info("host ready to be removed")
-	err = nodes.Delete(p.client, ironicNode.UUID).ExtractErr()
+	err = nodes.Delete(p.ctx, p.client, ironicNode.UUID).ExtractErr()
 	switch err.(type) {
 	case nil:
 		p.log.Info("removed")
@@ -1932,6 +1933,7 @@ func (p *ironicProvisioner) changePower(ironicNode *nodes.Node, target nodes.Tar
 	}
 
 	changeResult := nodes.ChangePowerState(
+		p.ctx,
 		p.client,
 		ironicNode.UUID,
 		powerStateOpts)
@@ -2061,7 +2063,7 @@ func (p *ironicProvisioner) loadBusyHosts() (hosts map[string]struct{}, err erro
 		Fields: []string{"uuid,name,provision_state,boot_interface"},
 	})
 
-	page, err := pager.AllPages()
+	page, err := pager.AllPages(p.ctx)
 	if err != nil {
 		return nil, err
 	}
@@ -2090,6 +2092,7 @@ func (p *ironicProvisioner) loadBusyHosts() (hosts map[string]struct{}, err erro
 
 func (p *ironicProvisioner) AddBMCEventSubscriptionForNode(subscription *metal3api.BMCEventSubscription, httpHeaders provisioner.HTTPHeaders) (result provisioner.Result, err error) {
 	newSubscription, err := nodes.CreateSubscription(
+		p.ctx,
 		p.client,
 		p.nodeID,
 		nodes.CallVendorPassthruOpts{
@@ -2115,7 +2118,7 @@ func (p *ironicProvisioner) RemoveBMCEventSubscriptionForNode(subscription metal
 	opts := nodes.DeleteSubscriptionOpts{
 		Id: subscription.Status.SubscriptionID,
 	}
-	err = nodes.DeleteSubscription(p.client, p.nodeID, method, opts).ExtractErr()
+	err = nodes.DeleteSubscription(p.ctx, p.client, p.nodeID, method, opts).ExtractErr()
 
 	if err != nil {
 		return provisioner.Result{RequeueAfter: subscriptionRequeueDelay}, err
diff --git a/pkg/provisioner/ironic/raid.go b/pkg/provisioner/ironic/raid.go
index 03718eb5..9e56ba63 100644
--- a/pkg/provisioner/ironic/raid.go
+++ b/pkg/provisioner/ironic/raid.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"reflect"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"github.com/pkg/errors"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
@@ -52,6 +52,7 @@ func setTargetRAIDCfg(p *ironicProvisioner, raidInterface string, ironicNode *no
 
 	// Set target for RAID configuration steps
 	err = nodes.SetRAIDConfig(
+		p.ctx,
 		p.client,
 		ironicNode.UUID,
 		nodes.RAIDConfigOpts{LogicalDisks: logicalDisks},
diff --git a/pkg/provisioner/ironic/update_opts.go b/pkg/provisioner/ironic/update_opts.go
index 99e3c89f..39c1cb2f 100644
--- a/pkg/provisioner/ironic/update_opts.go
+++ b/pkg/provisioner/ironic/update_opts.go
@@ -7,7 +7,7 @@ import (
 
 	"github.com/go-logr/logr"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 )
 
 type optionsData map[string]interface{}


Test patch:
diff --git a/hack/e2e/ensure_go.sh b/hack/e2e/ensure_go.sh
index c37e4309..a7eaa83f 100755
--- a/hack/e2e/ensure_go.sh
+++ b/hack/e2e/ensure_go.sh
@@ -2,7 +2,7 @@
 
 set -eux
 
-MINIMUM_GO_VERSION=go1.20.12
+MINIMUM_GO_VERSION=go1.21.7
 
 # Ensure the go tool exists and is a viable version, or installs it
 verify_go_version()
diff --git a/pkg/provisioner/ironic/adopt_test.go b/pkg/provisioner/ironic/adopt_test.go
index 9040cdc5..0ea0478f 100644
--- a/pkg/provisioner/ironic/adopt_test.go
+++ b/pkg/provisioner/ironic/adopt_test.go
@@ -4,7 +4,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"github.com/stretchr/testify/assert"
 
 	"github.com/metal3-io/baremetal-operator/pkg/hardwareutils/bmc"
diff --git a/pkg/provisioner/ironic/capabilities_test.go b/pkg/provisioner/ironic/capabilities_test.go
index d651bb86..e4688293 100644
--- a/pkg/provisioner/ironic/capabilities_test.go
+++ b/pkg/provisioner/ironic/capabilities_test.go
@@ -3,7 +3,7 @@ package ironic
 import (
 	"testing"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"github.com/stretchr/testify/assert"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
diff --git a/pkg/provisioner/ironic/configdrive_test.go b/pkg/provisioner/ironic/configdrive_test.go
index a50f09a8..c2b69e8f 100644
--- a/pkg/provisioner/ironic/configdrive_test.go
+++ b/pkg/provisioner/ironic/configdrive_test.go
@@ -3,7 +3,7 @@ package ironic
 import (
 	"testing"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"github.com/stretchr/testify/assert"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
diff --git a/pkg/provisioner/ironic/delete_test.go b/pkg/provisioner/ironic/delete_test.go
index 20345f70..76d14e06 100644
--- a/pkg/provisioner/ironic/delete_test.go
+++ b/pkg/provisioner/ironic/delete_test.go
@@ -5,7 +5,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"github.com/stretchr/testify/assert"
 
 	"github.com/metal3-io/baremetal-operator/pkg/hardwareutils/bmc"
diff --git a/pkg/provisioner/ironic/findhost_test.go b/pkg/provisioner/ironic/findhost_test.go
index 08c1eb63..01053891 100644
--- a/pkg/provisioner/ironic/findhost_test.go
+++ b/pkg/provisioner/ironic/findhost_test.go
@@ -3,7 +3,7 @@ package ironic
 import (
 	"testing"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 
 	"github.com/metal3-io/baremetal-operator/pkg/hardwareutils/bmc"
 	"github.com/metal3-io/baremetal-operator/pkg/provisioner/ironic/clients"
diff --git a/pkg/provisioner/ironic/hardwaredetails/hardwaredetails_test.go b/pkg/provisioner/ironic/hardwaredetails/hardwaredetails_test.go
index cba34fc5..f78e5532 100644
--- a/pkg/provisioner/ironic/hardwaredetails/hardwaredetails_test.go
+++ b/pkg/provisioner/ironic/hardwaredetails/hardwaredetails_test.go
@@ -4,8 +4,8 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/inventory"
-	"github.com/gophercloud/gophercloud/openstack/baremetalintrospection/v1/introspection"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/inventory"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetalintrospection/v1/introspection"
 	"github.com/stretchr/testify/assert"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
diff --git a/pkg/provisioner/ironic/inspecthardware_test.go b/pkg/provisioner/ironic/inspecthardware_test.go
index 44f1fb2d..32d4bd0a 100644
--- a/pkg/provisioner/ironic/inspecthardware_test.go
+++ b/pkg/provisioner/ironic/inspecthardware_test.go
@@ -5,8 +5,8 @@ import (
 	"testing"
 	"time"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/inventory"
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/inventory"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"github.com/stretchr/testify/assert"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
diff --git a/pkg/provisioner/ironic/power_test.go b/pkg/provisioner/ironic/power_test.go
index 7fd1ccd5..518e35cf 100644
--- a/pkg/provisioner/ironic/power_test.go
+++ b/pkg/provisioner/ironic/power_test.go
@@ -6,7 +6,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"github.com/stretchr/testify/assert"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
diff --git a/pkg/provisioner/ironic/prepare_test.go b/pkg/provisioner/ironic/prepare_test.go
index ca24f9ea..b5492823 100644
--- a/pkg/provisioner/ironic/prepare_test.go
+++ b/pkg/provisioner/ironic/prepare_test.go
@@ -5,7 +5,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"github.com/stretchr/testify/assert"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
diff --git a/pkg/provisioner/ironic/provision_test.go b/pkg/provisioner/ironic/provision_test.go
index 291e83af..cbb39289 100644
--- a/pkg/provisioner/ironic/provision_test.go
+++ b/pkg/provisioner/ironic/provision_test.go
@@ -5,7 +5,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"github.com/stretchr/testify/assert"
 	"k8s.io/apimachinery/pkg/util/intstr"
 
diff --git a/pkg/provisioner/ironic/provisioncapacity_test.go b/pkg/provisioner/ironic/provisioncapacity_test.go
index a571a5ee..e0882e2f 100644
--- a/pkg/provisioner/ironic/provisioncapacity_test.go
+++ b/pkg/provisioner/ironic/provisioncapacity_test.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"testing"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"github.com/stretchr/testify/assert"
 
 	"github.com/metal3-io/baremetal-operator/pkg/hardwareutils/bmc"
diff --git a/pkg/provisioner/ironic/raid_test.go b/pkg/provisioner/ironic/raid_test.go
index fc10b6ab..da8d09b5 100644
--- a/pkg/provisioner/ironic/raid_test.go
+++ b/pkg/provisioner/ironic/raid_test.go
@@ -5,7 +5,7 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"github.com/stretchr/testify/assert"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
diff --git a/pkg/provisioner/ironic/testserver/ironic.go b/pkg/provisioner/ironic/testserver/ironic.go
index da1f4650..be42cd54 100644
--- a/pkg/provisioner/ironic/testserver/ironic.go
+++ b/pkg/provisioner/ironic/testserver/ironic.go
@@ -8,8 +8,8 @@ import (
 	"net/url"
 	"testing"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/ports"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/ports"
 )
 
 // IronicMock is a test server that implements Ironic's semantics.
diff --git a/pkg/provisioner/ironic/testserver/ironic_test.go b/pkg/provisioner/ironic/testserver/ironic_test.go
index a97728fe..8dc1a4f2 100644
--- a/pkg/provisioner/ironic/testserver/ironic_test.go
+++ b/pkg/provisioner/ironic/testserver/ironic_test.go
@@ -4,7 +4,7 @@ import (
 	"net/http"
 	"testing"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 )
 
 func TestIronicDatabaseClearing(t *testing.T) {
diff --git a/pkg/provisioner/ironic/updatehardwarestate_test.go b/pkg/provisioner/ironic/updatehardwarestate_test.go
index dcab093d..b3c0e03d 100644
--- a/pkg/provisioner/ironic/updatehardwarestate_test.go
+++ b/pkg/provisioner/ironic/updatehardwarestate_test.go
@@ -4,7 +4,7 @@ import (
 	"net/http"
 	"testing"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	"github.com/stretchr/testify/assert"
 
 	"github.com/metal3-io/baremetal-operator/pkg/hardwareutils/bmc"
diff --git a/pkg/provisioner/ironic/updateopts_test.go b/pkg/provisioner/ironic/updateopts_test.go
index 96c41720..b3f8828e 100644
--- a/pkg/provisioner/ironic/updateopts_test.go
+++ b/pkg/provisioner/ironic/updateopts_test.go
@@ -8,7 +8,7 @@ import (
 	"github.com/pkg/errors"
 	"github.com/stretchr/testify/assert"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/utils/pointer"
 	logf "sigs.k8s.io/controller-runtime/pkg/log"
diff --git a/pkg/provisioner/ironic/validatemanagementaccess_test.go b/pkg/provisioner/ironic/validatemanagementaccess_test.go
index 1a4d3bc3..4121808d 100644
--- a/pkg/provisioner/ironic/validatemanagementaccess_test.go
+++ b/pkg/provisioner/ironic/validatemanagementaccess_test.go
@@ -5,8 +5,8 @@ import (
 	"net/http"
 	"testing"
 
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
-	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/ports"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/nodes"
+	"github.com/gophercloud/gophercloud/v2/openstack/baremetal/v1/ports"
 	"github.com/stretchr/testify/assert"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"