Repository: keikoproj/upgrade-manager
Pull request #79 (2020-03-17 21:28:26)

Improve logging - tag messages with RollingUpgrade name and use structured logging.
Covers #58.

This is WIP, to collect feedback.
I'm going to do extra testing and some extra cleanup.

**Testing Done**
Performed rollout and confirmed no issues.

uthark: @eytan-avisror Please take a look and provide your feedback. 
eytan-avisror: I think you need to find a way to define logger globally or make it part of the Reconciler without needing to define it per `ruObj` everywhere.
In other places it's worth while doing this worth to clean up places where we log an error and return it (which will log it again)
uthark: @eytan-avisror Options to simplify are:
1. Build logger and then propagate it everywhere (don't like it, pollutes API)
2. make helper log methods that will accept `ruObj` and write to logs.
3. Instead of ruObj pass another new struct ReconcileContext that will have both ruObj and logger to use. (might be the best one, also allows further expansion)

Or share your opinion on that.
eytan-avisror: @uthark 
Yeah, 3. would be good but that would be a bigger refactor - we can probably do this down the road as it will prove useful to have a context object per reconcile (not shared across multiple reconciles such as `RollingUpgradeReconciler`).

Can we do 2. for now, and possibly do 3. down the road? WDYT?
uthark: I'll update to 2 then.
uthark: @eytan-avisror I've updated logging, please take a look.
uthark: Do not merge it yet though, I'm going to fix couple more issues.
uthark: @eytan-avisror I've fixed couple of issues and tried to do a rollout –  all is good except for scripts outputs – they are rendered in base64.
uthark: Fixed script output logging too.
uthark: @eytan-avisror Hello! Do you have any other comments regarding this PR?

Patch:
diff --git a/controllers/rollingupgrade_controller.go b/controllers/rollingupgrade_controller.go
index c70bc7b..5f9a159 100644
--- a/controllers/rollingupgrade_controller.go
+++ b/controllers/rollingupgrade_controller.go
@@ -47,7 +47,6 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/reconcile"
 
 	upgrademgrv1alpha1 "github.com/keikoproj/upgrade-manager/api/v1alpha1"
-	log "github.com/keikoproj/upgrade-manager/pkg/log"
 )
 
 const (
@@ -109,18 +108,18 @@ type RollingUpgradeReconciler struct {
 
 func (r *RollingUpgradeReconciler) SetMaxParallel(max int) {
 	if max >= 1 {
-		log.Infof("max parallel reconciles = %v", max)
+		r.Log.Info(fmt.Sprintf("max parallel reconciles = %v", max))
 		r.maxParallel = max
 	}
 }
 
-func runScript(script string, background bool, objName string) (string, error) {
-	log.Printf("%s: Running script %s", objName, script)
+func (r *RollingUpgradeReconciler) runScript(script string, background bool, ruObj *upgrademgrv1alpha1.RollingUpgrade) (string, error) {
+	r.info(ruObj, "Running script", "script", script)
 	if background {
-		log.Printf("%s: Running script in background. Logs not available.", objName)
+		r.info(ruObj, "Running script in background. Logs not available.")
 		err := exec.Command(ShellBinary, "-c", script).Run()
 		if err != nil {
-			log.Printf("Script finished with error: %s", err)
+			r.info(ruObj, "Script finished with error: %s", err)
 		}
 
 		return "", nil
@@ -128,9 +127,9 @@ func runScript(script string, background bool, objName string) (string, error) {
 
 	out, err := exec.Command(ShellBinary, "-c", script).CombinedOutput()
 	if err != nil {
-		log.Printf("Script finished with output: %s\n, error: %s", out, err)
+		r.error(ruObj, err, "Script finished", "output", string(out))
 	} else {
-		log.Printf("%s: Script finished with output: %s", objName, out)
+		r.info(ruObj, "Script finished", "output", string(out))
 	}
 	return string(out), err
 }
@@ -138,11 +137,11 @@ func runScript(script string, background bool, objName string) (string, error) {
 func (r *RollingUpgradeReconciler) preDrainHelper(ruObj *upgrademgrv1alpha1.RollingUpgrade) error {
 	if ruObj.Spec.PreDrain.Script != "" {
 		script := ruObj.Spec.PreDrain.Script
-		_, err := runScript(script, false, ruObj.Name)
+		_, err := r.runScript(script, false, ruObj)
 		if err != nil {
-			msg := "Failed to run preDrain script: " + err.Error()
-			log.Printf("%s: %s", ruObj.Name, msg)
-			return errors.New(msg)
+			msg := "Failed to run preDrain script"
+			r.error(ruObj, err, msg)
+			return errors.Wrap(err, msg)
 		}
 	}
 	return nil
@@ -152,34 +151,36 @@ func (r *RollingUpgradeReconciler) preDrainHelper(ruObj *upgrademgrv1alpha1.Roll
 // kubeCtlCall is provided as an argument to decouple the method from the actual kubectl call
 func (r *RollingUpgradeReconciler) postDrainHelper(ruObj *upgrademgrv1alpha1.RollingUpgrade, nodeName string, kubeCtlCall string) error {
 	if ruObj.Spec.PostDrain.Script != "" {
-		_, err := runScript(ruObj.Spec.PostDrain.Script, false, ruObj.Name)
+		_, err := r.runScript(ruObj.Spec.PostDrain.Script, false, ruObj)
 		if err != nil {
-			msg := "Failed to run postDrain script: " + err.Error()
-			log.Printf("%s: %s", ruObj.Name, msg)
+			msg := "Failed to run postDrain script: "
+			r.error(ruObj, err, msg)
+			result := errors.Wrap(err, msg)
 
-			log.Printf("%s: Uncordoning the node %s since it failed to run postDrain Script", ruObj.Name, nodeName)
-			_, err = runScript(kubeCtlCall+" uncordon "+nodeName, false, ruObj.Name)
+			r.info(ruObj, "Uncordoning the node %s since it failed to run postDrain Script", "nodeName", nodeName)
+			_, err = r.runScript(kubeCtlCall+" uncordon "+nodeName, false, ruObj)
 			if err != nil {
-				log.Printf("%s: Failed to uncordon node %s: %v", ruObj.Name, nodeName, err)
+				r.error(ruObj, err, "Failed to uncordon", "nodeName", nodeName)
 			}
-			return errors.New(msg)
+			return result
 		}
 	}
-	log.Printf("%s: Waiting for postDrainDelay of %v seconds", ruObj.Name, ruObj.Spec.PostDrainDelaySeconds)
+	r.info(ruObj, "Waiting for postDrainDelay", "postDrainDelay", ruObj.Spec.PostDrainDelaySeconds)
 	time.Sleep(time.Duration(ruObj.Spec.PostDrainDelaySeconds) * time.Second)
 
 	if ruObj.Spec.PostDrain.PostWaitScript != "" {
-		_, err := runScript(ruObj.Spec.PostDrain.PostWaitScript, false, ruObj.Name)
+		_, err := r.runScript(ruObj.Spec.PostDrain.PostWaitScript, false, ruObj)
 		if err != nil {
 			msg := "Failed to run postDrainWait script: " + err.Error()
-			log.Printf("%s: %s", ruObj.Name, msg)
+			r.error(ruObj, err, msg)
+			result := errors.Wrap(err, msg)
 
-			log.Printf("%s: Uncordoning the node %s since it failed to run postDrainWait Script", ruObj.Name, nodeName)
-			_, err = runScript(kubeCtlCall+" uncordon "+nodeName, false, ruObj.Name)
+			r.info(ruObj, "Uncordoning the node %s since it failed to run postDrain Script", "nodeName", nodeName)
+			_, err = r.runScript(kubeCtlCall+" uncordon "+nodeName, false, ruObj)
 			if err != nil {
-				log.Printf("%s: Failed to uncordon node %s: %v", ruObj.Name, nodeName, err)
+				r.error(ruObj, err, "Failed to uncordon", "nodeName", nodeName)
 			}
-			return errors.New(msg)
+			return result
 		}
 	}
 	return nil
@@ -204,28 +205,27 @@ func (r *RollingUpgradeReconciler) DrainNode(ruObj *upgrademgrv1alpha1.RollingUp
 	// Add a context with timeout only if a valid drain timeout value is specified
 	// default value used for drain timeout is -1
 	if drainTimeout >= 0 {
-		log.Printf("Creating a context with timeout - %d", drainTimeout)
+		r.info(ruObj, "Creating a context with timeout", "drainTimeout", drainTimeout)
 		// Define a cancellation after drainTimeout
 		ctx, cancel = context.WithTimeout(ctx, time.Duration(drainTimeout)*time.Second)
 		defer cancel()
 	} else {
-		log.Printf("Skipped creating context with timeout. Drain timeout - %d", drainTimeout)
+		r.info(ruObj, "Skipped creating context with timeout.", "drainTimeout", drainTimeout)
 	}
 
-	log.Printf("Invoking kubectl drain for the node - %s", nodeName)
+	r.info(ruObj, "Invoking kubectl drain for the node", "nodeName", nodeName)
 	go r.CallKubectlDrain(ctx, nodeName, kubeCtlCall, ruObj, errChan)
 
 	// Listening to signals from the CallKubectlDrain go routine
 	select {
 	case <-ctx.Done():
-		log.Printf("Kubectl drain timed out for node - %s", nodeName)
-		log.Print(ctx.Err())
+		r.error(ruObj, ctx.Err(), "Kubectl drain timed out for node", "nodeName", nodeName)
 	case err := <-errChan:
 		if err != nil {
-			log.Printf("Kubectl drain errored for node - %s, error: %s", nodeName, err.Error())
+			r.error(ruObj, err, "Kubectl drain errored for node", "nodeName", nodeName)
 			return err
 		}
-		log.Printf("Kubectl drain completed for node - %s", nodeName)
+		r.info(ruObj, "Kubectl drain completed for node", "nodeName", nodeName)
 	}
 
 	return r.postDrainHelper(ruObj, nodeName, kubeCtlCall)
@@ -237,10 +237,11 @@ func (r *RollingUpgradeReconciler) CallKubectlDrain(ctx context.Context, nodeNam
 
 	// kops behavior implements the same behavior by using these flags when draining nodes
 	// https://github.com/kubernetes/kops/blob/7a629c77431dda02d02aadf00beb0bed87518cbf/pkg/instancegroups/instancegroups.go lines 337-340
-	out, err := runScript(kubeCtlCall+" drain "+nodeName+" --ignore-daemonsets=true --delete-local-data=true --force --grace-period=-1", false, ruObj.Name)
+	script := fmt.Sprintf("%s drain %s --ignore-daemonsets=true --delete-local-data=true --force --grace-period=-1", kubeCtlCall, nodeName)
+	out, err := r.runScript(script, false, ruObj)
 	if err != nil {
 		if strings.HasPrefix(out, "Error from server (NotFound)") {
-			log.Printf("%s: Not executing postDrainHelper. Node not found: %s", ruObj.Name, out)
+			r.error(ruObj, err, "Not executing postDrainHelper. Node not found.", "output", out)
 			errChan <- nil
 			return
 		}
@@ -266,11 +267,11 @@ func (r *RollingUpgradeReconciler) WaitForDesiredInstances(ruObj *upgrademgrv1al
 
 		inServiceCount := getInServiceCount(asg.Instances)
 		if inServiceCount == aws.Int64Value(asg.DesiredCapacity) {
-			log.Printf("%v: desired capacity is met, %v instances in service", ruObj.Name, inServiceCount)
+			r.info(ruObj, "desired capacity is met", "inServiceCount", inServiceCount)
 			return nil
 		}
 
-		log.Printf("%v: new instance has not yet joined the scaling group", ruObj.Name)
+		r.info(ruObj, "new instance has not yet joined the scaling group")
 	}
 	return errors.Wrapf(err, "%v: WaitForDesiredInstances timed out while waiting for instance to be added", ruObj.Name)
 }
@@ -286,7 +287,7 @@ func (r *RollingUpgradeReconciler) WaitForDesiredNodes(ruObj *upgrademgrv1alpha1
 
 		err = r.populateNodeList(ruObj, r.generatedClient.CoreV1().Nodes())
 		if err != nil {
-			log.Infof("%s: unable to populate node list: %v", ruObj.Name, err)
+			r.error(ruObj, err, "unable to populate node list")
 		}
 
 		asg, err := r.GetAutoScalingGroup(ruObj.Name)
@@ -309,32 +310,33 @@ func (r *RollingUpgradeReconciler) WaitForDesiredNodes(ruObj *upgrademgrv1alpha1
 		}
 
 		if foundCount == desiredCapacity {
-			log.Printf("%v: desired capacity is met, %v nodes in service", ruObj.Name, foundCount)
+			r.info(ruObj, "desired capacity is met", "inServiceCount", foundCount)
 			return nil
 		}
 
-		log.Printf("%v: new node has not yet joined the cluster", ruObj.Name)
+		r.info(ruObj, "new node has not yet joined the cluster")
 	}
 	return errors.Wrapf(err, "%v: WaitForDesiredNodes timed out while waiting for nodes to join", ruObj.Name)
 }
 
 func (r *RollingUpgradeReconciler) WaitForTermination(ruObj *upgrademgrv1alpha1.RollingUpgrade, nodeName string, nodeInterface v1.NodeInterface) (bool, error) {
-	var (
-		started = time.Now()
-	)
+
+	started := time.Now()
 	for {
 		if time.Since(started) >= (time.Second * time.Duration(TerminationTimeoutSeconds)) {
-			log.Printf("%v: WaitForTermination timed out while waiting for node to unjoin", ruObj.Name)
+			r.info(ruObj, "WaitForTermination timed out while waiting for node to unjoin")
 			return false, nil
 		}
 
 		_, err := nodeInterface.Get(nodeName, metav1.GetOptions{})
 		if v1errors.IsNotFound(err) {
-			log.Printf("%v: node %s is unjoined from cluster, upgrade will proceed", ruObj.Name, nodeName)
+			r.info(ruObj, "node is unjoined from cluster, upgrade will proceed", "nodeName", nodeName)
 			break
 		}
 
-		log.Printf("%v: node %s is still joined to cluster, will wait %vs and retry", ruObj.Name, nodeName, TerminationSleepIntervalSeconds)
+		r.info(ruObj, "node is still joined to cluster, will wait and retry",
+			"nodeName", nodeName, "terminationSleepIntervalSeconds", TerminationSleepIntervalSeconds)
+
 		time.Sleep(time.Duration(TerminationSleepIntervalSeconds) * time.Second)
 	}
 	return true, nil
@@ -352,8 +354,7 @@ func (r *RollingUpgradeReconciler) GetAutoScalingGroup(rollupName string) (*auto
 
 // SetStandby sets the autoscaling instance to standby mode.
 func (r *RollingUpgradeReconciler) SetStandby(ruObj *upgrademgrv1alpha1.RollingUpgrade, instanceID string) error {
-
-	log.Infof("%v: Setting %v to stand-by", ruObj.Name, instanceID)
+	r.info(ruObj, "Setting to stand-by", ruObj.Name, instanceID)
 	input := &autoscaling.EnterStandbyInput{
 		AutoScalingGroupName:           aws.String(ruObj.Spec.AsgName),
 		InstanceIds:                    aws.StringSlice([]string{instanceID}),
@@ -371,13 +372,13 @@ func (r *RollingUpgradeReconciler) SetStandby(ruObj *upgrademgrv1alpha1.RollingU
 	}
 
 	if !isInServiceLifecycleState(instanceState) {
-		log.Infof("%v: cannot set instance %v to stand-by, instance is in state %v", ruObj.Name, instanceID, instanceState)
+		r.info(ruObj, "Cannot set instance to stand-by, instance is in state", "instanceState", instanceState, "instanceID", instanceID)
 		return nil
 	}
 
 	_, err = r.ASGClient.EnterStandby(input)
 	if err != nil {
-		log.Warnf("%v: instance %v failed to enter standby: %v", ruObj.Name, instanceID, err)
+		r.error(ruObj, err, "Failed to enter standby", "instanceID", instanceID)
 	}
 	return nil
 }
@@ -394,36 +395,35 @@ func (r *RollingUpgradeReconciler) TerminateNode(ruObj *upgrademgrv1alpha1.Rolli
 	if err != nil {
 		if aerr, ok := err.(awserr.Error); ok {
 			if strings.Contains(aerr.Message(), "not found") {
-				log.Printf("Instance %s not found. Moving on\n", instanceID)
+				r.info(ruObj, "Instance not found. Moving on", "instanceID", instanceID)
 				return nil
 			}
 			switch aerr.Code() {
 			case autoscaling.ErrCodeScalingActivityInProgressFault:
-				log.Println(autoscaling.ErrCodeScalingActivityInProgressFault, aerr.Error())
+				r.error(ruObj, aerr, autoscaling.ErrCodeScalingActivityInProgressFault, "instanceID", instanceID)
 			case autoscaling.ErrCodeResourceContentionFault:
-				log.Println(autoscaling.ErrCodeResourceContentionFault, aerr.Error())
+				r.error(ruObj, aerr, autoscaling.ErrCodeResourceContentionFault, "instanceID", instanceID)
 				return nil
 			default:
-				log.Println(aerr.Error())
+				r.error(ruObj, aerr, aerr.Code(), "instanceID", instanceID)
 				return err
 			}
 		}
 	}
 
-	log.Infof("%v: terminated instance %v", ruObj.Name, instanceID)
-
-	log.Printf("%v: starting post termination sleep for %v seconds", ruObj.Name, ruObj.Spec.NodeIntervalSeconds)
+	r.info(ruObj, "Instance terminated.", "instanceID", instanceID)
+	r.info(ruObj, "starting post termination sleep", "instanceID", instanceID, "nodeIntervalSeconds", ruObj.Spec.NodeIntervalSeconds)
 	time.Sleep(time.Duration(ruObj.Spec.NodeIntervalSeconds) * time.Second)
 	if ruObj.Spec.PostTerminate.Script != "" {
-		out, err := runScript(ruObj.Spec.PostTerminate.Script, false, ruObj.Name)
+		out, err := r.runScript(ruObj.Spec.PostTerminate.Script, false, ruObj)
 		if err != nil {
 			if strings.HasPrefix(out, "Error from server (NotFound)") {
-				log.Printf("%s: Node not found when running postTerminate: %s. Ignoring ...", ruObj.Name, out)
+				r.error(ruObj, err, "Node not found when running postTerminate. Ignoring ...", "output", out, "instanceID", instanceID)
 				return nil
 			}
-			msg := "Failed to run postTerminate script: " + err.Error()
-			log.Printf("%s: %s", ruObj.Name, msg)
-			return errors.New(msg)
+			msg := "Failed to run postTerminate script"
+			r.error(ruObj, err, msg, "instanceID", instanceID)
+			return errors.Wrap(err, msg)
 		}
 	}
 	return nil
@@ -432,7 +432,7 @@ func (r *RollingUpgradeReconciler) TerminateNode(ruObj *upgrademgrv1alpha1.Rolli
 func (r *RollingUpgradeReconciler) getNodeName(i *autoscaling.Instance, nodeList *corev1.NodeList, ruObj *upgrademgrv1alpha1.RollingUpgrade) string {
 	node := r.getNodeFromAsg(i, nodeList, ruObj)
 	if node == nil {
-		log.Printf("%s: Node name for instance %s not found\n", ruObj.Name, *i.InstanceId)
+		r.info(ruObj, "Node name for instance not found", "instanceID", *i.InstanceId)
 		return ""
 	}
 	return node.Name
@@ -443,12 +443,12 @@ func (r *RollingUpgradeReconciler) getNodeFromAsg(i *autoscaling.Instance, nodeL
 		tokens := strings.Split(n.Spec.ProviderID, "/")
 		justID := tokens[len(tokens)-1]
 		if *i.InstanceId == justID {
-			log.Printf("%s: Found instance %s, name %s\n", ruObj.Name, justID, n.Name)
+			r.info(ruObj, "Found instance", "instanceID", justID, "instanceName", n.Name)
 			return &n
 		}
 	}
 
-	log.Printf("%s: Node for instance %s not found\n", ruObj.Name, *i.InstanceId)
+	r.info(ruObj, "Node for instance not found", "instanceID", *i.InstanceId)
 	return nil
 }
 
@@ -458,18 +458,17 @@ func (r *RollingUpgradeReconciler) populateAsg(ruObj *upgrademgrv1alpha1.Rolling
 			aws.String(ruObj.Spec.AsgName),
 		},
 	}
-
 	result, err := r.ASGClient.DescribeAutoScalingGroups(input)
 	if err != nil {
-		log.Println(err.Error())
-		return errors.New(ruObj.Name + ": Failed to describe autoscaling group: " + err.Error())
+		r.error(ruObj, err, "Failed to describe autoscaling group")
+		return errors.Wrap(err, ruObj.Name+": Failed to describe autoscaling group")
 	}
 
 	if len(result.AutoScalingGroups) == 0 {
-		log.Printf("%s: No ASG found with name %s!\n", ruObj.Name, ruObj.Spec.AsgName)
+		r.info(ruObj, "%s: No ASG found with name %s!\n", ruObj.Name, ruObj.Spec.AsgName)
 		return errors.New("No ASG found")
 	} else if len(result.AutoScalingGroups) > 1 {
-		log.Printf("%s: Too many asgs found with name %d!\n", ruObj.Name, len(result.AutoScalingGroups))
+		r.info(ruObj, "%s: Too many asgs found with name %d!\n", ruObj.Name, len(result.AutoScalingGroups))
 		return errors.New("Too many ASGs")
 	}
 
@@ -483,8 +482,8 @@ func (r *RollingUpgradeReconciler) populateNodeList(ruObj *upgrademgrv1alpha1.Ro
 	nodeList, err := nodeInterface.List(metav1.ListOptions{})
 	if err != nil {
 		msg := "Failed to get all nodes in the cluster: " + err.Error()
-		log.Printf("%s: %s", ruObj.Name, msg)
-		return errors.New(ruObj.Name + ": Failed to get all nodes in the cluster: " + err.Error())
+		r.info(ruObj, msg)
+		return errors.Wrap(err, ruObj.Name+": Failed to get all nodes in the cluster")
 	}
 	r.NodeList = nodeList
 	return nil
@@ -528,13 +527,13 @@ func (r *RollingUpgradeReconciler) runRestack(ctx *context.Context, ruObj *upgra
 		return 0, fmt.Errorf("Unable to load ASG with name: %s", ruObj.Name)
 	}
 
-	log.Printf("Nodes in ASG %s that *might* need to be updated: %d\n", *asg.AutoScalingGroupName, len(asg.Instances))
+	r.info(ruObj, "Nodes in ASG that *might* need to be updated", "asgName", *asg.AutoScalingGroupName, "asgSize", len(asg.Instances))
 
 	// No further processing is required if ASG doesn't have an instance running
 	totalNodes := len(asg.Instances)
 	// No further processing is required if ASG doesn't have an instance running
 	if totalNodes == 0 {
-		log.Printf("Total nodes found for %s is 0", ruObj.Name)
+		r.info(ruObj, "Total nodes found for %s is 0", ruObj.Name)
 		return 0, nil
 	}
 
@@ -549,7 +548,7 @@ func (r *RollingUpgradeReconciler) runRestack(ctx *context.Context, ruObj *upgra
 
 	inProgress, err := r.getInProgressInstances(asg.Instances)
 	if err != nil {
-		log.Errorf("Failed to acquire in-progress instances, %v", err)
+		r.error(ruObj, err, "Failed to acquire in-progress instances")
 	}
 
 	for processedInstances < totalNodes {
@@ -557,12 +556,12 @@ func (r *RollingUpgradeReconciler) runRestack(ctx *context.Context, ruObj *upgra
 		if len(inProgress) == 0 {
 			// Fetch instances to update from node selector
 			instances = nodeSelector.SelectNodesForRestack(r.ClusterState)
-			log.Printf("selected instances for rotation: %+v", instances)
+			r.info(ruObj, fmt.Sprintf("selected instances for rotation: %+v", instances))
 		} else {
 			// Prefer in progress instances over new ones
 			instances = inProgress
 			inProgress = []*autoscaling.Instance{}
-			log.Printf("found in progress instances: %+v", instances)
+			r.info(ruObj, fmt.Sprintf("found in progress instances: %+v", instances))
 		}
 
 		if instances == nil {
@@ -570,7 +569,7 @@ func (r *RollingUpgradeReconciler) runRestack(ctx *context.Context, ruObj *upgra
 				"No instances available for update across all AZ's for %s. Processed %d of total %d instances",
 				ruObj.Name, processedInstances, totalNodes)
 			// No instances fetched from any AZ, stop processing
-			log.Print(errorMessage)
+			r.info(ruObj, errorMessage)
 
 			// this should never be case, return error
 			return processedInstances, errors.New(errorMessage)
@@ -590,9 +589,9 @@ func (r *RollingUpgradeReconciler) runRestack(ctx *context.Context, ruObj *upgra
 func (r *RollingUpgradeReconciler) finishExecution(finalStatus string, nodesProcessed int, ctx *context.Context, ruObj *upgrademgrv1alpha1.RollingUpgrade) (reconcile.Result, error) {
 	// delete the entry instances of the ASG
 	r.ClusterState.deleteEntryOfAsg(ruObj.Spec.AsgName)
-	log.Printf("Deleted the entries of ASG %s in the cluster store for %s", ruObj.Spec.AsgName, ruObj.Name)
+	r.info(ruObj, "Deleted the entries of ASG in the cluster store", "asgName", ruObj.Spec.AsgName)
 
-	log.Printf("Marked object %s as %s", ruObj.Name, finalStatus)
+	r.info(ruObj, "Marked object as", "finalStatus", finalStatus)
 	endTime := time.Now()
 	ruObj.Status.EndTime = endTime.Format(time.RFC3339)
 	ruObj.Status.CurrentStatus = finalStatus
@@ -600,43 +599,42 @@ func (r *RollingUpgradeReconciler) finishExecution(finalStatus string, nodesProc
 
 	startTime, err := time.Parse(time.RFC3339, ruObj.Status.StartTime)
 	if err != nil {
-		log.Printf("Failed to calculate totalProcessingTime for %s", ruObj.Name)
+		r.info(ruObj, "Failed to calculate totalProcessingTime")
 	} else {
 		ruObj.Status.TotalProcessingTime = endTime.Sub(startTime).String()
 	}
 	MarkObjForCleanup(ruObj)
 	if err := r.Status().Update(*ctx, ruObj); err != nil {
-		log.Errorf("failed to update status: %v", err)
+		r.error(ruObj, err, "failed to update status")
 	}
 	r.admissionMap.Delete(ruObj.Name)
-	log.Printf("Deleted %s from admission map %p", ruObj.Name, &r.admissionMap)
+	r.info(ruObj, "Deleted from admission map ", "admissionMap", &r.admissionMap)
 	return reconcile.Result{}, nil
 }
 
 // Process actually performs the ec2-instance restacking.
 func (r *RollingUpgradeReconciler) Process(ctx *context.Context,
 	ruObj *upgrademgrv1alpha1.RollingUpgrade) (reconcile.Result, error) {
-	logr := r.Log.WithValues("rollingupgrade", ruObj.Name)
 
 	// If the object is being deleted, nothing to do.
 	if !ruObj.DeletionTimestamp.IsZero() {
-		logr.Info("Object is being deleted. No more processing")
+		r.info(ruObj, "Object is being deleted. No more processing")
 		r.admissionMap.Delete(ruObj.Name)
-		logr.Info("Deleted object from admission map")
+		r.info(ruObj, "Deleted object from admission map")
 		return reconcile.Result{}, nil
 	}
 
 	if ruObj.Status.CurrentStatus == StatusComplete ||
 		ruObj.Status.CurrentStatus == StatusError {
-		logr.Info("No more processing", "Object state", ruObj.Status.CurrentStatus)
+		r.info(ruObj, "No more processing", "currentStatus", ruObj.Status.CurrentStatus)
 
 		if exists := ruObj.ObjectMeta.Annotations[JanitorAnnotation]; exists == "" {
-			logr.Info("Marking object for deletion")
+			r.info(ruObj, "Marking object for deletion")
 			MarkObjForCleanup(ruObj)
 		}
 
 		r.admissionMap.Delete(ruObj.Name)
-		logr.Info("Deleted object from admission map")
+		r.info(ruObj, "Deleted object from admission map")
 		return reconcile.Result{}, nil
 	}
 
@@ -654,7 +652,7 @@ func (r *RollingUpgradeReconciler) Process(ctx *context.Context,
 
 	asg, err := r.GetAutoScalingGroup(ruObj.Name)
 	if err != nil {
-		log.Errorf("Unable to load ASG with name: %s", ruObj.Name)
+		r.error(ruObj, err, "Unable to load ASG for rolling upgrade")
 		return r.finishExecution(StatusError, 0, ctx, ruObj)
 	}
 
@@ -665,13 +663,13 @@ func (r *RollingUpgradeReconciler) Process(ctx *context.Context,
 	ruObj.Status.TotalNodes = len(asg.Instances)
 
 	if err := r.Status().Update(*ctx, ruObj); err != nil {
-		log.Errorf("failed to update status: %v", err)
+		r.error(ruObj, err, "failed to update status")
 	}
 
 	// Run the restack that actually performs the rolling update.
 	nodesProcessed, err := r.runRestack(ctx, ruObj, KubeCtlBinary)
 	if err != nil {
-		log.Errorf("%s: failed to runRestack: %v", ruObj.Name, err)
+		r.error(ruObj, err, "Failed to runRestack")
 		return r.finishExecution(StatusError, nodesProcessed, ctx, ruObj)
 	}
 
@@ -704,7 +702,6 @@ func MarkObjForCleanup(ruObj *upgrademgrv1alpha1.RollingUpgrade) {
 // and the details in the RollingUpgrade.Spec
 func (r *RollingUpgradeReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
 	ctx := context.Background()
-	logr := r.Log.WithValues("rollingupgrade", req.NamespacedName)
 
 	// Fetch the RollingUpgrade instance
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{}
@@ -714,7 +711,7 @@ func (r *RollingUpgradeReconciler) Reconcile(req ctrl.Request) (ctrl.Result, err
 			// Object not found, return. Created objects are automatically garbage collected.
 			// For additional cleanup logic use finalizers.
 			r.admissionMap.Delete(req.Name)
-			logr.Info("Deleted object from map", "name", req.Name)
+			r.info(ruObj, "Deleted object from map", "name", req.NamespacedName)
 			return ctrl.Result{}, nil
 		}
 		// Error reading the object - requeue the request.
@@ -723,33 +720,33 @@ func (r *RollingUpgradeReconciler) Reconcile(req ctrl.Request) (ctrl.Result, err
 
 	// Setting default values for the Strategy in rollup object
 	r.setDefaultsForRollingUpdateStrategy(ruObj)
-	log.Printf("Default strategy settings applied for %s, update strategy - %+v", ruObj.Name, ruObj.Spec.Strategy)
+	r.info(ruObj, "Default strategy settings applied.", "updateStrategy", ruObj.Spec.Strategy)
 
 	err = r.validateRollingUpgradeObj(ruObj)
 	if err != nil {
-		log.Printf("Validation failed for %s, error: %v", ruObj.Name, err.Error())
+		r.error(ruObj, err, "Validation failed")
 		return reconcile.Result{}, err
 	}
 
 	result, ok := r.admissionMap.Load(ruObj.Name)
 	if ok {
 		if result == "processing" {
-			logr.Info("Found obj in map:", "name", ruObj.Name)
-			logr.Info("Object already being processed", "name", ruObj.Name)
+			r.info(ruObj, "Found obj in map:", "name", ruObj.Name)
+			r.info(ruObj, "Object already being processed", "name", ruObj.Name)
 		} else {
-			logr.Info("Sync map with invalid entry for ", "name", ruObj.Name)
+			r.info(ruObj, "Sync map with invalid entry for ", "name", ruObj.Name)
 		}
 	} else {
 		_, err := r.Process(&ctx, ruObj)
 		if err != nil {
-			log.Printf("Processing failed for %s, error: %v", ruObj.Name, err.Error())
+			r.error(ruObj, err, "Processing failed")
 		}
-		logr.Info("Adding obj to map: ", "name", ruObj.Name)
+		r.info(ruObj, "Adding obj to map: ", "name", ruObj.Name)
 		r.admissionMap.Store(ruObj.Name, "processing")
 	}
 
 	if err = r.Update(ctx, ruObj); err != nil {
-		log.Errorf("failed to update custom resource: %v", err)
+		r.error(ruObj, err, "failed to update custom resource")
 	}
 	return ctrl.Result{}, nil
 }
@@ -764,7 +761,7 @@ func (r *RollingUpgradeReconciler) SetupWithManager(mgr ctrl.Manager) error {
 }
 
 func (r *RollingUpgradeReconciler) setStateTag(ruObj *upgrademgrv1alpha1.RollingUpgrade, instanceID string, state string) error {
-	log.Printf("%v: setting instance %q state to %q", ruObj.Name, instanceID, state)
+	r.info(ruObj, "setting instance state", "instanceID", instanceID, "instanceState", state)
 	err := tagEC2instance(instanceID, EC2StateTagKey, state, r.EC2Client)
 	if err != nil {
 		return err
@@ -780,13 +777,12 @@ func (r *RollingUpgradeReconciler) validateRollingUpgradeObj(ruObj *upgrademgrv1
 	if strategy == nilStrategy {
 		return nil
 	}
-
 	// validating the maxUnavailable value
 	if strategy.MaxUnavailable.Type == 0 {
 		if strategy.MaxUnavailable.IntVal <= 0 {
 			err := errors.New(fmt.Sprintf("%s: Invalid value for maxUnavailable - %d",
 				ruObj.Name, strategy.MaxUnavailable.IntVal))
-			log.Print(err)
+			r.error(ruObj, err, "Invalid value for maxUnavailable", "value", strategy.MaxUnavailable.IntVal)
 			return err
 		}
 	} else if strategy.MaxUnavailable.Type == 1 {
@@ -795,7 +791,7 @@ func (r *RollingUpgradeReconciler) validateRollingUpgradeObj(ruObj *upgrademgrv1
 		if intValue <= 0 || intValue > 100 {
 			err := errors.New(fmt.Sprintf("%s: Invalid value for maxUnavailable - %s",
 				ruObj.Name, strategy.MaxUnavailable.StrVal))
-			log.Print(err)
+			r.error(ruObj, err, "Invalid value for maxUnavailable", "value", strategy.MaxUnavailable.StrVal)
 			return err
 		}
 	}
@@ -804,7 +800,7 @@ func (r *RollingUpgradeReconciler) validateRollingUpgradeObj(ruObj *upgrademgrv1
 	if strategy.Type != upgrademgrv1alpha1.RandomUpdateStrategy &&
 		strategy.Type != upgrademgrv1alpha1.UniformAcrossAzUpdateStrategy {
 		err := errors.New(fmt.Sprintf("%s: Invalid value for strategy type - %s", ruObj.Name, strategy.Type))
-		log.Print(err)
+		r.error(ruObj, err, "Invalid value for strategy type", "value", strategy.Type)
 		return err
 	}
 	return nil
@@ -817,7 +813,7 @@ func (r *RollingUpgradeReconciler) setDefaultsForRollingUpdateStrategy(ruObj *up
 	// Default behaviour should be to update one node at a time and should wait for kubectl drain completion
 	var nilStrategy = upgrademgrv1alpha1.UpdateStrategy{}
 	if ruObj.Spec.Strategy == nilStrategy {
-		log.Printf("Update strategy not set on the rollup object - %s, setting the default strategy.", ruObj.Name)
+		r.info(ruObj, "Update strategy not set on the rollup object, setting the default strategy.")
 		strategy := upgrademgrv1alpha1.UpdateStrategy{
 			Type:           upgrademgrv1alpha1.RandomUpdateStrategy,
 			Mode:           upgrademgrv1alpha1.UpdateStrategyModeLazy,
@@ -965,10 +961,10 @@ func (r *RollingUpgradeReconciler) UpdateInstance(ctx *context.Context,
 	// there is no need to refresh it.
 	targetInstanceID := aws.StringValue(i.InstanceId)
 	if !requiresRefresh(i, launchDefinition) {
-		log.Printf("Ignoring %s since it has the correct launch-config", targetInstanceID)
+		r.info(ruObj, "Ignoring since it has the correct launch-config", "instanceID", targetInstanceID)
 		ruObj.Status.NodesProcessed = ruObj.Status.NodesProcessed + 1
 		if err := r.Status().Update(*ctx, ruObj); err != nil {
-			log.Errorf("failed to update status: %v", err)
+			r.error(ruObj, err, "failed to update status")
 		}
 		ch <- nil
 		return
@@ -996,10 +992,10 @@ func (r *RollingUpgradeReconciler) UpdateInstance(ctx *context.Context,
 
 	mode := ruObj.Spec.Strategy.Mode.String()
 	if strings.ToLower(mode) == upgrademgrv1alpha1.UpdateStrategyModeEager.String() {
-		log.Printf("%v: starting replacement with eager mode", ruObj.Name)
+		r.info(ruObj, "starting replacement with eager mode", "mode", mode)
 		r.UpdateInstanceEager(ruObj, nodeName, targetInstanceID, KubeCtlCall, ch)
 	} else if strings.ToLower(mode) == upgrademgrv1alpha1.UpdateStrategyModeLazy.String() {
-		log.Printf("%v: starting replacement with lazy mode", ruObj.Name)
+		r.info(ruObj, "starting replacement with lazy mode", "mode", mode)
 		r.DrainTerminate(ruObj, nodeName, targetInstanceID, KubeCtlCall, ch)
 	}
 
@@ -1010,7 +1006,7 @@ func (r *RollingUpgradeReconciler) UpdateInstance(ctx *context.Context,
 	}
 
 	if !unjoined {
-		log.Warnf("%v: termination waiter completed but %s is still joined, will proceed with upgrade", ruObj.Name, nodeName)
+		r.info(ruObj, "termination waiter completed but node is still joined, will proceed with upgrade", "nodeName", nodeName)
 	}
 
 	// set the EC2 tag indicating the state to completed
@@ -1022,7 +1018,7 @@ func (r *RollingUpgradeReconciler) UpdateInstance(ctx *context.Context,
 
 	ruObj.Status.NodesProcessed = ruObj.Status.NodesProcessed + 1
 	if err := r.Status().Update(*ctx, ruObj); err != nil {
-		log.Errorf("failed to update status: %v", err)
+		r.error(ruObj, err, "failed to update status")
 	}
 
 	// TODO(shri): Run validate. How?
@@ -1050,3 +1046,18 @@ func requiresRefresh(ec2Instance *autoscaling.Instance, definition *launchDefini
 	}
 	return false
 }
+
+// logger creates logger for rolling upgrade.
+func (r *RollingUpgradeReconciler) logger(ruObj *upgrademgrv1alpha1.RollingUpgrade) logr.Logger {
+	return r.Log.WithValues("rollingupgrade", ruObj.Name)
+}
+
+// info logs message with Info level for the specified rolling upgrade.
+func (r *RollingUpgradeReconciler) info(ruObj *upgrademgrv1alpha1.RollingUpgrade, msg string, keysAndValues ...interface{}) {
+	r.logger(ruObj).Info(msg, keysAndValues...)
+}
+
+// error logs message with Error level for the specified rolling upgrade.
+func (r *RollingUpgradeReconciler) error(ruObj *upgrademgrv1alpha1.RollingUpgrade, err error, msg string, keysAndValues ...interface{}) {
+	r.logger(ruObj).Error(err, msg, keysAndValues...)
+}


Test patch:
diff --git a/controllers/rollingupgrade_controller_test.go b/controllers/rollingupgrade_controller_test.go
index ecd2676..b887503 100644
--- a/controllers/rollingupgrade_controller_test.go
+++ b/controllers/rollingupgrade_controller_test.go
@@ -10,6 +10,7 @@ import (
 	"time"
 
 	"k8s.io/client-go/kubernetes/scheme"
+	log2 "sigs.k8s.io/controller-runtime/pkg/log"
 
 	"github.com/keikoproj/aws-sdk-go-cache/cache"
 	"github.com/keikoproj/upgrade-manager/pkg/log"
@@ -42,8 +43,6 @@ import (
 
 var c client.Client
 
-var defaultMsgPrefix = "ru-foo"
-
 func TestMain(m *testing.M) {
 	testEnv = &envtest.Environment{
 		CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
@@ -55,7 +54,9 @@ func TestMain(m *testing.M) {
 
 func TestEchoScript(t *testing.T) {
 	g := gomega.NewGomegaWithT(t)
-	out, err := runScript("echo hello", false, defaultMsgPrefix)
+	ru := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
+	r := &RollingUpgradeReconciler{Log: log2.NullLogger{}}
+	out, err := r.runScript("echo hello", false, ru)
 
 	g.Expect(err).To(gomega.BeNil())
 	g.Expect(out).To(gomega.Equal("hello\n"))
@@ -63,7 +64,9 @@ func TestEchoScript(t *testing.T) {
 
 func TestEchoBackgroundScript(t *testing.T) {
 	g := gomega.NewGomegaWithT(t)
-	out, err := runScript("echo background", true, defaultMsgPrefix)
+	ru := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
+	r := &RollingUpgradeReconciler{Log: log2.NullLogger{}}
+	out, err := r.runScript("echo background", true, ru)
 
 	g.Expect(err).To(gomega.BeNil())
 	g.Expect(out).To(gomega.Equal(""))
@@ -71,7 +74,9 @@ func TestEchoBackgroundScript(t *testing.T) {
 
 func TestRunScriptFailure(t *testing.T) {
 	g := gomega.NewGomegaWithT(t)
-	out, err := runScript("echo this will fail; exit 1", false, defaultMsgPrefix)
+	ru := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
+	r := &RollingUpgradeReconciler{Log: log2.NullLogger{}}
+	out, err := r.runScript("echo this will fail; exit 1", false, ru)
 
 	g.Expect(err).To(gomega.Not(gomega.BeNil()))
 	g.Expect(out).To(gomega.Not(gomega.Equal("")))
@@ -87,6 +92,7 @@ func TestErrorStatusMarkJanitor(t *testing.T) {
 
 	rcRollingUpgrade := &RollingUpgradeReconciler{Client: mgr.GetClient(),
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
+		Log:             log2.NullLogger{},
 		admissionMap:    sync.Map{},
 		ruObjNameToASG:  sync.Map{},
 		ClusterState:    NewClusterState(),
@@ -134,7 +140,7 @@ func TestPreDrainScriptSuccess(t *testing.T) {
 	instance := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
 	instance.Spec.PreDrain.Script = "echo 'Predrain script ran without error'"
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	err := rcRollingUpgrade.preDrainHelper(instance)
 	g.Expect(err).To(gomega.BeNil())
 }
@@ -145,7 +151,7 @@ func TestPreDrainScriptError(t *testing.T) {
 	instance := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
 	instance.Spec.PreDrain.Script = "exit 1"
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	err := rcRollingUpgrade.preDrainHelper(instance)
 	g.Expect(err.Error()).To(gomega.HavePrefix("Failed to run preDrain script"))
 }
@@ -158,7 +164,7 @@ func TestPostDrainHelperPostDrainScriptSuccess(t *testing.T) {
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
 	ruObj.Spec.PostDrain.Script = "echo Hello, postDrainScript!"
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	err := rcRollingUpgrade.postDrainHelper(ruObj, mockNode, mockKubeCtlCall)
 
 	g.Expect(err).To(gomega.BeNil())
@@ -172,7 +178,7 @@ func TestPostDrainHelperPostDrainScriptError(t *testing.T) {
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
 	ruObj.Spec.PostDrain.Script = "exit 1"
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	err := rcRollingUpgrade.postDrainHelper(ruObj, mockNode, mockKubeCtlCall)
 
 	g.Expect(err).To(gomega.Not(gomega.BeNil()))
@@ -187,7 +193,7 @@ func TestPostDrainHelperPostDrainWaitScriptSuccess(t *testing.T) {
 	ruObj.Spec.PostDrain.PostWaitScript = "echo Hello, postDrainWaitScript!"
 	ruObj.Spec.PostDrainDelaySeconds = 0
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	err := rcRollingUpgrade.postDrainHelper(ruObj, mockNode, mockKubeCtlCall)
 
 	g.Expect(err).To(gomega.BeNil())
@@ -202,7 +208,7 @@ func TestPostDrainHelperPostDrainWaitScriptError(t *testing.T) {
 	ruObj.Spec.PostDrain.PostWaitScript = "exit 1"
 	ruObj.Spec.PostDrainDelaySeconds = 0
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	err := rcRollingUpgrade.postDrainHelper(ruObj, mockNode, mockKubeCtlCall)
 
 	g.Expect(err).To(gomega.Not(gomega.BeNil()))
@@ -214,7 +220,7 @@ func TestDrainNodeSuccess(t *testing.T) {
 	mockKubeCtlCall := "echo"
 
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 
 	err := rcRollingUpgrade.DrainNode(ruObj, mockNode, mockKubeCtlCall, ruObj.Spec.Strategy.DrainTimeout)
 	g.Expect(err).To(gomega.BeNil())
@@ -227,7 +233,7 @@ func TestDrainNodePreDrainError(t *testing.T) {
 
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
 	ruObj.Spec.PreDrain.Script = "exit 1"
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 
 	err := rcRollingUpgrade.DrainNode(ruObj, mockNode, mockKubeCtlCall, ruObj.Spec.Strategy.DrainTimeout)
 	g.Expect(err).To(gomega.Not(gomega.BeNil()))
@@ -240,7 +246,7 @@ func TestDrainNodePostDrainScriptError(t *testing.T) {
 
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
 	ruObj.Spec.PostDrain.Script = "exit 1"
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 
 	err := rcRollingUpgrade.DrainNode(ruObj, mockNode, mockKubeCtlCall, ruObj.Spec.Strategy.DrainTimeout)
 	g.Expect(err).To(gomega.Not(gomega.BeNil()))
@@ -253,7 +259,7 @@ func TestDrainNodePostDrainWaitScriptError(t *testing.T) {
 
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
 	ruObj.Spec.PostDrain.PostWaitScript = "exit 1"
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 
 	err := rcRollingUpgrade.DrainNode(ruObj, mockNode, mockKubeCtlCall, ruObj.Spec.Strategy.DrainTimeout)
 	g.Expect(err).To(gomega.Not(gomega.BeNil()))
@@ -267,7 +273,7 @@ func TestDrainNodePostDrainFailureToDrainNotFound(t *testing.T) {
 	mockKubeCtlCall := "echo 'Error from server (NotFound)'; exit 1;"
 
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 
 	err := rcRollingUpgrade.DrainNode(ruObj, mockNode, mockKubeCtlCall, ruObj.Spec.Strategy.DrainTimeout)
 	g.Expect(err).To(gomega.BeNil())
@@ -286,12 +292,19 @@ func TestDrainNodePostDrainFailureToDrain(t *testing.T) {
 			Strategy: upgrademgrv1alpha1.UpdateStrategy{DrainTimeout: -1},
 		},
 	}
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 
 	err := rcRollingUpgrade.DrainNode(ruObj, mockNode, mockKubeCtlCall, ruObj.Spec.Strategy.DrainTimeout)
 	g.Expect(err).To(gomega.Not(gomega.BeNil()))
 }
 
+func createReconciler() *RollingUpgradeReconciler {
+	return &RollingUpgradeReconciler{
+		ClusterState: NewClusterState(),
+		Log:          log2.NullLogger{},
+	}
+}
+
 type MockEC2 struct {
 	ec2iface.EC2API
 	reservations []*ec2.Reservation
@@ -419,6 +432,7 @@ func TestTerminateNodeSuccess(t *testing.T) {
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		ClusterState: NewClusterState(),
+		Log:          log2.NullLogger{},
 		EC2Client:    MockEC2{},
 		ASGClient: MockAutoscalingGroup{
 			errorFlag: false,
@@ -440,6 +454,7 @@ func TestTerminateNodeErrorNotFound(t *testing.T) {
 		nil)}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		ClusterState: NewClusterState(),
+		Log:          log2.NullLogger{},
 		ASGClient:    mockAutoscalingGroup,
 		EC2Client:    MockEC2{},
 	}
@@ -459,6 +474,7 @@ func TestTerminateNodeErrorOtherError(t *testing.T) {
 
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		ClusterState: NewClusterState(),
+		Log:          log2.NullLogger{},
 		ASGClient:    mockAutoscalingGroup,
 		EC2Client:    MockEC2{},
 	}
@@ -475,6 +491,7 @@ func TestTerminateNodePostTerminateScriptSuccess(t *testing.T) {
 	mockAutoscalingGroup := MockAutoscalingGroup{errorFlag: false, awsErr: nil}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		ClusterState: NewClusterState(),
+		Log:          log2.NullLogger{},
 		ASGClient:    mockAutoscalingGroup,
 		EC2Client:    MockEC2{},
 	}
@@ -491,6 +508,7 @@ func TestTerminateNodePostTerminateScriptErrorNotFoundFromServer(t *testing.T) {
 	mockAutoscalingGroup := MockAutoscalingGroup{errorFlag: false, awsErr: nil}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		ClusterState: NewClusterState(),
+		Log:          log2.NullLogger{},
 		ASGClient:    mockAutoscalingGroup,
 		EC2Client:    MockEC2{},
 	}
@@ -507,6 +525,7 @@ func TestTerminateNodePostTerminateScriptErrorOtherError(t *testing.T) {
 	mockAutoscalingGroup := MockAutoscalingGroup{errorFlag: false, awsErr: nil}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		ClusterState: NewClusterState(),
+		Log:          log2.NullLogger{},
 		ASGClient:    mockAutoscalingGroup,
 		EC2Client:    MockEC2{},
 	}
@@ -551,7 +570,7 @@ func TestGetNodeNameFoundNode(t *testing.T) {
 
 	nodeList := corev1.NodeList{Items: []corev1.Node{fooNode1, fooNode2, correctNode}}
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
-	rcRollingUpgrade := RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	name := rcRollingUpgrade.getNodeName(&autoscalingInstance, &nodeList, ruObj)
 
 	g.Expect(name).To(gomega.Equal("correctNode"))
@@ -570,7 +589,7 @@ func TestGetNodeNameMissingNode(t *testing.T) {
 
 	nodeList := corev1.NodeList{Items: []corev1.Node{fooNode1, fooNode2}}
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
-	rcRollingUpgrade := RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	name := rcRollingUpgrade.getNodeName(&autoscalingInstance, &nodeList, ruObj)
 
 	g.Expect(name).To(gomega.Equal(""))
@@ -588,7 +607,7 @@ func TestGetNodeFromAsgFoundNode(t *testing.T) {
 	correctNode := corev1.Node{Spec: corev1.NodeSpec{ProviderID: "fake-separator/" + mockInstanceID}}
 
 	nodeList := corev1.NodeList{Items: []corev1.Node{fooNode1, fooNode2, correctNode}}
-	rcRollingUpgrade := RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
 	node := rcRollingUpgrade.getNodeFromAsg(&autoscalingInstance, &nodeList, ruObj)
 
@@ -606,7 +625,7 @@ func TestGetNodeFromAsgMissingNode(t *testing.T) {
 	fooNode2 := corev1.Node{Spec: corev1.NodeSpec{ProviderID: "foo-bar/1234501"}}
 
 	nodeList := corev1.NodeList{Items: []corev1.Node{fooNode1, fooNode2}}
-	rcRollingUpgrade := RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
 	node := rcRollingUpgrade.getNodeFromAsg(&autoscalingInstance, &nodeList, ruObj)
 
@@ -621,6 +640,7 @@ func TestPopulateAsgSuccess(t *testing.T) {
 		Spec:     upgrademgrv1alpha1.RollingUpgradeSpec{AsgName: "correct-asg"}}
 
 	rcRollingUpgrade := &RollingUpgradeReconciler{
+		Log:          log2.NullLogger{},
 		ClusterState: NewClusterState(),
 		ASGClient:    &MockAutoscalingGroup{},
 		EC2Client:    MockEC2{},
@@ -645,6 +665,7 @@ func TestPopulateAsgTooMany(t *testing.T) {
 		Spec:     upgrademgrv1alpha1.RollingUpgradeSpec{AsgName: "too-many"}}
 
 	rcRollingUpgrade := &RollingUpgradeReconciler{
+		Log:          log2.NullLogger{},
 		ClusterState: NewClusterState(),
 		ASGClient:    &MockAutoscalingGroup{},
 		EC2Client:    MockEC2{},
@@ -663,6 +684,7 @@ func TestPopulateAsgNone(t *testing.T) {
 		Spec:     upgrademgrv1alpha1.RollingUpgradeSpec{AsgName: "no-asg-at-all"}}
 
 	rcRollingUpgrade := &RollingUpgradeReconciler{
+		Log:          log2.NullLogger{},
 		ClusterState: NewClusterState(),
 		ASGClient:    &MockAutoscalingGroup{},
 		EC2Client:    MockEC2{},
@@ -690,6 +712,7 @@ func TestParallelAsgTracking(t *testing.T) {
 	expectedAsgB := autoscaling.Group{AutoScalingGroupName: &asgBName}
 
 	rcRollingUpgrade := &RollingUpgradeReconciler{
+		Log:          log2.NullLogger{},
 		ClusterState: NewClusterState(),
 		ASGClient:    &MockAutoscalingGroup{},
 		EC2Client:    MockEC2{},
@@ -742,7 +765,7 @@ func TestPopulateNodeListSuccess(t *testing.T) {
 
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		TypeMeta: metav1.TypeMeta{Kind: "RollingUpgrade", APIVersion: "v1alpha1"}}
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 
 	mockNodeListInterface := &MockNodeList{errorFlag: false}
 	err := rcRollingUpgrade.populateNodeList(ruObj, mockNodeListInterface)
@@ -758,7 +781,7 @@ func TestPopulateNodeListError(t *testing.T) {
 
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		TypeMeta: metav1.TypeMeta{Kind: "RollingUpgrade", APIVersion: "v1alpha1"}}
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 
 	mockNodeListInterface := &MockNodeList{errorFlag: true}
 	err := rcRollingUpgrade.populateNodeList(ruObj, mockNodeListInterface)
@@ -781,6 +804,7 @@ func TestFinishExecutionCompleted(t *testing.T) {
 
 	rcRollingUpgrade := &RollingUpgradeReconciler{Client: mgr.GetClient(),
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
+		Log:             log2.NullLogger{},
 		admissionMap:    sync.Map{},
 		ruObjNameToASG:  sync.Map{},
 		ClusterState:    NewClusterState(),
@@ -808,6 +832,7 @@ func TestFinishExecutionError(t *testing.T) {
 	c = mgr.GetClient()
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
 		admissionMap:    sync.Map{},
 		ruObjNameToASG:  sync.Map{},
@@ -860,6 +885,7 @@ func TestRunRestackSuccessOneNode(t *testing.T) {
 	nodeList := corev1.NodeList{Items: []corev1.Node{fooNode1, fooNode2, correctNode}}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       MockAutoscalingGroup{},
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
@@ -910,6 +936,7 @@ func TestRunRestackSuccessMultipleNodes(t *testing.T) {
 	nodeList := corev1.NodeList{Items: []corev1.Node{fooNode1, fooNode2, correctNode, correctNode2}}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       MockAutoscalingGroup{},
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
@@ -949,6 +976,7 @@ func TestRunRestackSameLaunchConfig(t *testing.T) {
 
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       MockAutoscalingGroup{},
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
@@ -972,6 +1000,7 @@ func TestRunRestackRollingUpgradeNotInMap(t *testing.T) {
 
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
+		Log:          log2.NullLogger{},
 		ClusterState: NewClusterState(),
 		ASGClient:    MockAutoscalingGroup{},
 		EC2Client:    MockEC2{},
@@ -1008,6 +1037,7 @@ func TestRunRestackRollingUpgradeNodeNameNotFound(t *testing.T) {
 	emptyNodeList := corev1.NodeList{}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       MockAutoscalingGroup{},
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
@@ -1055,6 +1085,7 @@ func TestRunRestackNoNodeName(t *testing.T) {
 	nodeList := corev1.NodeList{Items: []corev1.Node{fooNode1, fooNode2, correctNode}}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       MockAutoscalingGroup{},
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
@@ -1119,6 +1150,7 @@ func TestRunRestackDrainNodeFail(t *testing.T) {
 	nodeList := corev1.NodeList{Items: []corev1.Node{fooNode1, fooNode2, correctNode}}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       MockAutoscalingGroup{},
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
@@ -1179,6 +1211,7 @@ func TestRunRestackTerminateNodeFail(t *testing.T) {
 	nodeList := corev1.NodeList{Items: []corev1.Node{fooNode1, fooNode2, correctNode}}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       mockAutoscalingGroup,
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
@@ -1271,6 +1304,7 @@ func TestUniformAcrossAzUpdateSuccessMultipleNodes(t *testing.T) {
 	}}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       MockAutoscalingGroup{},
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
@@ -1328,6 +1362,7 @@ func TestUpdateInstances(t *testing.T) {
 	nodeList := corev1.NodeList{Items: []corev1.Node{fooNode1, fooNode2, correctNode, correctNode2}}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       MockAutoscalingGroup{},
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
@@ -1392,6 +1427,7 @@ func TestUpdateInstancesError(t *testing.T) {
 	nodeList := corev1.NodeList{Items: []corev1.Node{fooNode1, fooNode2, correctNode, correctNode2}}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       mockAutoScalingGroup,
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
@@ -1463,6 +1499,7 @@ func TestUpdateInstancesPartialError(t *testing.T) {
 	nodeList := corev1.NodeList{Items: []corev1.Node{fooNode1, fooNode2, correctNode, correctNode2}}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       mockAutoScalingGroup,
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
@@ -1496,6 +1533,7 @@ func TestUpdateInstancesWithZeroInstances(t *testing.T) {
 
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
 		admissionMap:    sync.Map{},
 		ruObjNameToASG:  sync.Map{},
@@ -1517,7 +1555,7 @@ func TestTestCallKubectlDrainWithoutDrainTimeout(t *testing.T) {
 	mockKubeCtlCall := "sleep 1; echo"
 	mockNodeName := "some-node-name"
 	mockAsgName := "some-asg"
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{AsgName: mockAsgName}}
 
@@ -1552,7 +1590,7 @@ func TestTestCallKubectlDrainWithDrainTimeout(t *testing.T) {
 
 	mockKubeCtlCall := "sleep 1; echo"
 	mockNodeName := "some-node-name"
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 
 	mockAsgName := "some-asg"
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
@@ -1591,7 +1629,7 @@ func TestTestCallKubectlDrainWithZeroDrainTimeout(t *testing.T) {
 
 	mockKubeCtlCall := "sleep 1; echo"
 	mockNodeName := "some-node-name"
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 
 	mockAsgName := "some-asg"
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
@@ -1630,7 +1668,7 @@ func TestTestCallKubectlDrainWithError(t *testing.T) {
 
 	mockKubeCtlCall := "cat xyz"
 	mockNodeName := "some-node-name"
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 
 	mockAsgName := "some-asg"
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
@@ -1667,7 +1705,7 @@ func TestTestCallKubectlDrainWithTimeoutOccurring(t *testing.T) {
 
 	mockKubeCtlCall := "sleep 1; echo"
 	mockNodeName := "some-node-name"
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 
 	mockAsgName := "some-asg"
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
@@ -1712,7 +1750,7 @@ func TestValidateRuObj(t *testing.T) {
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -1736,7 +1774,7 @@ func TestValidateruObjInvalidMaxUnavailable(t *testing.T) {
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -1760,7 +1798,7 @@ func TestValidateruObjMaxUnavailableZeroPercent(t *testing.T) {
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -1784,7 +1822,7 @@ func TestValidateruObjMaxUnavailableInt(t *testing.T) {
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -1808,7 +1846,7 @@ func TestValidateruObjMaxUnavailableIntZero(t *testing.T) {
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -1832,7 +1870,7 @@ func TestValidateruObjMaxUnavailableIntNegativeValue(t *testing.T) {
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -1856,7 +1894,7 @@ func TestValidateruObjWithStrategyAndDrainTimeoutOnly(t *testing.T) {
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -1878,7 +1916,7 @@ func TestValidateruObjWithoutStrategyOnly(t *testing.T) {
 	if err != nil {
 		fmt.Printf("Error occurred while unmarshalling RollingUpgrade object, error: %s", err.Error())
 	}
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	err = rcRollingUpgrade.validateRollingUpgradeObj(&ruObj)
 
 	g.Expect(err).To(gomega.BeNil())
@@ -1895,7 +1933,7 @@ func TestValidateruObjStrategyType(t *testing.T) {
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -1919,7 +1957,7 @@ func TestValidateruObjInvalidStrategyType(t *testing.T) {
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -1948,7 +1986,7 @@ type: randomUpdate
 		fmt.Printf("Error occurred while unmarshalling strategy yaml object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -1973,7 +2011,7 @@ func TestSetDefaultsForRollingUpdateStrategy(t *testing.T) {
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -1999,7 +2037,7 @@ func TestValidateruObjStrategyAfterSettingDefaults(t *testing.T) {
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -2024,7 +2062,7 @@ func TestValidateruObjStrategyAfterSettingDefaultsWithInvalidStrategyType(t *tes
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -2049,7 +2087,7 @@ func TestValidateruObjStrategyAfterSettingDefaultsWithOnlyDrainTimeout(t *testin
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -2074,7 +2112,7 @@ func TestValidateruObjStrategyAfterSettingDefaultsWithOnlyMaxUnavailable(t *test
 		fmt.Printf("Error occurred while unmarshalling strategy object, error: %s", err.Error())
 	}
 
-	rcRollingUpgrade := &RollingUpgradeReconciler{ClusterState: NewClusterState()}
+	rcRollingUpgrade := createReconciler()
 	ruObj := &upgrademgrv1alpha1.RollingUpgrade{
 		ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"},
 		Spec: upgrademgrv1alpha1.RollingUpgradeSpec{
@@ -2111,6 +2149,7 @@ func TestRunRestackNoNodeInAsg(t *testing.T) {
 	nodeList := corev1.NodeList{Items: []corev1.Node{}}
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       MockAutoscalingGroup{},
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
@@ -2149,6 +2188,7 @@ func TestWaitForTermination(t *testing.T) {
 
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),
 		admissionMap:    sync.Map{},
 		ruObjNameToASG:  sync.Map{},
@@ -2211,6 +2251,7 @@ func TestRunRestackWithNodesLessThanMaxUnavailable(t *testing.T) {
 
 	rcRollingUpgrade := &RollingUpgradeReconciler{
 		Client:          mgr.GetClient(),
+		Log:             log2.NullLogger{},
 		ASGClient:       MockAutoscalingGroup{},
 		EC2Client:       MockEC2{},
 		generatedClient: kubernetes.NewForConfigOrDie(mgr.GetConfig()),