Skip to content

Commit

Permalink
Merge pull request #153 from dharmjit/add_events
Browse files Browse the repository at this point in the history
Registered Events to k8s Event API for ByoMachine, ByoHost
  • Loading branch information
anusha94 authored Oct 26, 2021
2 parents 3ba26aa + 74ec3cb commit 8f727b4
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 16 deletions.
1 change: 1 addition & 0 deletions agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ func main() {
DefaultNetworkInterfaceName: registration.LocalHostRegistrar.ByoHostInfo.DefaultNetworkInterfaceName,
},
},
Recorder: mgr.GetEventRecorderFor("hostagent-controller"),
}
if err = hostReconciler.SetupWithManager(context.TODO(), mgr); err != nil {
klog.Errorf("unable to create controller, err=%v", err)
Expand Down
21 changes: 14 additions & 7 deletions agent/reconciler/host_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/vmware-tanzu/cluster-api-provider-byoh/agent/registration"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/util/conditions"
"sigs.k8s.io/cluster-api/util/patch"
Expand All @@ -29,6 +30,7 @@ type HostReconciler struct {
CmdRunner cloudinit.ICmdRunner
FileWriter cloudinit.IFileWriter
TemplateParser cloudinit.ITemplateParser
Recorder record.EventRecorder
}

const (
Expand Down Expand Up @@ -93,12 +95,14 @@ func (r *HostReconciler) reconcileNormal(ctx context.Context, byoHost *infrastru
bootstrapScript, err := r.getBootstrapScript(ctx, byoHost.Spec.BootstrapSecret.Name, byoHost.Spec.BootstrapSecret.Namespace)
if err != nil {
logger.Error(err, "error getting bootstrap script")
r.Recorder.Eventf(byoHost, corev1.EventTypeWarning, "ReadBootstrapSecretFailed", "bootstrap secret %s not found", byoHost.Spec.BootstrapSecret.Name)
return ctrl.Result{}, err
}

err = r.installK8sComponents(ctx, byoHost)
if err != nil {
logger.Error(err, "error in installing k8s components")
r.Recorder.Event(byoHost, corev1.EventTypeWarning, "InstallK8sComponentFailed", "k8s component installation failed")
conditions.MarkFalse(byoHost, infrastructurev1beta1.K8sComponentsInstallationSucceeded, infrastructurev1beta1.K8sComponentsInstallationFailedReason, clusterv1.ConditionSeverityInfo, "")
return ctrl.Result{}, err
}
Expand All @@ -112,12 +116,13 @@ func (r *HostReconciler) reconcileNormal(ctx context.Context, byoHost *infrastru
err = r.bootstrapK8sNode(ctx, bootstrapScript, byoHost)
if err != nil {
logger.Error(err, "error in bootstrapping k8s node")
_ = r.resetNode(ctx)
r.Recorder.Event(byoHost, corev1.EventTypeWarning, "BootstrapK8sNodeFailed", "k8s Node Bootstrap failed")
_ = r.resetNode(ctx, byoHost)
conditions.MarkFalse(byoHost, infrastructurev1beta1.K8sNodeBootstrapSucceeded, infrastructurev1beta1.CloudInitExecutionFailedReason, clusterv1.ConditionSeverityError, "")
return ctrl.Result{}, err
}
logger.Info("k8s node successfully bootstrapped")

r.Recorder.Event(byoHost, corev1.EventTypeNormal, "BootstrapK8sNodeSucceeded", "k8s Node Bootstraped")
conditions.MarkTrue(byoHost, infrastructurev1beta1.K8sNodeBootstrapSucceeded)
}

Expand Down Expand Up @@ -147,17 +152,17 @@ func (r *HostReconciler) SetupWithManager(ctx context.Context, mgr manager.Manag
}

// cleanup kubeadm dir to remove any stale config on the host
func (r HostReconciler) kubeadmDirCleanup(ctx context.Context) error {
func (r *HostReconciler) kubeadmDirCleanup(ctx context.Context) error {
logger := ctrl.LoggerFrom(ctx)
logger.Info("cleaning up kubeadm directory")
const kubeadmDir = "/run/kubeadm"
return os.RemoveAll(kubeadmDir)
}

func (r HostReconciler) hostCleanUp(ctx context.Context, byoHost *infrastructurev1beta1.ByoHost) error {
func (r *HostReconciler) hostCleanUp(ctx context.Context, byoHost *infrastructurev1beta1.ByoHost) error {
logger := ctrl.LoggerFrom(ctx)
logger.Info("cleaning up host")
err := r.resetNode(ctx)
err := r.resetNode(ctx, byoHost)
if err != nil {
return err
}
Expand Down Expand Up @@ -197,16 +202,17 @@ func (r HostReconciler) hostCleanUp(ctx context.Context, byoHost *infrastructure
return nil
}

func (r *HostReconciler) resetNode(ctx context.Context) error {
func (r *HostReconciler) resetNode(ctx context.Context, byoHost *infrastructurev1beta1.ByoHost) error {
logger := ctrl.LoggerFrom(ctx)
logger.Info("Running kubeadm reset")

err := r.CmdRunner.RunCmd(KubeadmResetCommand)
if err != nil {
r.Recorder.Event(byoHost, corev1.EventTypeWarning, "ResetK8sNodeFailed", "k8s Node Reset failed")
return errors.Wrapf(err, "failed to exec kubeadm reset")
}

logger.Info("Kubernetes Node reset completed")
r.Recorder.Event(byoHost, corev1.EventTypeNormal, "ResetK8sNodeSucceeded", "k8s Node Reset completed")
return nil
}

Expand All @@ -226,6 +232,7 @@ func (r *HostReconciler) installK8sComponents(ctx context.Context, byoHost *infr
// TODO: call installer.Install(k8sVersion) here
// if err, return err

r.Recorder.Event(byoHost, corev1.EventTypeNormal, "k8sComponentInstalled", "Successfully Installed K8s components")
conditions.MarkTrue(byoHost, infrastructurev1beta1.K8sComponentsInstallationSucceeded)
return nil
}
41 changes: 40 additions & 1 deletion agent/reconciler/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ package reconciler
import (
"context"
"errors"
"fmt"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vmware-tanzu/cluster-api-provider-byoh/agent/cloudinit/cloudinitfakes"
infrastructurev1beta1 "github.com/vmware-tanzu/cluster-api-provider-byoh/apis/infrastructure/v1beta1"
"github.com/vmware-tanzu/cluster-api-provider-byoh/common"
"github.com/vmware-tanzu/cluster-api-provider-byoh/test/builder"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/util/conditions"
"sigs.k8s.io/cluster-api/util/patch"
Expand All @@ -30,18 +33,20 @@ var _ = Describe("Byohost Agent Tests", func() {
byoMachine *infrastructurev1beta1.ByoMachine
byoHostLookupKey types.NamespacedName
bootstrapSecret *corev1.Secret
recorder *record.FakeRecorder
)

BeforeEach(func() {
fakeCommandRunner = &cloudinitfakes.FakeICmdRunner{}
fakeFileWriter = &cloudinitfakes.FakeIFileWriter{}
fakeTemplateParser = &cloudinitfakes.FakeITemplateParser{}

recorder = record.NewFakeRecorder(32)
reconciler = &HostReconciler{
Client: k8sClient,
CmdRunner: fakeCommandRunner,
FileWriter: fakeFileWriter,
TemplateParser: fakeTemplateParser,
Recorder: recorder,
}
})

Expand Down Expand Up @@ -132,6 +137,12 @@ var _ = Describe("Byohost Agent Tests", func() {
})
Expect(result).To(Equal(controllerruntime.Result{}))
Expect(reconcilerErr).To(MatchError("secrets \"non-existent\" not found"))

// assert events
events := common.CollectEvents(recorder.Events)
Expect(events).Should(ConsistOf([]string{
fmt.Sprintf("Warning ReadBootstrapSecretFailed bootstrap secret %s not found", byoHost.Spec.BootstrapSecret.Name),
}))
})

Context("When bootstrap secret is ready", func() {
Expand Down Expand Up @@ -177,6 +188,15 @@ runCmd:
Reason: infrastructurev1beta1.CloudInitExecutionFailedReason,
Severity: clusterv1.ConditionSeverityError,
}))

// assert events
events := common.CollectEvents(recorder.Events)
Expect(events).Should(ConsistOf([]string{
"Normal k8sComponentInstalled Successfully Installed K8s components",
"Warning BootstrapK8sNodeFailed k8s Node Bootstrap failed",
// TODO: improve test to remove this event
"Warning ResetK8sNodeFailed k8s Node Reset failed",
}))
})

It("should set K8sNodeBootstrapSucceeded to True if the boostrap execution succeeds", func() {
Expand All @@ -198,6 +218,13 @@ runCmd:
Type: infrastructurev1beta1.K8sNodeBootstrapSucceeded,
Status: corev1.ConditionTrue,
}))

// assert events
events := common.CollectEvents(recorder.Events)
Expect(events).Should(ConsistOf([]string{
"Normal k8sComponentInstalled Successfully Installed K8s components",
"Normal BootstrapK8sNodeSucceeded k8s Node Bootstraped",
}))
})

It("should execute bootstrap secret only once ", func() {
Expand Down Expand Up @@ -271,6 +298,12 @@ runCmd:
Reason: infrastructurev1beta1.K8sNodeAbsentReason,
Severity: clusterv1.ConditionSeverityInfo,
}))

// assert events
events := common.CollectEvents(recorder.Events)
Expect(events).Should(ConsistOf([]string{
"Normal ResetK8sNodeSucceeded k8s Node Reset completed",
}))
})

It("should return error if host cleanup failed", func() {
Expand All @@ -291,6 +324,12 @@ runCmd:
Type: infrastructurev1beta1.K8sNodeBootstrapSucceeded,
Status: corev1.ConditionTrue,
}))

// assert events
events := common.CollectEvents(recorder.Events)
Expect(events).Should(ConsistOf([]string{
"Warning ResetK8sNodeFailed k8s Node Reset failed",
}))
})
})

Expand Down
34 changes: 34 additions & 0 deletions common/testutils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2021 VMware, Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package common

// CollectEvents returns a slice of string consisting
// all the events from the record.FakeRecorder.Events Chan
func CollectEvents(source <-chan string) []string {
done := false
events := make([]string, 0)
for !done {
select {
case event := <-source:
events = append(events, event)
default:
done = true
}
}
return events
}

// DrainEvents clears all the events in the chan recorder.Events
// This is a hack as the current byomachine reconciler is global to test
// and the record.FakeRecorder could have events from different tests
// It could also introduce data races in parallel tests run
func DrainEvents(events chan string) {
for {
select {
case <-events:
default:
return
}
}
}
13 changes: 11 additions & 2 deletions controllers/infrastructure/byomachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/selection"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/cluster-api/controllers/remote"
"sigs.k8s.io/cluster-api/util"
"sigs.k8s.io/cluster-api/util/conditions"
Expand Down Expand Up @@ -47,8 +48,9 @@ const (
// ByoMachineReconciler reconciles a ByoMachine object
type ByoMachineReconciler struct {
client.Client
Scheme *runtime.Scheme
Tracker *remote.ClusterCacheTracker
Scheme *runtime.Scheme
Tracker *remote.ClusterCacheTracker
Recorder record.EventRecorder
}

//+kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=byomachines,verbs=get;list;watch;create;update;patch;delete
Expand Down Expand Up @@ -179,6 +181,8 @@ func (r *ByoMachineReconciler) reconcileDelete(ctx context.Context, machineScope
}
}

r.Recorder.Eventf(machineScope.ByoHost, corev1.EventTypeNormal, "ByoHostReleaseSucceeded", "ByoHost Released by %s", machineScope.ByoMachine.Name)
r.Recorder.Eventf(machineScope.ByoMachine, corev1.EventTypeNormal, "ByoHostReleaseSucceeded", "Released ByoHost %s", machineScope.ByoHost.Name)
controllerutil.RemoveFinalizer(machineScope.ByoMachine, infrav1.MachineFinalizer)
return reconcile.Result{}, nil
}
Expand Down Expand Up @@ -216,6 +220,8 @@ func (r *ByoMachineReconciler) reconcileNormal(ctx context.Context, machineScope
if res, err := r.attachByoHost(ctx, machineScope); err != nil {
return res, err
}
r.Recorder.Eventf(machineScope.ByoHost, corev1.EventTypeNormal, "ByoHostAttachSucceeded", "Attached to ByoMachine %s", machineScope.ByoMachine.Name)
r.Recorder.Eventf(machineScope.ByoMachine, corev1.EventTypeNormal, "ByoHostAttachSucceeded", "Attached ByoHost %s", machineScope.ByoHost.Name)
}

if machineScope.ByoMachine.Spec.ProviderID == "" {
Expand All @@ -230,11 +236,13 @@ func (r *ByoMachineReconciler) reconcileNormal(ctx context.Context, machineScope
err = r.setNodeProviderID(ctx, remoteClient, machineScope.ByoHost, providerID)
if err != nil {
logger.Error(err, "failed to set node providerID")
r.Recorder.Eventf(machineScope.ByoMachine, corev1.EventTypeWarning, "SetNodeProviderFailed", "Node %s does not exist", machineScope.ByoHost.Name)
return ctrl.Result{}, err
}
machineScope.ByoMachine.Spec.ProviderID = providerID
machineScope.ByoMachine.Status.Ready = true
conditions.MarkTrue(machineScope.ByoMachine, infrav1.BYOHostReady)
r.Recorder.Eventf(machineScope.ByoMachine, corev1.EventTypeNormal, "NodeProvisionedSucceeded", "Provisioned Node %s", machineScope.ByoHost.Name)
}

return ctrl.Result{}, nil
Expand Down Expand Up @@ -394,6 +402,7 @@ func (r *ByoMachineReconciler) attachByoHost(ctx context.Context, machineScope *
}
if len(hostsList.Items) == 0 {
logger.Info("No hosts found, waiting..")
r.Recorder.Eventf(machineScope.ByoMachine, corev1.EventTypeWarning, "ByoHostSelectionFailed", "No available ByoHost")
conditions.MarkFalse(machineScope.ByoMachine, infrav1.BYOHostReady, infrav1.BYOHostsUnavailableReason, clusterv1.ConditionSeverityInfo, "")
return ctrl.Result{RequeueAfter: RequeueForbyohost}, errors.New("no hosts found")
}
Expand Down
Loading

0 comments on commit 8f727b4

Please sign in to comment.