func (m Action) CreateUser(ctx context.Context) error {
	timer := prometheus.NewTimer(metrics.ActionDuration.With(prometheus.Labels{"service": "bmc", "action": "create_user"}))
	defer timer.ObserveDuration()
	host, user, password, err := m.ParseAuth(m.CreateUserRequest.Authn)
	if err != nil {
		return err
	}
	creds := m.CreateUserRequest.GetUserCreds()
	status := fmt.Sprintf("updating user %q", creds.GetUsername())
	m.SendStatusMessage(status)
	actions, err := m.setupConnection(ctx, &bmclibUserManagement{user: user, password: password, host: host, log: m.Log, creds: creds})
	if err != nil {
		m.SendStatusMessage("connection setup failed")
		return err
	}
	err = oob.CreateUser(ctx, actions)
	if err != nil {
		m.SendStatusMessage(fmt.Sprintf("error %s: %v", status, err))
		m.Log.Info(fmt.Sprintf("error %s: %v", status, err))
		return err
	}
	m.SendStatusMessage(status + " complete")
	return nil
}
CreateUser functionality for machines.
package bmc
import (
	"context"
	"fmt"
	"github.com/bmc-toolbox/bmclib"
	"github.com/bmc-toolbox/bmclib/bmc"
	"github.com/go-logr/logr"
	"github.com/prometheus/client_golang/prometheus"
	v1 "github.com/tinkerbell/pbnj/api/v1"
	common "github.com/tinkerbell/pbnj/grpc/oob"
	"github.com/tinkerbell/pbnj/pkg/metrics"
	"github.com/tinkerbell/pbnj/pkg/oob"
	"github.com/tinkerbell/pbnj/pkg/repository"
)
type Action struct {
	common.Accessory
	CreateUserRequest *v1.CreateUserRequest
	DeleteUserRequest *v1.DeleteUserRequest
	UpdateUserRequest *v1.UpdateUserRequest
	ResetBMCRequest   *v1.ResetRequest
}
type Option func(a *Action) error
func WithLogger(l logr.Logger) Option {
	return func(a *Action) error {
		a.Log = l
		return nil
	}
}
func WithStatusMessage(s chan string) Option {
	return func(a *Action) error {
		a.StatusMessages = s
		return nil
	}
}
func WithCreateUserRequest(in *v1.CreateUserRequest) Option {
	return func(a *Action) error {
		a.CreateUserRequest = in
		return nil
	}
}
func WithDeleteUserRequest(in *v1.DeleteUserRequest) Option {
	return func(a *Action) error {
		a.DeleteUserRequest = in
		return nil
	}
}
func WithUpdateUserRequest(in *v1.UpdateUserRequest) Option {
	return func(a *Action) error {
		a.UpdateUserRequest = in
		return nil
	}
}
func WithResetRequest(in *v1.ResetRequest) Option {
	return func(a *Action) error {
		a.ResetBMCRequest = in
		return nil
	}
}
func NewBMC(opts ...Option) (oob.BMC, error) {
	a := &Action{}
	for _, opt := range opts {
		err := opt(a)
		if err != nil {
			return nil, err
		}
	}
	return a, nil
}
func NewBMCResetter(opts ...Option) (*Action, error) {
	a := &Action{}
	for _, opt := range opts {
		err := opt(a)
		if err != nil {
			return nil, err
		}
	}
	return a, nil
}
func (m Action) setupConnection(ctx context.Context, u *bmclibUserManagement) ([]oob.BMC, error) {
	connections := map[string]interface{}{"bmclib": u}
	m.SendStatusMessage("connecting to BMC")
	successfulConnections, err := common.EstablishConnections(ctx, connections)
	if err != nil {
		m.SendStatusMessage("connecting to BMC failed")
		return nil, err
	}
	m.SendStatusMessage("connected to BMC")
	var actions []oob.BMC
	for _, elem := range successfulConnections {
		conn := connections[elem]
		if r, ok := conn.(common.Connection); ok {
			defer r.Close(ctx)  
		}
		if r, ok := conn.(oob.BMC); ok {
			actions = append(actions, r)
		}
	}
	return actions, nil
}