Skip to content

Commit

Permalink
Improve readability:
Browse files Browse the repository at this point in the history
Return in each switch case. Make function for patching status.
Reorganize where some conditions were being set.
Replace !errors.IsNotFound with ctrlclient.IgnoreNotFound
in order to improve readability.

Signed-off-by: Jacob Weinstock <[email protected]>
  • Loading branch information
jacobweinstock committed Sep 29, 2024
1 parent 7084d48 commit ff45778
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 75 deletions.
28 changes: 28 additions & 0 deletions docs/Workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# The Workflow custom resource

This doc provides details for different parts of the Workflow custom resource.

## Spec

### BootOptions

The `spec.bootOptions` object contains optional functionality that will run before a Workflow and triggers handling of different Hardware booting capabilities.

## Status

### State

There are several states that a Workflow can be in:

`STATE_WAITING` -
`STATE_PENDING` -
`STATE_RUNNING` -
`STATE_SUCCESS` -
`STATE_FAILED` -
`STATE_TIMEOUT` -

### OneTimeNetboot

### TemplateRendering

### Conditions
10 changes: 4 additions & 6 deletions internal/deprecated/workflow/bootops.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

rufio "github.com/tinkerbell/rufio/api/v1alpha1"
"github.com/tinkerbell/tink/api/v1alpha1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"knative.dev/pkg/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -25,13 +24,13 @@ func handleExistingJob(ctx context.Context, cc client.Client, wf *v1alpha1.Workf
}
name := fmt.Sprintf(bmcJobName, wf.Spec.HardwareRef)
namespace := wf.Namespace
if err := cc.Get(ctx, client.ObjectKey{Name: name, Namespace: namespace}, &rufio.Job{}); (err != nil && !errors.IsNotFound(err)) || err == nil {
if err := cc.Get(ctx, client.ObjectKey{Name: name, Namespace: namespace}, &rufio.Job{}); client.IgnoreNotFound(err) != nil || err == nil {
existingJob := &rufio.Job{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace}}
opts := []client.DeleteOption{
client.GracePeriodSeconds(0),
client.PropagationPolicy(metav1.DeletePropagationForeground),
}
if err := cc.Delete(ctx, existingJob, opts...); err != nil {
if err := cc.Delete(ctx, existingJob, opts...); client.IgnoreNotFound(err) != nil {
return reconcile.Result{}, fmt.Errorf("error deleting job.bmc.tinkerbell.org object: %w", err)

Check warning on line 34 in internal/deprecated/workflow/bootops.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/bootops.go#L34

Added line #L34 was not covered by tests
}
return reconcile.Result{Requeue: true}, nil
Expand All @@ -49,8 +48,8 @@ func handleJobCreation(ctx context.Context, cc client.Client, wf *v1alpha1.Workf
return reconcile.Result{Requeue: true}, nil

Check warning on line 48 in internal/deprecated/workflow/bootops.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/bootops.go#L47-L48

Added lines #L47 - L48 were not covered by tests
}
hw := &v1alpha1.Hardware{ObjectMeta: metav1.ObjectMeta{Name: wf.Spec.HardwareRef, Namespace: wf.Namespace}}
if gerr := cc.Get(ctx, client.ObjectKey{Name: wf.Spec.HardwareRef, Namespace: wf.Namespace}, hw); gerr != nil {
return reconcile.Result{}, fmt.Errorf("error getting hardware %s: %w", wf.Spec.HardwareRef, gerr)
if err := cc.Get(ctx, client.ObjectKey{Name: wf.Spec.HardwareRef, Namespace: wf.Namespace}, hw); err != nil {
return reconcile.Result{}, fmt.Errorf("error getting hardware %s: %w", wf.Spec.HardwareRef, err)

Check warning on line 52 in internal/deprecated/workflow/bootops.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/bootops.go#L52

Added line #L52 was not covered by tests
}
if hw.Spec.BMCRef == nil {
return reconcile.Result{}, fmt.Errorf("hardware %s does not have a BMC, cannot perform one time netboot", hw.Name)

Check warning on line 55 in internal/deprecated/workflow/bootops.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/bootops.go#L55

Added line #L55 was not covered by tests
Expand All @@ -72,7 +71,6 @@ func handleJobCreation(ctx context.Context, cc client.Client, wf *v1alpha1.Workf
Message: "job created",
Time: &metav1.Time{Time: metav1.Now().UTC()},
})

return reconcile.Result{Requeue: true}, nil
}

Expand Down
126 changes: 57 additions & 69 deletions internal/deprecated/workflow/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package workflow

import (
"context"
serrors "errors"
"fmt"
"time"

Expand Down Expand Up @@ -57,91 +58,83 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
if !stored.DeletionTimestamp.IsZero() {
return reconcile.Result{}, nil
}

wflow := stored.DeepCopy()

var (
resp reconcile.Result
err error
)
switch wflow.Status.State {
case "":
resp, err = r.processNewWorkflow(ctx, logger, wflow)
case v1alpha1.WorkflowStateRunning:
resp = r.processRunningWorkflow(ctx, wflow)
// set the current action in the status
ca := runningAction(wflow)
if ca != "" && wflow.Status.CurrentAction != ca {
wflow.Status.CurrentAction = ca
}
resp, err := r.processNewWorkflow(ctx, logger, wflow)

return resp, serrors.Join(err, mergePatchsStatus(ctx, r.client, stored, wflow))
case v1alpha1.WorkflowStateWaiting:

Check warning on line 69 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L69

Added line #L69 was not covered by tests
// make sure any existing job is deleted
if !wflow.Status.BootOptions.OneTimeNetboot.ExistingJobDeleted {
rc, err := handleExistingJob(ctx, r.client, wflow)

Check warning on line 72 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L71-L72

Added lines #L71 - L72 were not covered by tests
// Patch any changes, regardless of errors
if !equality.Semantic.DeepEqual(wflow, stored) {
if perr := r.client.Status().Patch(ctx, wflow, ctrlclient.MergeFrom(stored)); perr != nil {
err = fmt.Errorf("error patching workflow %s, %w", wflow.Name, perr)
}
}
return rc, err

return rc, serrors.Join(err, mergePatchsStatus(ctx, r.client, stored, wflow))

Check warning on line 74 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L74

Added line #L74 was not covered by tests
}

// create a new job
if wflow.Status.BootOptions.OneTimeNetboot.UID == "" && wflow.Status.BootOptions.OneTimeNetboot.ExistingJobDeleted {
rc, err := handleJobCreation(ctx, r.client, wflow)

Check warning on line 79 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L78-L79

Added lines #L78 - L79 were not covered by tests
// Patch any changes, regardless of errors
if !equality.Semantic.DeepEqual(wflow, stored) {
if perr := r.client.Status().Patch(ctx, wflow, ctrlclient.MergeFrom(stored)); perr != nil {
err = fmt.Errorf("error patching workflow %s, %w", wflow.Name, perr)
}
}
return rc, err

return rc, serrors.Join(err, mergePatchsStatus(ctx, r.client, stored, wflow))

Check warning on line 81 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L81

Added line #L81 was not covered by tests
}

// check if the job is complete
if !wflow.Status.BootOptions.OneTimeNetboot.Complete && wflow.Status.BootOptions.OneTimeNetboot.UID != "" && wflow.Status.BootOptions.OneTimeNetboot.ExistingJobDeleted {
rc, err := handleJobComplete(ctx, r.client, wflow)

Check warning on line 86 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L85-L86

Added lines #L85 - L86 were not covered by tests
// Patch any changes, regardless of errors
if !equality.Semantic.DeepEqual(wflow, stored) {
if perr := r.client.Status().Patch(ctx, wflow, ctrlclient.MergeFrom(stored)); perr != nil {
err = fmt.Errorf("error patching workflow %s, %w", wflow.Name, perr)
}
}
return rc, err

return rc, serrors.Join(err, mergePatchsStatus(ctx, r.client, stored, wflow))

Check warning on line 88 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L88

Added line #L88 was not covered by tests
}
case v1alpha1.WorkflowStateRunning:
r.processRunningWorkflow(wflow)
// set the current action in the status
ca := runningAction(wflow)
if ca != "" && wflow.Status.CurrentAction != ca {
wflow.Status.CurrentAction = ca

Check warning on line 95 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L95

Added line #L95 was not covered by tests
}

return reconcile.Result{}, mergePatchsStatus(ctx, r.client, stored, wflow)
case v1alpha1.WorkflowStatePending, v1alpha1.WorkflowStateTimeout, v1alpha1.WorkflowStateFailed:
return reconcile.Result{}, nil
case v1alpha1.WorkflowStateSuccess:
if wflow.Spec.BootOptions.ToggleAllowNetboot && !wflow.Status.HasCondition(v1alpha1.ToggleAllowNetbootFalse, metav1.ConditionTrue) {

Check warning on line 102 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L99-L102

Added lines #L99 - L102 were not covered by tests
// handle updating hardware allowPXE to false
wflow.Status.SetCondition(v1alpha1.WorkflowCondition{
Type: v1alpha1.ToggleAllowNetbootFalse,
Status: metav1.ConditionTrue,
Reason: "Complete",
Message: "set allowPXE to false",
Time: &metav1.Time{Time: metav1.Now().UTC()},
})
if gerr := handleHardwareAllowPXE(ctx, r.client, wflow, nil, false); gerr != nil {
if err := handleHardwareAllowPXE(ctx, r.client, wflow, nil, false); err != nil {
stored.Status.SetCondition(v1alpha1.WorkflowCondition{
Type: v1alpha1.ToggleAllowNetbootFalse,
Status: metav1.ConditionTrue,
Reason: "Error",
Message: fmt.Sprintf("error setting Allow PXE: %v", gerr),
Message: fmt.Sprintf("error setting Allow PXE: %v", err),
Time: &metav1.Time{Time: metav1.Now().UTC()},
})
err = gerr
return reconcile.Result{}, serrors.Join(err, mergePatchsStatus(ctx, r.client, stored, wflow))

Check warning on line 112 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L104-L112

Added lines #L104 - L112 were not covered by tests
}
wflow.Status.SetCondition(v1alpha1.WorkflowCondition{
Type: v1alpha1.ToggleAllowNetbootFalse,
Status: metav1.ConditionTrue,
Reason: "Complete",
Message: "set allowPXE to false",
Time: &metav1.Time{Time: metav1.Now().UTC()},
})

Check warning on line 120 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L114-L120

Added lines #L114 - L120 were not covered by tests

return reconcile.Result{}, mergePatchsStatus(ctx, r.client, stored, wflow)

Check warning on line 122 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L122

Added line #L122 was not covered by tests
}
default:
return resp, nil
}

return reconcile.Result{}, nil

Check warning on line 126 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L126

Added line #L126 was not covered by tests
}

// mergePatchsStatus merges an updated Workflow with an original Workflow and patches the Status object via the client (cc).
func mergePatchsStatus(ctx context.Context, cc ctrlclient.Client, original, updated *v1alpha1.Workflow) error {
// Patch any changes, regardless of errors
if !equality.Semantic.DeepEqual(wflow, stored) {
if perr := r.client.Status().Patch(ctx, wflow, ctrlclient.MergeFrom(stored)); perr != nil {
err = fmt.Errorf("error patching workflow %s, %w", wflow.Name, perr)
if !equality.Semantic.DeepEqual(updated, original) {
if err := cc.Status().Patch(ctx, updated, ctrlclient.MergeFrom(original)); err != nil {
return fmt.Errorf("error patching status of workflow: %s, error: %w", updated.Name, err)

Check warning on line 134 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L134

Added line #L134 was not covered by tests
}
}

return resp, err
return nil
}

func runningAction(wf *v1alpha1.Workflow) string {
Expand Down Expand Up @@ -187,14 +180,9 @@ func (r *Reconciler) processNewWorkflow(ctx context.Context, logger logr.Logger,
return reconcile.Result{}, err
}

data := make(map[string]interface{})
for key, val := range stored.Spec.HardwareMap {
data[key] = val
}

var hardware v1alpha1.Hardware
err := r.client.Get(ctx, ctrlclient.ObjectKey{Name: stored.Spec.HardwareRef, Namespace: stored.Namespace}, &hardware)
if err != nil && !errors.IsNotFound(err) {
if ctrlclient.IgnoreNotFound(err) != nil {
logger.Error(err, "error getting Hardware object in processNewWorkflow function")
stored.Status.TemplateRendering = v1alpha1.TemplateRenderingFailed
stored.Status.SetCondition(v1alpha1.WorkflowCondition{
Expand Down Expand Up @@ -224,10 +212,12 @@ func (r *Reconciler) processNewWorkflow(ctx context.Context, logger logr.Logger,
)
}

if err == nil {
contract := toTemplateHardwareData(hardware)
data["Hardware"] = contract
data := make(map[string]interface{})
for key, val := range stored.Spec.HardwareMap {
data[key] = val
}
contract := toTemplateHardwareData(hardware)
data["Hardware"] = contract

tinkWf, err := renderTemplateHardware(stored.Name, ptr.StringValue(tpl.Spec.Data), data)
if err != nil {
Expand Down Expand Up @@ -255,13 +245,6 @@ func (r *Reconciler) processNewWorkflow(ctx context.Context, logger logr.Logger,

// set hardware allowPXE if requested.
if stored.Spec.BootOptions.ToggleAllowNetboot {
stored.Status.SetCondition(v1alpha1.WorkflowCondition{
Type: v1alpha1.ToggleAllowNetbootTrue,
Status: metav1.ConditionTrue,
Reason: "Complete",
Message: "set allowPXE to true",
Time: &metav1.Time{Time: metav1.Now().UTC()},
})
if err := handleHardwareAllowPXE(ctx, r.client, stored, &hardware, true); err != nil {
stored.Status.SetCondition(v1alpha1.WorkflowCondition{
Type: v1alpha1.ToggleAllowNetbootTrue,
Expand All @@ -272,6 +255,13 @@ func (r *Reconciler) processNewWorkflow(ctx context.Context, logger logr.Logger,
})
return reconcile.Result{}, err

Check warning on line 256 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L248-L256

Added lines #L248 - L256 were not covered by tests
}
stored.Status.SetCondition(v1alpha1.WorkflowCondition{
Type: v1alpha1.ToggleAllowNetbootTrue,
Status: metav1.ConditionTrue,
Reason: "Complete",
Message: "set allowPXE to true",
Time: &metav1.Time{Time: metav1.Now().UTC()},
})

Check warning on line 264 in internal/deprecated/workflow/reconciler.go

View check run for this annotation

Codecov / codecov/patch

internal/deprecated/workflow/reconciler.go#L258-L264

Added lines #L258 - L264 were not covered by tests
}

// netboot the hardware if requested
Expand Down Expand Up @@ -315,7 +305,7 @@ func toTemplateHardwareData(hardware v1alpha1.Hardware) templateHardwareData {
return contract
}

func (r *Reconciler) processRunningWorkflow(_ context.Context, stored *v1alpha1.Workflow) reconcile.Result { //nolint:unparam // This is the way controller runtime works.
func (r *Reconciler) processRunningWorkflow(stored *v1alpha1.Workflow) {
// Check for global timeout expiration
if r.nowFunc().After(stored.GetStartTime().Add(time.Duration(stored.Status.GlobalTimeout) * time.Second)) {
stored.Status.State = v1alpha1.WorkflowStateTimeout
Expand All @@ -336,6 +326,4 @@ func (r *Reconciler) processRunningWorkflow(_ context.Context, stored *v1alpha1.
}
}
}

return reconcile.Result{}
}

0 comments on commit ff45778

Please sign in to comment.