func (m *IronicMock) BIOSDetailSettings(nodeUUID string) *IronicMock {
	iTrue := true
	iFalse := false
	minLength := 0
	maxLength := 16
	lowerBound := 0
	upperBound := 20
	settings := []nodes.BIOSSetting{
		{
			Name:            "L2Cache",
			Value:           "10x256 KB",
			AttributeType:   "String",
			AllowableValues: []string{},
			LowerBound:      nil,
			UpperBound:      nil,
			MinLength:       &minLength,
			MaxLength:       &maxLength,
			ReadOnly:        &iTrue,
			ResetRequired:   nil,
			Unique:          nil,
		},
		{
			Name:            "NumCores",
			Value:           "10",
			AttributeType:   "Integer",
			AllowableValues: []string{},
			LowerBound:      &lowerBound,
			UpperBound:      &upperBound,
			MinLength:       nil,
			MaxLength:       nil,
			ReadOnly:        &iTrue,
			ResetRequired:   nil,
			Unique:          nil,
		},
		{
			Name:            "ProcVirtualization",
			Value:           "Enabled",
			AttributeType:   "Enumeration",
			AllowableValues: []string{"Enabled", "Disabled"},
			LowerBound:      nil,
			UpperBound:      nil,
			MinLength:       nil,
			MaxLength:       nil,
			ReadOnly:        &iFalse,
			ResetRequired:   nil,
			Unique:          nil,
		},
	}
	resp := struct {
		Settings []nodes.BIOSSetting `json:"bios"`
	}{
		Settings: settings,
	}
	m.ResponseJSON(m.buildURL("/v1/nodes/"+nodeUUID+"/bios", http.MethodGet), resp)
	m.AddDefaultResponseJSON("/v1/nodes/"+nodeUUID, "", http.StatusOK, nodes.Node{
		UUID: nodeUUID,
	})
	return m
}
BIOSDetailSettings configure the server with a valid response for /v1/nodes/<node>/bios?detail=True
package testserver
import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"testing"
	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/nodes"
	"github.com/gophercloud/gophercloud/openstack/baremetal/v1/ports"
)
type IronicMock struct {
	*MockServer
	CreatedNodes int
}
func NewIronic(t *testing.T) *IronicMock {
	return &IronicMock{
		MockServer:   New(t, "ironic"),
		CreatedNodes: 0,
	}
}
func (m *IronicMock) WithDefaultResponses() *IronicMock {
	m.AddDefaultResponseJSON("/v1/nodes/{id}", "", http.StatusOK, nodes.Node{
		UUID: "{id}",
	})
	m.AddDefaultResponse("/v1/nodes/{id}/states/provision", "", http.StatusAccepted, "{}")
	m.AddDefaultResponse("/v1/nodes/{id}/states/power", "", http.StatusAccepted, "{}")
	m.AddDefaultResponse("/v1/nodes/{id}/states/raid", "", http.StatusNoContent, "{}")
	m.AddDefaultResponse("/v1/nodes/{id}/validate", "", http.StatusOK, "{}")
	m.Ready()
	return m
}
func (m *IronicMock) Endpoint() string {
	if m == nil {
		return "https://ironic.test/v1/"
	}
	return m.MockServer.Endpoint()
}
func (m *IronicMock) Ready() *IronicMock {
	m.ResponseWithCode("/v1", "{}", http.StatusOK)
	return m
}
func (m *IronicMock) NotReady(errorCode int) *IronicMock {
	m.ErrorResponse("/v1", errorCode)
	return m
}
func (m *IronicMock) WithDrivers() *IronicMock {
	m.ResponseWithCode("/v1/drivers", `
	{
		"drivers": [{
			"hosts": [
			  "master-2.ostest.test.metalkube.org"
			],
			"links": [
			  {
				"href": "http://[fd00:1101::3]:6385/v1/drivers/fake-hardware",
				"rel": "self"
			  },
			  {
				"href": "http://[fd00:1101::3]:6385/drivers/fake-hardware",
				"rel": "bookmark"
			  }
			],
			"name": "fake-hardware"
		}]
	}
	`, http.StatusOK)
	return m
}
func (m *IronicMock) buildURL(url string, method string) string {
	return fmt.Sprintf("%s:%s", url, method)
}
func (m *IronicMock) Delete(id string) *IronicMock {
	m.ResponseWithCode(m.buildURL("/v1/nodes/"+id, http.MethodDelete), "", http.StatusAccepted)
	return m
}
func (m *IronicMock) DeleteError(id string, errorCode int) *IronicMock {
	m.ResponseWithCode(m.buildURL("/v1/nodes/"+id, http.MethodDelete), "", errorCode)
	return m
}
func (m *IronicMock) Node(node nodes.Node) *IronicMock {
	if node.UUID != "" {
		m.ResponseJSON(m.buildURL("/v1/nodes/"+node.UUID, http.MethodGet), node)
	}
	if node.Name != "" {
		m.ResponseJSON(m.buildURL("/v1/nodes/"+node.Name, http.MethodGet), node)
	}
	return m
}
func (m *IronicMock) NodeUpdateError(id string, errorCode int) *IronicMock {
	m.ResponseWithCode(m.buildURL("/v1/nodes/"+id, http.MethodPatch), "", errorCode)
	return m
}
func (m *IronicMock) NodeUpdate(node nodes.Node) *IronicMock {
	if node.UUID != "" {
		m.ResponseJSON(m.buildURL("/v1/nodes/"+node.UUID, http.MethodPatch), node)
	}
	if node.Name != "" {
		m.ResponseJSON(m.buildURL("/v1/nodes/"+node.Name, http.MethodPatch), node)
	}
	return m
}
func (m *IronicMock) GetLastNodeUpdateRequestFor(id string) (updates []nodes.UpdateOperation) {
	if bodyRaw, ok := m.GetLastRequestFor("/v1/nodes/"+id, http.MethodPatch); ok {
		json.Unmarshal([]byte(bodyRaw), &updates)
	}
	return
}
func (m *IronicMock) withNodeStatesProvision(nodeUUID string, method string) *IronicMock {
	m.ResponseWithCode(m.buildURL("/v1/nodes/"+nodeUUID+"/states/provision", method), "{}", http.StatusAccepted)
	return m
}
func (m *IronicMock) WithNodeStatesProvision(nodeUUID string) *IronicMock {
	return m.withNodeStatesProvision(nodeUUID, http.MethodGet)
}
func (m *IronicMock) WithNodeStatesProvisionUpdate(nodeUUID string) *IronicMock {
	return m.withNodeStatesProvision(nodeUUID, http.MethodPut)
}
func (m *IronicMock) NoNode(name string) *IronicMock {
	return m.NodeError(name, http.StatusNotFound)
}
func (m *IronicMock) NodeError(name string, errorCode int) *IronicMock {
	m.ErrorResponse(fmt.Sprintf("/v1/nodes/%s", name), errorCode)
	return m
}
type NodeCreateCallback func(node nodes.Node)
func (m *IronicMock) CreateNodes(callback NodeCreateCallback) *IronicMock {
	m.Handler("/v1/nodes", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			http.Error(w, fmt.Sprintf("%s not handled for %s", r.Method, r.URL),
				http.StatusNotImplemented)
		}
		bodyRaw, err := io.ReadAll(r.Body)
		if err != nil {
			m.logRequest(r, fmt.Sprintf("ERROR: %s", err))
			http.Error(w, fmt.Sprintf("%s", err), http.StatusInternalServerError)
			return
		}
		body := string(bodyRaw)
		m.t.Logf("%s: create nodes request %v", m.name, body)
		node := nodes.Node{}
		err = json.Unmarshal(bodyRaw, &node)
		if err != nil {
			m.logRequest(r, fmt.Sprintf("ERROR: %s", err))
			http.Error(w, fmt.Sprintf("%s", err), http.StatusInternalServerError)
			return
		}
		node.UUID = fmt.Sprintf("node-%d", m.CreatedNodes)
		m.t.Logf("%s: uuid %s", m.name, node.UUID)
		m.CreatedNodes++
		callback(node)
		m.SendJSONResponse(node, http.StatusCreated, w, r)
	})
	return m
}
func (m *IronicMock) withNodeStatesPower(nodeUUID string, code int, method string) *IronicMock {
	m.ResponseWithCode(m.buildURL("/v1/nodes/"+nodeUUID+"/states/power", method), "{}", code)
	return m
}
func (m *IronicMock) WithNodeStatesPower(nodeUUID string, code int) *IronicMock {
	return m.withNodeStatesPower(nodeUUID, code, http.MethodGet)
}
func (m *IronicMock) WithNodeStatesPowerUpdate(nodeUUID string, code int) *IronicMock {
	return m.withNodeStatesPower(nodeUUID, code, http.MethodPut)
}
func (m *IronicMock) WithNodeValidate(nodeUUID string) *IronicMock {
	m.ResponseWithCode("/v1/nodes/"+nodeUUID+"/validate", "{}", http.StatusOK)
	return m
}
func (m *IronicMock) Port(port ports.Port) *IronicMock {
	if port.NodeUUID == "" {
		m.MockServer.t.Error("When using withPort(), the port must include a NodeUUID.")
	}
	resp := map[string][]ports.Port{
		"ports": {port},
	}
	address := url.QueryEscape(port.Address)
	m.ResponseJSON(m.buildURL("/v1/nodes/"+port.NodeUUID+"/ports", http.MethodGet), resp)
	m.ResponseJSON(m.buildURL("/v1/ports", http.MethodGet), resp)
	m.ResponseJSON(m.buildURL("/v1/ports?address="+address, http.MethodGet), resp)
	m.ResponseJSON(m.buildURL("/v1/ports?address="+address+"&fields=node_uuid", http.MethodGet), resp)
	return m
}
func (m *IronicMock) Nodes(allNodes []nodes.Node) *IronicMock {
	resp := struct {
		Nodes []nodes.Node `json:"nodes"`
	}{
		Nodes: allNodes,
	}
	m.ResponseJSON(m.buildURL("/v1/nodes", http.MethodGet), resp)
	return m
}
func (m *IronicMock) ClearDatabase() {
	m.t.Log("clearing ironic database")
	for i, resp := range m.defaultResponses {
		if resp.method == "POST" {
			continue
		}
		m.defaultResponses[i].code = http.StatusNotFound
		m.defaultResponses[i].payload = ""
	}
	for url, methodMap := range m.responsesByMethod {
		for method := range methodMap {
			if method == "POST" {
				continue
			}
			m.responsesByMethod[url][method] = response{
				code:    http.StatusNotFound,
				payload: "",
			}
		}
	}
}
func (m *IronicMock) BIOSSettings(nodeUUID string) *IronicMock {
	settings := []nodes.BIOSSetting{
		{
			Name:  "L2Cache",
			Value: "10x256 KB",
		},
		{
			Name:  "NumCores",
			Value: "10",
		},
		{
			Name:  "ProcVirtualization",
			Value: "Enabled",
		},
	}
	resp := struct {
		Settings []nodes.BIOSSetting `json:"bios"`
	}{
		Settings: settings,
	}
	m.ResponseJSON(m.buildURL("/v1/nodes/"+nodeUUID+"/bios", http.MethodGet), resp)
	m.AddDefaultResponseJSON("/v1/nodes/"+nodeUUID, "", http.StatusOK, nodes.Node{
		UUID: nodeUUID,
	})
	return m
}