From 70c2f54b8d0d13761ed6307d2e190d05319ccd89 Mon Sep 17 00:00:00 2001 From: Jacob Weinstock Date: Wed, 20 Sep 2023 09:42:05 -0600 Subject: [PATCH] Update machine controller to implement provider opts: This makes the provider opts in the CRD operational via the bmclib client. Rename pkg; controllers -> controller: this is the preferred practive in Go. Added a requeue interval. Signed-off-by: Jacob Weinstock --- config/samples/hmac-secret1.yaml | 7 + config/samples/hmac-secret2.yaml | 7 + config/samples/machine_v1alpha1.yaml | 3 +- .../samples/machine_with_opts_v1alpha1.yaml | 25 +++ config/samples/task_v1alpha1.yaml | 1 - controller/client.go | 142 ++++++++++++++++ {controllers => controller}/helpers_test.go | 8 +- {controllers => controller}/job.go | 2 +- {controllers => controller}/job_test.go | 8 +- controller/kube.go | 55 ++++++ {controllers => controller}/machine.go | 156 ++++++++---------- {controllers => controller}/machine_test.go | 26 ++- {controllers => controller}/task.go | 10 +- {controllers => controller}/task_test.go | 6 +- controllers/client.go | 40 ----- go.mod | 25 +-- go.sum | 65 +++++--- main.go | 35 ++-- 18 files changed, 403 insertions(+), 218 deletions(-) create mode 100644 config/samples/hmac-secret1.yaml create mode 100644 config/samples/hmac-secret2.yaml create mode 100644 config/samples/machine_with_opts_v1alpha1.yaml create mode 100644 controller/client.go rename {controllers => controller}/helpers_test.go (90%) rename {controllers => controller}/job.go (99%) rename {controllers => controller}/job_test.go (96%) create mode 100644 controller/kube.go rename {controllers => controller}/machine.go (54%) rename {controllers => controller}/machine_test.go (82%) rename {controllers => controller}/task.go (97%) rename {controllers => controller}/task_test.go (97%) delete mode 100644 controllers/client.go diff --git a/config/samples/hmac-secret1.yaml b/config/samples/hmac-secret1.yaml new file mode 100644 index 0000000..1807278 --- /dev/null +++ b/config/samples/hmac-secret1.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: secret1 +type: Opaque +data: # echo -n 'superSecret1' | base64; + secret: c3VwZXJTZWNyZXQx \ No newline at end of file diff --git a/config/samples/hmac-secret2.yaml b/config/samples/hmac-secret2.yaml new file mode 100644 index 0000000..df39c91 --- /dev/null +++ b/config/samples/hmac-secret2.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: secret2 +type: Opaque +data: # echo -n 'superSecret2' | base64; + secret: c3VwZXJTZWNyZXQy \ No newline at end of file diff --git a/config/samples/machine_v1alpha1.yaml b/config/samples/machine_v1alpha1.yaml index eabbb22..dddb596 100644 --- a/config/samples/machine_v1alpha1.yaml +++ b/config/samples/machine_v1alpha1.yaml @@ -5,8 +5,9 @@ metadata: spec: connection: host: 127.0.0.1 - port: 623 authSecretRef: name: sample-machine-auth namespace: rufio-system insecureTLS: true + + diff --git a/config/samples/machine_with_opts_v1alpha1.yaml b/config/samples/machine_with_opts_v1alpha1.yaml new file mode 100644 index 0000000..cdd5235 --- /dev/null +++ b/config/samples/machine_with_opts_v1alpha1.yaml @@ -0,0 +1,25 @@ +apiVersion: bmc.tinkerbell.org/v1alpha1 +kind: Machine +metadata: + name: machine-sample-with-opts +spec: + connection: + host: 127.0.0.1 + insecureTLS: true + providerOptions: + rpc: + consumerURL: "https://example.com/rpc" + hmac: + secrets: + sha256: + - name: secret1 + namespace: default + - name: secret2 + namespace: default + sha512: + - name: secret1 + namespace: default + - name: secret2 + namespace: default + + diff --git a/config/samples/task_v1alpha1.yaml b/config/samples/task_v1alpha1.yaml index e0fa7a4..5c6f439 100644 --- a/config/samples/task_v1alpha1.yaml +++ b/config/samples/task_v1alpha1.yaml @@ -5,7 +5,6 @@ metadata: spec: connection: host: 127.0.0.1 - port: 623 authSecretRef: name: sample-machine-auth namespace: rufio-system diff --git a/controller/client.go b/controller/client.go new file mode 100644 index 0000000..d1a5ca8 --- /dev/null +++ b/controller/client.go @@ -0,0 +1,142 @@ +package controller + +import ( + "context" + "fmt" + "strconv" + "time" + + "dario.cat/mergo" + bmclib "github.com/bmc-toolbox/bmclib/v2" + "github.com/bmc-toolbox/bmclib/v2/providers/rpc" + "github.com/go-logr/logr" + "github.com/tinkerbell/rufio/api/v1alpha1" +) + +// ClientFunc defines a func that returns a bmclib.Client. +type ClientFunc func(ctx context.Context, log logr.Logger, hostIP, username, password string, opts *BMCOptions) (*bmclib.Client, error) + +// NewClientFunc returns a new BMCClientFactoryFunc. The timeout parameter determines the +// maximum time to probe for compatible interfaces. +func NewClientFunc(timeout time.Duration) ClientFunc { + // Initializes a bmclib client based on input host and credentials + // Establishes a connection with the bmc with client.Open + // Returns a bmclib.Client. + return func(ctx context.Context, log logr.Logger, hostIP, username, password string, opts *BMCOptions) (*bmclib.Client, error) { + o := opts.translate(hostIP) + log = log.WithValues("host", hostIP, "username", username) + o = append(o, bmclib.WithLogger(log)) + client := bmclib.NewClient(hostIP, username, password, o...) + + ctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + + // TODO (pokearu): Make an option + client.Registry.Drivers = client.Registry.PreferProtocol("redfish") + if err := client.Open(ctx); err != nil { + md := client.GetMetadata() + log.Info("Failed to open connection to BMC", "error", err, "providersAttempted", md.ProvidersAttempted, "successfulProvider", md.SuccessfulOpenConns) + + return nil, fmt.Errorf("failed to open connection to BMC: %w", err) + } + md := client.GetMetadata() + log.Info("Connected to BMC", "providersAttempted", md.ProvidersAttempted, "successfulProvider", md.SuccessfulOpenConns) + + return client, nil + } +} + +type BMCOptions struct { + *v1alpha1.ProviderOptions + rpcSecrets map[rpc.Algorithm][]string +} + +func (b BMCOptions) translate(host string) []bmclib.Option { + o := []bmclib.Option{} + + if b.ProviderOptions == nil { + return o + } + + // redfish options + if b.Redfish != nil { + if b.Redfish.Port != 0 { + o = append(o, bmclib.WithRedfishPort(strconv.Itoa(b.Redfish.Port))) + } + } + + // ipmitool options + if b.IPMITOOL != nil { + if b.IPMITOOL.Port != 0 { + o = append(o, bmclib.WithIpmitoolPort(strconv.Itoa(b.IPMITOOL.Port))) + } + if b.IPMITOOL.CipherSuite != "" { + o = append(o, bmclib.WithIpmitoolCipherSuite(b.IPMITOOL.CipherSuite)) + } + } + + // intelAmt options + if b.IntelAMT != nil { + amt := bmclib.WithIntelAMTPort(uint32(b.IntelAMT.Port)) + o = append(o, amt) + } + + // rpc options + if b.RPC != nil { + op := b.translateRPC(host) + o = append(o, bmclib.WithRPCOpt(op)) + } + + return o +} + +func (b BMCOptions) translateRPC(host string) rpc.Provider { + s := map[rpc.Algorithm][]string{} + if b.rpcSecrets != nil { + s = b.rpcSecrets + } + + defaults := rpc.Provider{ + Opts: rpc.Opts{ + Request: rpc.RequestOpts{ + TimestampHeader: "X-Rufio-Timestamp", + }, + Signature: rpc.SignatureOpts{ + HeaderName: "X-Rufio-Signature", + IncludedPayloadHeaders: []string{"X-Rufio-Timestamp"}, + }, + }, + } + o := rpc.Provider{ + ConsumerURL: b.RPC.ConsumerURL, + Host: host, + Opts: rpc.Opts{ + Request: rpc.RequestOpts{ + HTTPContentType: b.RPC.Request.HTTPContentType, + HTTPMethod: b.RPC.Request.HTTPMethod, + StaticHeaders: b.RPC.Request.StaticHeaders, + TimestampFormat: b.RPC.Request.TimestampFormat, + TimestampHeader: b.RPC.Request.TimestampHeader, + }, + Signature: rpc.SignatureOpts{ + HeaderName: b.RPC.Signature.HeaderName, + AppendAlgoToHeaderDisabled: b.RPC.Signature.AppendAlgoToHeaderDisabled, + IncludedPayloadHeaders: b.RPC.Signature.IncludedPayloadHeaders, + }, + HMAC: rpc.HMACOpts{ + PrefixSigDisabled: b.RPC.HMAC.PrefixSigDisabled, + Secrets: s, + }, + Experimental: rpc.Experimental{ + CustomRequestPayload: []byte(b.RPC.Experimental.CustomRequestPayload), + DotPath: b.RPC.Experimental.DotPath, + }, + }, + } + + _ = mergo.Merge(&o, &defaults, mergo.WithOverride, mergo.WithTransformers(&rpc.Provider{})) + + return o +} + +// func (r BMCOptions) diff --git a/controllers/helpers_test.go b/controller/helpers_test.go similarity index 90% rename from controllers/helpers_test.go rename to controller/helpers_test.go index d63a44c..2ca31c4 100644 --- a/controllers/helpers_test.go +++ b/controller/helpers_test.go @@ -1,4 +1,4 @@ -package controllers_test +package controller_test import ( "context" @@ -8,7 +8,7 @@ import ( "github.com/go-logr/logr" "github.com/jacobweinstock/registrar" "github.com/tinkerbell/rufio/api/v1alpha1" - "github.com/tinkerbell/rufio/controllers" + "github.com/tinkerbell/rufio/controller" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client/fake" @@ -95,8 +95,8 @@ func (t *testProvider) SetVirtualMedia(_ context.Context, _ string, _ string) (o } // newMockBMCClientFactoryFunc returns a new BMCClientFactoryFunc. -func newTestClient(provider *testProvider) controllers.ClientFunc { - return func(ctx context.Context, log logr.Logger, hostIP, port, username, password string) (*bmclib.Client, error) { +func newTestClient(provider *testProvider) controller.ClientFunc { + return func(ctx context.Context, log logr.Logger, hostIP, username, password string, opts *controller.BMCOptions) (*bmclib.Client, error) { reg := registrar.NewRegistry(registrar.WithLogger(log)) reg.Register(provider.Name(), provider.Protocol(), provider.Features(), nil, provider) cl := bmclib.NewClient(hostIP, username, password, bmclib.WithLogger(log), bmclib.WithRegistry(reg)) diff --git a/controllers/job.go b/controller/job.go similarity index 99% rename from controllers/job.go rename to controller/job.go index aab1076..a0c55c0 100644 --- a/controllers/job.go +++ b/controller/job.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package controllers +package controller import ( "context" diff --git a/controllers/job_test.go b/controller/job_test.go similarity index 96% rename from controllers/job_test.go rename to controller/job_test.go index 1313a4d..956e2e7 100644 --- a/controllers/job_test.go +++ b/controller/job_test.go @@ -1,4 +1,4 @@ -package controllers_test +package controller_test import ( "context" @@ -6,7 +6,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/tinkerbell/rufio/api/v1alpha1" - "github.com/tinkerbell/rufio/controllers" + "github.com/tinkerbell/rufio/controller" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -44,10 +44,10 @@ func TestJobReconcile(t *testing.T) { clnt := newClientBuilder(). WithObjects(tt.job, tt.machine, tt.secret). WithStatusSubresource(tt.job, tt.machine). - WithIndex(&v1alpha1.Task{}, ".metadata.controller", controllers.TaskOwnerIndexFunc). + WithIndex(&v1alpha1.Task{}, ".metadata.controller", controller.TaskOwnerIndexFunc). Build() - reconciler := controllers.NewJobReconciler(clnt) + reconciler := controller.NewJobReconciler(clnt) request := reconcile.Request{ NamespacedName: types.NamespacedName{ diff --git a/controller/kube.go b/controller/kube.go new file mode 100644 index 0000000..0d63b8c --- /dev/null +++ b/controller/kube.go @@ -0,0 +1,55 @@ +package controller + +import ( + "context" + "fmt" + "strings" + + "github.com/tinkerbell/rufio/api/v1alpha1" + v1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// resolveAuthSecretRef Gets the Secret from the SecretReference. +// Returns the username and password encoded in the Secret. +func resolveAuthSecretRef(ctx context.Context, c client.Client, secretRef v1.SecretReference) (string, string, error) { + secret := &v1.Secret{} + key := types.NamespacedName{Namespace: secretRef.Namespace, Name: secretRef.Name} + + if err := c.Get(ctx, key, secret); err != nil { + if apierrors.IsNotFound(err) { + return "", "", fmt.Errorf("secret %s not found: %w", key, err) + } + + return "", "", fmt.Errorf("failed to retrieve secret %s : %w", secretRef, err) + } + + username, ok := secret.Data["username"] + if !ok { + return "", "", fmt.Errorf("'username' required in Machine secret") + } + + password, ok := secret.Data["password"] + if !ok { + return "", "", fmt.Errorf("'password' required in Machine secret") + } + + return string(username), string(password), nil +} + +// toPowerState takes a raw BMC power state response and converts it to a v1alpha1.PowerState. +func toPowerState(state string) v1alpha1.PowerState { + // Normalize the response string for comparison. + state = strings.ToLower(state) + + switch { + case strings.Contains(state, "on"): + return v1alpha1.On + case strings.Contains(state, "off"): + return v1alpha1.Off + default: + return v1alpha1.Unknown + } +} diff --git a/controllers/machine.go b/controller/machine.go similarity index 54% rename from controllers/machine.go rename to controller/machine.go index 0493830..92602cd 100644 --- a/controllers/machine.go +++ b/controller/machine.go @@ -14,15 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package controllers +package controller import ( "context" "fmt" - "strconv" - "strings" + "time" bmclib "github.com/bmc-toolbox/bmclib/v2" + "github.com/bmc-toolbox/bmclib/v2/providers/rpc" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -37,49 +37,46 @@ import ( // MachineReconciler reconciles a Machine object. type MachineReconciler struct { - client client.Client - recorder record.EventRecorder - bmcClientFactory ClientFunc + client client.Client + recorder record.EventRecorder + bmcClient ClientFunc } const ( - EventGetPowerStateFailed = "GetPowerStateFailed" - EventSetPowerStateFailed = "SetPowerStateFailed" + eventGetPowerStateFailed = "GetPowerStateFailed" + // machineRequeueInterval is the interval at which the machine's power state is reconciled. + // This should only be used when the power state was successfully retrieved. + machineRequeueInterval = 3 * time.Minute ) // NewMachineReconciler returns a new MachineReconciler. func NewMachineReconciler(c client.Client, recorder record.EventRecorder, bmcClientFactory ClientFunc) *MachineReconciler { return &MachineReconciler{ - client: c, - recorder: recorder, - bmcClientFactory: bmcClientFactory, + client: c, + recorder: recorder, + bmcClient: bmcClientFactory, } } -// machineFieldReconciler defines a function to reconcile Machine spec field. -type machineFieldReconciler func(context.Context, *v1alpha1.Machine, *bmclib.Client) error - //+kubebuilder:rbac:groups=bmc.tinkerbell.org,resources=machines,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=bmc.tinkerbell.org,resources=machines/status,verbs=get;update;patch //+kubebuilder:rbac:groups=bmc.tinkerbell.org,resources=machines/finalizers,verbs=update //+kubebuilder:rbac:groups="",resources=secrets;,verbs=get;list;watch -// Reconcile ensures the state of a Machine. -// Gets the Machine object and uses the SecretReference to initialize a BMC Client. +// Reconcile reports on the state of a Machine. It does not change the state of the Machine in any way. // Updates the Power status and conditions accordingly. func (r *MachineReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - logger := ctrl.LoggerFrom(ctx).WithName("controllers/Machine").WithValues("Machine", req.NamespacedName) - logger.Info("Reconciling Machine") + logger := ctrl.LoggerFrom(ctx).WithName("controllers/Machine") + logger.Info("reconciling machine") // Fetch the Machine object machine := &v1alpha1.Machine{} - err := r.client.Get(ctx, req.NamespacedName, machine) - if err != nil { + if err := r.client.Get(ctx, req.NamespacedName, machine); err != nil { if apierrors.IsNotFound(err) { return ctrl.Result{}, nil } - logger.Error(err, "Failed to get Machine") + logger.Error(err, "failed to get Machine from KubeAPI") return ctrl.Result{}, err } @@ -100,19 +97,33 @@ func (r *MachineReconciler) doReconcile(ctx context.Context, bm *v1alpha1.Machin // Requeue if error fetching secret username, password, err := resolveAuthSecretRef(ctx, r.client, bm.Spec.Connection.AuthSecretRef) if err != nil { - return ctrl.Result{Requeue: true}, fmt.Errorf("resolving Machine %s/%s SecretReference: %w", bm.Namespace, bm.Name, err) + return ctrl.Result{}, fmt.Errorf("resolving Machine %s/%s SecretReference: %w", bm.Namespace, bm.Name, err) + } + + opts := &BMCOptions{} + if bm.Spec.Connection.ProviderOptions != nil && bm.Spec.Connection.ProviderOptions.RPC != nil { + opts.ProviderOptions = bm.Spec.Connection.ProviderOptions + if len(bm.Spec.Connection.ProviderOptions.RPC.HMAC.Secrets) > 0 { + se, err := retrieveHMACSecrets(ctx, r.client, bm.Spec.Connection.ProviderOptions.RPC.HMAC.Secrets) + if err != nil { + return ctrl.Result{}, fmt.Errorf("unable to get hmac secrets: %w", err) + } + opts.rpcSecrets = se + } } - // Initializing BMC Client - bmcClient, err := r.bmcClientFactory(ctx, logger, bm.Spec.Connection.Host, strconv.Itoa(bm.Spec.Connection.Port), username, password) + // Initializing BMC Client and Open the connection. + bmcClient, err := r.bmcClient(ctx, logger, bm.Spec.Connection.Host, username, password, opts) if err != nil { logger.Error(err, "BMC connection failed", "host", bm.Spec.Connection.Host) bm.SetCondition(v1alpha1.Contactable, v1alpha1.ConditionFalse, v1alpha1.WithMachineConditionMessage(err.Error())) + bm.Status.Power = v1alpha1.Unknown if patchErr := r.patchStatus(ctx, bm, bmPatch); patchErr != nil { return ctrl.Result{}, utilerrors.NewAggregate([]error{patchErr, err}) } - return ctrl.Result{}, err + // requeue as bmc connections can be transient. + return ctrl.Result{RequeueAfter: machineRequeueInterval}, nil } // Close BMC connection after reconciliation @@ -127,99 +138,72 @@ func (r *MachineReconciler) doReconcile(ctx context.Context, bm *v1alpha1.Machin logger.Info("BMC connection closed", "host", bm.Spec.Connection.Host, "successfulCloseConns", md.SuccessfulCloseConns, "providersAttempted", md.ProvidersAttempted, "successfulProvider", md.SuccessfulProvider) }() - // Setting condition Contactable to True. - bm.SetCondition(v1alpha1.Contactable, v1alpha1.ConditionTrue) - - // fieldReconcilers defines Machine spec field reconciler functions - fieldReconcilers := []machineFieldReconciler{ - r.reconcilePower, + contactable := v1alpha1.ConditionTrue + conditionMsg := v1alpha1.WithMachineConditionMessage("") + multiErr := []error{} + pErr := r.powerState(ctx, bm, bmcClient) + if pErr != nil { + logger.Error(pErr, "failed to get Machine power state", "host", bm.Spec.Connection.Host) + contactable = v1alpha1.ConditionFalse + conditionMsg = v1alpha1.WithMachineConditionMessage(pErr.Error()) + multiErr = append(multiErr, pErr) } - var aggErr utilerrors.Aggregate - for _, reconiler := range fieldReconcilers { - if err := reconiler(ctx, bm, bmcClient); err != nil { - logger.Error(err, "Failed to reconcile Machine", "host", bm.Spec.Connection.Host) - aggErr = utilerrors.NewAggregate([]error{err, aggErr}) - } - } + // Set condition. + bm.SetCondition(v1alpha1.Contactable, contactable, conditionMsg) // Patch the status after each reconciliation if err := r.patchStatus(ctx, bm, bmPatch); err != nil { - aggErr = utilerrors.NewAggregate([]error{err, aggErr}) + multiErr = append(multiErr, err) + return ctrl.Result{}, utilerrors.NewAggregate(multiErr) } - return ctrl.Result{}, utilerrors.Flatten(aggErr) + return ctrl.Result{RequeueAfter: machineRequeueInterval}, nil } -// reconcilePower ensures the Machine Power is in the desired state. -func (r *MachineReconciler) reconcilePower(ctx context.Context, bm *v1alpha1.Machine, bmcClient *bmclib.Client) error { +// powerState gets the current power state of the machine. +func (r *MachineReconciler) powerState(ctx context.Context, bm *v1alpha1.Machine, bmcClient *bmclib.Client) error { rawState, err := bmcClient.GetPowerState(ctx) if err != nil { - r.recorder.Eventf(bm, corev1.EventTypeWarning, EventGetPowerStateFailed, "get power state: %v", err) + bm.Status.Power = v1alpha1.Unknown + r.recorder.Eventf(bm, corev1.EventTypeWarning, eventGetPowerStateFailed, "get power state: %v", err) return fmt.Errorf("get power state: %w", err) } - state, err := convertRawBMCPowerState(rawState) - if err != nil { - return err - } - - bm.Status.Power = state + bm.Status.Power = toPowerState(rawState) return nil } // patchStatus patches the specifies patch on the Machine. func (r *MachineReconciler) patchStatus(ctx context.Context, bm *v1alpha1.Machine, patch client.Patch) error { - err := r.client.Status().Patch(ctx, bm, patch) - if err != nil { + if err := r.client.Status().Patch(ctx, bm, patch); err != nil { return fmt.Errorf("failed to patch Machine %s/%s status: %w", bm.Namespace, bm.Name, err) } return nil } -// convertRawBMCPowerState takes a raw BMC power state response and attempts to convert it to -// a PowerState. -func convertRawBMCPowerState(response string) (v1alpha1.PowerState, error) { - // Normalize the response string for comparison. - response = strings.ToLower(response) - - switch { - case strings.Contains(response, "on"): - return v1alpha1.On, nil - case strings.Contains(response, "off"): - return v1alpha1.Off, nil - } +func retrieveHMACSecrets(ctx context.Context, c client.Client, hmacSecrets v1alpha1.HMACSecrets) (rpc.Secrets, error) { + sec := rpc.Secrets{} + for k, v := range hmacSecrets { + for _, s := range v { + secret := &corev1.Secret{} + key := types.NamespacedName{Namespace: s.Namespace, Name: s.Name} - return "", fmt.Errorf("unknown bmc power state: %v", response) -} + if err := c.Get(ctx, key, secret); err != nil { + if apierrors.IsNotFound(err) { + return nil, fmt.Errorf("secret %s not found: %w", key, err) + } -// resolveAuthSecretRef Gets the Secret from the SecretReference. -// Returns the username and password encoded in the Secret. -func resolveAuthSecretRef(ctx context.Context, c client.Client, secretRef corev1.SecretReference) (string, string, error) { - secret := &corev1.Secret{} - key := types.NamespacedName{Namespace: secretRef.Namespace, Name: secretRef.Name} + return nil, fmt.Errorf("failed to retrieve secret %s : %w", s, err) + } - if err := c.Get(ctx, key, secret); err != nil { - if apierrors.IsNotFound(err) { - return "", "", fmt.Errorf("secret %s not found: %w", key, err) + sec[rpc.Algorithm(k)] = append(sec[rpc.Algorithm(k)], string(secret.Data["secret"])) } - - return "", "", fmt.Errorf("failed to retrieve secret %s : %w", secretRef, err) - } - - username, ok := secret.Data["username"] - if !ok { - return "", "", fmt.Errorf("'username' required in Machine secret") - } - - password, ok := secret.Data["password"] - if !ok { - return "", "", fmt.Errorf("'password' required in Machine secret") } - return string(username), string(password), nil + return sec, nil } // SetupWithManager sets up the controller with the Manager. diff --git a/controllers/machine_test.go b/controller/machine_test.go similarity index 82% rename from controllers/machine_test.go rename to controller/machine_test.go index 2b7e19a..6ee978e 100644 --- a/controllers/machine_test.go +++ b/controller/machine_test.go @@ -1,4 +1,4 @@ -package controllers_test +package controller_test import ( "context" @@ -12,7 +12,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "github.com/tinkerbell/rufio/api/v1alpha1" - "github.com/tinkerbell/rufio/controllers" + "github.com/tinkerbell/rufio/controller" ) func TestMachineReconcile(t *testing.T) { @@ -32,27 +32,23 @@ func TestMachineReconcile(t *testing.T) { }, "fail on open": { - provider: &testProvider{ErrOpen: errors.New("failed to open connection")}, - shouldErr: true, - secret: createSecret(), + provider: &testProvider{ErrOpen: errors.New("failed to open connection")}, + secret: createSecret(), }, "fail on power get": { - provider: &testProvider{ErrPowerStateGet: errors.New("failed to set power state")}, - shouldErr: true, - secret: createSecret(), + provider: &testProvider{ErrPowerStateGet: errors.New("failed to set power state")}, + secret: createSecret(), }, "fail bad power state": { - provider: &testProvider{Powerstate: "bad"}, - shouldErr: true, - secret: createSecret(), + provider: &testProvider{Powerstate: "bad"}, + secret: createSecret(), }, "fail on close": { - provider: &testProvider{ErrClose: errors.New("failed to close connection")}, - shouldErr: true, - secret: createSecret(), + provider: &testProvider{ErrClose: errors.New("failed to close connection")}, + secret: createSecret(), }, "fail secret not found": { @@ -101,7 +97,7 @@ func TestMachineReconcile(t *testing.T) { fakeRecorder := record.NewFakeRecorder(2) - reconciler := controllers.NewMachineReconciler( + reconciler := controller.NewMachineReconciler( client, fakeRecorder, newTestClient(tt.provider), diff --git a/controllers/task.go b/controller/task.go similarity index 97% rename from controllers/task.go rename to controller/task.go index da46c70..8b9b177 100644 --- a/controllers/task.go +++ b/controller/task.go @@ -11,12 +11,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -package controllers +package controller import ( "context" "fmt" - "strconv" "time" bmclib "github.com/bmc-toolbox/bmclib/v2" @@ -96,7 +95,7 @@ func (r *TaskReconciler) doReconcile(ctx context.Context, task *v1alpha1.Task, t } // Initializing BMC Client - bmcClient, err := r.bmcClientFactory(ctx, logger, task.Spec.Connection.Host, strconv.Itoa(task.Spec.Connection.Port), username, password) + bmcClient, err := r.bmcClientFactory(ctx, logger, task.Spec.Connection.Host, username, password, nil) if err != nil { logger.Error(err, "BMC connection failed", "host", task.Spec.Connection.Host) task.SetCondition(v1alpha1.TaskFailed, v1alpha1.ConditionTrue, v1alpha1.WithTaskConditionMessage(fmt.Sprintf("Failed to connect to BMC: %v", err))) @@ -229,10 +228,7 @@ func (r *TaskReconciler) checkTaskStatus(ctx context.Context, log logr.Logger, t log = log.WithValues("currentPowerState", rawState) log.Info("power state check") - state, err := convertRawBMCPowerState(rawState) - if err != nil { - return ctrl.Result{}, err - } + state := toPowerState(rawState) switch *task.PowerAction { //nolint:exhaustive // we only support a few power actions right now. case v1alpha1.PowerOn: diff --git a/controllers/task_test.go b/controller/task_test.go similarity index 97% rename from controllers/task_test.go rename to controller/task_test.go index 773e285..f3c7855 100644 --- a/controllers/task_test.go +++ b/controller/task_test.go @@ -1,4 +1,4 @@ -package controllers_test +package controller_test import ( "context" @@ -8,7 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/tinkerbell/rufio/api/v1alpha1" - "github.com/tinkerbell/rufio/controllers" + "github.com/tinkerbell/rufio/controller" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -116,7 +116,7 @@ func TestTaskReconcile(t *testing.T) { WithStatusSubresource(task). Build() - reconciler := controllers.NewTaskReconciler(cluster, newTestClient(tt.provider)) + reconciler := controller.NewTaskReconciler(cluster, newTestClient(tt.provider)) request := reconcile.Request{ NamespacedName: types.NamespacedName{ Namespace: task.Namespace, diff --git a/controllers/client.go b/controllers/client.go deleted file mode 100644 index 98b717a..0000000 --- a/controllers/client.go +++ /dev/null @@ -1,40 +0,0 @@ -package controllers - -import ( - "context" - "fmt" - "time" - - bmclib "github.com/bmc-toolbox/bmclib/v2" - "github.com/go-logr/logr" -) - -// ClientFunc defines a func that returns a bmclib.Client. -type ClientFunc func(ctx context.Context, log logr.Logger, hostIP, port, username, password string) (*bmclib.Client, error) - -// NewClientFunc returns a new BMCClientFactoryFunc. The timeout parameter determines the -// maximum time to probe for compatible interfaces. -func NewClientFunc(timeout time.Duration) ClientFunc { - // Initializes a bmclib client based on input host and credentials - // Establishes a connection with the bmc with client.Open - // Returns a bmclib.Client. - return func(ctx context.Context, log logr.Logger, hostIP, port, username, password string) (*bmclib.Client, error) { - client := bmclib.NewClient(hostIP, username, password) - log = log.WithValues("host", hostIP, "port", port, "username", username) - - ctx, cancel := context.WithTimeout(ctx, timeout) - defer cancel() - - // TODO (pokearu): Make an option - client.Registry.Drivers = client.Registry.PreferProtocol("redfish") - if err := client.Open(ctx); err != nil { - md := client.GetMetadata() - log.Info("Failed to open connection to BMC", "error", err, "providersAttempted", md.ProvidersAttempted, "successfulProvider", md.SuccessfulOpenConns) - return nil, fmt.Errorf("failed to open connection to BMC: %w", err) - } - md := client.GetMetadata() - log.Info("Connected to BMC", "providersAttempted", md.ProvidersAttempted, "successfulProvider", md.SuccessfulOpenConns) - - return client, nil - } -} diff --git a/go.mod b/go.mod index 301548a..e5e9dc5 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,8 @@ module github.com/tinkerbell/rufio go 1.20 require ( - github.com/bmc-toolbox/bmclib/v2 v2.0.1-0.20230511130410-5f3cb3510c90 + dario.cat/mergo v1.0.0 + github.com/bmc-toolbox/bmclib/v2 v2.0.1-0.20230920073854-44c296132a03 github.com/go-logr/logr v1.2.4 github.com/go-logr/zerologr v1.2.3 github.com/google/go-cmp v0.5.9 @@ -11,13 +12,14 @@ require ( github.com/peterbourgon/ff/v3 v3.4.0 github.com/rs/zerolog v1.30.0 golang.org/x/tools v0.13.0 - k8s.io/api v0.28.1 - k8s.io/apimachinery v0.28.1 - k8s.io/client-go v0.28.1 - sigs.k8s.io/controller-runtime v0.15.0 + k8s.io/api v0.28.2 + k8s.io/apimachinery v0.28.2 + k8s.io/client-go v0.28.2 + sigs.k8s.io/controller-runtime v0.16.2 ) require ( + github.com/Jeffail/gabs/v2 v2.7.0 // indirect github.com/VictorLowther/simplexml v0.0.0-20180716164440-0bff93621230 // indirect github.com/VictorLowther/soap v0.0.0-20150314151524-8e36fca84b22 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -28,6 +30,7 @@ require ( github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/ghodss/yaml v1.0.0 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect @@ -51,10 +54,10 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.15.1 // indirect + github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect github.com/satori/go.uuid v1.2.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stmcginnis/gofish v0.14.0 // indirect @@ -66,14 +69,14 @@ require ( golang.org/x/term v0.12.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect - gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.30.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.27.2 // indirect - k8s.io/component-base v0.27.2 // indirect + k8s.io/apiextensions-apiserver v0.28.0 // indirect + k8s.io/component-base v0.28.1 // indirect k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect diff --git a/go.sum b/go.sum index 7f0fd31..4a11a80 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,17 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/Jeffail/gabs/v2 v2.7.0 h1:Y2edYaTcE8ZpRsR2AtmPu5xQdFDIthFG0jYhu5PY8kg= +github.com/Jeffail/gabs/v2 v2.7.0/go.mod h1:dp5ocw1FvBBQYssgHsG7I1WYsiLRtkUaB1FEtSwvNUw= github.com/VictorLowther/simplexml v0.0.0-20180716164440-0bff93621230 h1:t95Grn2mOPfb3+kPDWsNnj4dlNcxnvuR72IjY8eYjfQ= github.com/VictorLowther/simplexml v0.0.0-20180716164440-0bff93621230/go.mod h1:t2EzW1qybnPDQ3LR/GgeF0GOzHUXT5IVMLP2gkW1cmc= github.com/VictorLowther/soap v0.0.0-20150314151524-8e36fca84b22 h1:a0MBqYm44o0NcthLKCljZHe1mxlN6oahCQHHThnSwB4= github.com/VictorLowther/soap v0.0.0-20150314151524-8e36fca84b22/go.mod h1:/B7V22rcz4860iDqstGvia/2+IYWXf3/JdQCVd/1D2A= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bmc-toolbox/bmclib/v2 v2.0.1-0.20230511130410-5f3cb3510c90 h1:r52ize1/OF+C++ushrNUIgXFq9VaEmmg/IcyfbWrcoU= -github.com/bmc-toolbox/bmclib/v2 v2.0.1-0.20230511130410-5f3cb3510c90/go.mod h1:a3Ra0ce/LV3wAj7AHuphlHNTx5Sg67iQqtLGr1zoqio= +github.com/bmc-toolbox/bmclib/v2 v2.0.1-0.20230919153453-b9b7ef821d3d h1:/s7rr6giE02JpbYtW/yFyyeRnCJdX2I0DO2iI1g70Bk= +github.com/bmc-toolbox/bmclib/v2 v2.0.1-0.20230919153453-b9b7ef821d3d/go.mod h1:+4Rf1p0klRc//ktZQVZ0Nj/t9Sls9JwX7qUGpRxZKXE= +github.com/bmc-toolbox/bmclib/v2 v2.0.1-0.20230920073854-44c296132a03 h1:++XvytvtWPaiWVJC5wq2VzHneXDfl1dH3ASYEL2spEk= +github.com/bmc-toolbox/bmclib/v2 v2.0.1-0.20230920073854-44c296132a03/go.mod h1:+4Rf1p0klRc//ktZQVZ0Nj/t9Sls9JwX7qUGpRxZKXE= github.com/bmc-toolbox/common v0.0.0-20230220061748-93ff001f4a1d h1:cQ30Wa8mhLzK1TSOG+g3FlneIsXtFgun61mmPwVPmD0= github.com/bmc-toolbox/common v0.0.0-20230220061748-93ff001f4a1d/go.mod h1:SY//n1PJjZfbFbmAsB6GvEKbc7UXz3d30s3kWxfJQ/c= github.com/bombsimon/logrusr/v2 v2.0.1 h1:1VgxVNQMCvjirZIYaT9JYn6sAVGVEcNtRE0y4mvaOAM= @@ -24,6 +30,9 @@ github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJ github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -72,8 +81,10 @@ github.com/jacobweinstock/registrar v0.4.7/go.mod h1:PWmkdGFG5/ZdCqgMo7pvB3pXABO github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -97,8 +108,9 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= -github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -106,14 +118,14 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= -github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= @@ -135,10 +147,9 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -188,8 +199,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.3.0 h1:8NFhfS6gzxNqjLIYnZxg319wZ5Qjnx4m/CcX+Klzazc= -gomodules.xyz/jsonpatch/v2 v2.3.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= @@ -209,24 +220,24 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.28.1 h1:i+0O8k2NPBCPYaMB+uCkseEbawEt/eFaiRqUx8aB108= -k8s.io/api v0.28.1/go.mod h1:uBYwID+66wiL28Kn2tBjBYQdEU0Xk0z5qF8bIBqk/Dg= -k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo= -k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= -k8s.io/apimachinery v0.28.1 h1:EJD40og3GizBSV3mkIoXQBsws32okPOy+MkRyzh6nPY= -k8s.io/apimachinery v0.28.1/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= -k8s.io/client-go v0.28.1 h1:pRhMzB8HyLfVwpngWKE8hDcXRqifh1ga2Z/PU9SXVK8= -k8s.io/client-go v0.28.1/go.mod h1:pEZA3FqOsVkCc07pFVzK076R+P/eXqsgx5zuuRWukNE= -k8s.io/component-base v0.27.2 h1:neju+7s/r5O4x4/txeUONNTS9r1HsPbyoPBAtHsDCpo= -k8s.io/component-base v0.27.2/go.mod h1:5UPk7EjfgrfgRIuDBFtsEFAe4DAvP3U+M8RTzoSJkpo= +k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= +k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= +k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E= +k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= +k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= +k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= +k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= +k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= +k8s.io/component-base v0.28.1 h1:LA4AujMlK2mr0tZbQDZkjWbdhTV5bRyEyAFe0TJxlWg= +k8s.io/component-base v0.28.1/go.mod h1:jI11OyhbX21Qtbav7JkhehyBsIRfnO8oEgoAR12ArIU= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= -sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= +sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= diff --git a/main.go b/main.go index aa8b550..03ee199 100644 --- a/main.go +++ b/main.go @@ -38,9 +38,10 @@ import ( clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/healthz" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "github.com/tinkerbell/rufio/api/v1alpha1" - "github.com/tinkerbell/rufio/controllers" + "github.com/tinkerbell/rufio/controller" //+kubebuilder:scaffold:imports ) @@ -62,16 +63,12 @@ func init() { // defaultLogger is a zerolog logr implementation. func defaultLogger(level string) logr.Logger { - zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMs - zerologr.NameFieldName = "logger" - zerologr.NameSeparator = "/" - zl := zerolog.New(os.Stdout) zl = zl.With().Caller().Timestamp().Logger() var l zerolog.Level switch level { case "debug": - l = zerolog.DebugLevel + l = zerolog.TraceLevel default: l = zerolog.InfoLevel } @@ -119,13 +116,15 @@ func main() { setupLog.Info("Watching objects in namespace for reconciliation", "namespace", kubeNamespace) mgr, err := ctrl.NewManager(cfg, ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: metricsAddr, - Port: 9443, - HealthProbeBindAddress: probeAddr, - LeaderElection: enableLeaderElection, - LeaderElectionID: "e74dec1a.tinkerbell.org", - Namespace: kubeNamespace, + Scheme: scheme, + Metrics: metricsserver.Options{ + BindAddress: metricsAddr, + }, + // Port: 9443, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "e74dec1a.tinkerbell.org", + LeaderElectionNamespace: kubeNamespace, }) if err != nil { setupLog.Error(err, "unable to start manager") @@ -135,7 +134,7 @@ func main() { // Setup the context that's going to be used in controllers and for the manager. ctx := ctrl.SetupSignalHandler() - bmcClientFactory := controllers.NewClientFunc(bmcConnectTimeout) + bmcClientFactory := controller.NewClientFunc(bmcConnectTimeout) // Setup controller reconcilers setupReconcilers(ctx, mgr, bmcClientFactory) @@ -169,8 +168,8 @@ func newClientConfig(kubeAPIServer, kubeconfig string) clientcmd.ClientConfig { } // setupReconcilers initializes the controllers with the Manager. -func setupReconcilers(ctx context.Context, mgr ctrl.Manager, bmcClientFactory controllers.ClientFunc) { - err := (controllers.NewMachineReconciler( +func setupReconcilers(ctx context.Context, mgr ctrl.Manager, bmcClientFactory controller.ClientFunc) { + err := (controller.NewMachineReconciler( mgr.GetClient(), mgr.GetEventRecorderFor("machine-controller"), bmcClientFactory, @@ -180,7 +179,7 @@ func setupReconcilers(ctx context.Context, mgr ctrl.Manager, bmcClientFactory co os.Exit(1) } - err = (controllers.NewJobReconciler( + err = (controller.NewJobReconciler( mgr.GetClient(), )).SetupWithManager(ctx, mgr) if err != nil { @@ -188,7 +187,7 @@ func setupReconcilers(ctx context.Context, mgr ctrl.Manager, bmcClientFactory co os.Exit(1) } - err = (controllers.NewTaskReconciler( + err = (controller.NewTaskReconciler( mgr.GetClient(), bmcClientFactory, )).SetupWithManager(mgr)