diff --git a/controllers/machinedeletionremediation_controller.go b/controllers/machinedeletionremediation_controller.go index 134398eb..46e36b68 100644 --- a/controllers/machinedeletionremediation_controller.go +++ b/controllers/machinedeletionremediation_controller.go @@ -25,6 +25,7 @@ import ( "github.com/go-logr/logr" commonannotations "github.com/medik8s/common/pkg/annotations" commonconditions "github.com/medik8s/common/pkg/conditions" + commonevents "github.com/medik8s/common/pkg/events" "github.com/pkg/errors" v1 "k8s.io/api/core/v1" @@ -34,6 +35,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -59,6 +61,7 @@ const ( failedToDeleteMachineError = "failed to delete machine of node name: %s" nodeNotFoundErrorMsg = "failed to fetch node" machineNotFoundErrorMsg = "failed to fetch machine of node" + noControllerOwnerErrorMsg = "ignoring remediation of the machine: the machine has no controller owner" // Cluster Provider messages machineDeletedOnCloudProviderMessage = "Machine will be deleted and the unhealthy node replaced. This is a Cloud cluster provider: the new node is expected to have a new name" machineDeletedOnBareMetalProviderMessage = "Machine will be deleted and the unhealthy node replaced. This is a BareMetal cluster provider: the new node is NOT expected to have a new name" @@ -74,7 +77,11 @@ const ( remediationSkippedNodeNotFound conditionChangeReason = "RemediationSkippedNodeNotFound" remediationSkippedMachineNotFound conditionChangeReason = "RemediationSkippedMachineNotFound" remediationSkippedNoControllerOwner conditionChangeReason = "RemediationSkippedNoControllerOwner" - remediationFailed conditionChangeReason = "remediationFailed" + remediationFailed conditionChangeReason = "RemediationFailed" + + // Event reasons and messages + machineDeletionRequestedEventReason = "MachineDeletionRequested" + machineDeletionRequestedEventMessage = "requesting machine deletion" ) var ( @@ -86,8 +93,9 @@ var ( // MachineDeletionRemediationReconciler reconciles a MachineDeletionRemediation object type MachineDeletionRemediationReconciler struct { client.Client - Log logr.Logger - Scheme *runtime.Scheme + Log logr.Logger + Scheme *runtime.Scheme + Recorder record.EventRecorder } //+kubebuilder:rbac:groups=machine-deletion-remediation.medik8s.io,resources=machinedeletionremediations,verbs=get;list;watch;create;update;patch;delete @@ -127,9 +135,11 @@ func (r *MachineDeletionRemediationReconciler) Reconcile(ctx context.Context, re finalResult.RequeueAfter = time.Second } }() + commonevents.RemediationStarted(r.Recorder, mdr) if r.isTimedOutByNHC(mdr) { log.Info("NHC time out annotation found, stopping remediation") + commonevents.RemediationStoppedByNHC(r.Recorder, mdr) _, err = r.updateConditions(remediationTimedOutByNhc, mdr) return ctrl.Result{}, err } @@ -148,10 +158,13 @@ func (r *MachineDeletionRemediationReconciler) Reconcile(ctx context.Context, re // situation. An error is returned only if it does not match the following custom errors, or // updateConditions fails. if err == nodeNotFoundError { + commonevents.WarningEvent(r.Recorder, mdr, string(remediationSkippedNodeNotFound), nodeNotFoundErrorMsg) _, err = r.updateConditions(remediationSkippedNodeNotFound, mdr) } else if err == machineNotFoundError { + commonevents.WarningEvent(r.Recorder, mdr, string(remediationSkippedMachineNotFound), machineNotFoundErrorMsg) _, err = r.updateConditions(remediationSkippedMachineNotFound, mdr) } else if err == unrecoverableError { + commonevents.WarningEvent(r.Recorder, mdr, string(remediationFailed), unrecoverableError.Error()) _, err = r.updateConditions(remediationFailed, mdr) } @@ -167,13 +180,18 @@ func (r *MachineDeletionRemediationReconciler) Reconcile(ctx context.Context, re // verify nodes count restoration even if machine == nil. if machine == nil || machine.GetCreationTimestamp().After(mdr.GetCreationTimestamp().Time) { if isRestored, err := r.isExpectedNodesNumberRestored(ctx, mdr); err != nil { - log.Error(err, "could not verify if node was restored") + msg := "could not verify if node was restored" + log.Error(err, msg) + commonevents.WarningEvent(r.Recorder, mdr, "unableToVerifyNodesCount", err.Error()) if err == unrecoverableError { return ctrl.Result{}, nil } return ctrl.Result{}, err } else if isRestored { _, err = r.updateConditions(remediationFinishedMachineDeleted, mdr) + if err == nil { + commonevents.RemediationFinished(r.Recorder, mdr) + } return ctrl.Result{}, err } log.Info("waiting for the nodes count to be re-provisioned") @@ -204,6 +222,7 @@ func (r *MachineDeletionRemediationReconciler) Reconcile(ctx context.Context, re if updateRequired := r.setPermanentNodeDeletionExpectedCondition(status, mdr); updateRequired { log.Info(permanentNodeDeletionExpectedMsg) + commonevents.NormalEvent(r.Recorder, mdr, "PermanentNodeDeletionExpected", permanentNodeDeletionExpectedMsg) return ctrl.Result{RequeueAfter: time.Second}, nil } @@ -214,7 +233,8 @@ func (r *MachineDeletionRemediationReconciler) Reconcile(ctx context.Context, re } if !hasControllerOwner(machine) { - log.Info("ignoring remediation of the machine: the machine has no controller owner", "machine", machine.GetName()) + log.Info(noControllerOwnerErrorMsg, "machine", machine.GetName(), "remediation name", mdr.Name) + commonevents.WarningEvent(r.Recorder, mdr, string(remediationSkippedNoControllerOwner), noControllerOwnerErrorMsg) _, err = r.updateConditions(remediationSkippedNoControllerOwner, mdr) return ctrl.Result{}, err } @@ -225,12 +245,13 @@ func (r *MachineDeletionRemediationReconciler) Reconcile(ctx context.Context, re return ctrl.Result{}, errors.Wrapf(err, "failed to save Machine's name and namespace") } - log.Info("request machine deletion", "machine", machine.GetName()) + log.Info("request machine deletion", "machine", machine.GetName(), "remediation name", mdr.Name) err = r.Delete(ctx, machine) if err != nil { log.Error(err, "failed to delete machine", "machine", machine.GetName()) return ctrl.Result{}, err } + commonevents.NormalEvent(r.Recorder, mdr, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage) // requeue immediately to check machine deletion progression return ctrl.Result{Requeue: true}, nil diff --git a/controllers/machinedeletionremediation_controller_test.go b/controllers/machinedeletionremediation_controller_test.go index fe5267f3..d90fa976 100644 --- a/controllers/machinedeletionremediation_controller_test.go +++ b/controllers/machinedeletionremediation_controller_test.go @@ -146,6 +146,10 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.ProcessingType, metav1.ConditionFalse, remediationSkippedNodeNotFound}, {commonconditions.SucceededType, metav1.ConditionFalse, remediationSkippedNodeNotFound}}) verifyConditionUnset(commonconditions.PermanentNodeDeletionExpectedType) + verifyEvents([]expectedEvent{ + {v1.EventTypeWarning, "RemediationSkippedNodeNotFound", "failed to fetch node", true}, + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, false}, + }) }) }) @@ -162,6 +166,10 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.SucceededType, metav1.ConditionFalse, remediationSkippedNoControllerOwner}, // Cluster provider is not set in this test {commonconditions.PermanentNodeDeletionExpectedType, metav1.ConditionUnknown, v1alpha1.MachineDeletionOnUndefinedProviderReason}}) + verifyEvents([]expectedEvent{ + {v1.EventTypeWarning, "RemediationSkippedNoControllerOwner", noControllerOwnerErrorMsg, true}, + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, false}, + }) }) }) @@ -180,6 +188,10 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.SucceededType, metav1.ConditionFalse, remediationSkippedNoControllerOwner}, // Cluster provider is not set in this test {commonconditions.PermanentNodeDeletionExpectedType, metav1.ConditionUnknown, v1alpha1.MachineDeletionOnUndefinedProviderReason}}) + verifyEvents([]expectedEvent{ + {v1.EventTypeWarning, "RemediationSkippedNoControllerOwner", noControllerOwnerErrorMsg, true}, + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, false}, + }) }) }) @@ -199,6 +211,11 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.SucceededType, metav1.ConditionFalse, remediationSkippedNoControllerOwner}, // Cluster provider is not set in this test {commonconditions.PermanentNodeDeletionExpectedType, metav1.ConditionUnknown, v1alpha1.MachineDeletionOnUndefinedProviderReason}}) + + verifyEvents([]expectedEvent{ + {v1.EventTypeWarning, "RemediationSkippedNoControllerOwner", noControllerOwnerErrorMsg, true}, + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, false}, + }) }) }) @@ -239,6 +256,9 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.SucceededType, metav1.ConditionTrue, remediationFinishedMachineDeleted}, // Cluster provider is not set in this test {commonconditions.PermanentNodeDeletionExpectedType, metav1.ConditionUnknown, v1alpha1.MachineDeletionOnUndefinedProviderReason}}) + verifyEvents([]expectedEvent{ + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, true}, + }) }) }) @@ -274,6 +294,10 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.SucceededType, metav1.ConditionTrue, remediationFinishedMachineDeleted}, // Cluster provider is not set in this test {commonconditions.PermanentNodeDeletionExpectedType, metav1.ConditionUnknown, v1alpha1.MachineDeletionOnUndefinedProviderReason}}) + verifyEvents([]expectedEvent{ + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, true}, + {v1.EventTypeNormal, "RemediationFinished", "Remediation finished", true}, + }) }) }) @@ -285,6 +309,12 @@ var _ = Describe("Machine Deletion Remediation CR", func() { }) It("sets PermanentNodeDeletionExpected condition to false", func() { verifyConditionMatches(commonconditions.PermanentNodeDeletionExpectedType, metav1.ConditionFalse, v1alpha1.MachineDeletionOnBareMetalProviderReason) + verifyEvents([]expectedEvent{ + {v1.EventTypeNormal, + "PermanentNodeDeletionExpected", + "Machine will be deleted and the unhealthy node replaced. This is a BareMetal cluster provider: the new node is NOT expected to have a new name", + true}, + }) }) }) @@ -296,6 +326,12 @@ var _ = Describe("Machine Deletion Remediation CR", func() { }) It("sets PermanentNodeDeletionExpected condition to true", func() { verifyConditionMatches(commonconditions.PermanentNodeDeletionExpectedType, metav1.ConditionTrue, v1alpha1.MachineDeletionOnCloudProviderReason) + verifyEvents([]expectedEvent{ + {v1.EventTypeNormal, + "PermanentNodeDeletionExpected", + "Machine will be deleted and the unhealthy node replaced. This is a Cloud cluster provider: the new node is expected to have a new name", + true}, + }) }) }) @@ -308,6 +344,12 @@ var _ = Describe("Machine Deletion Remediation CR", func() { }) It("sets PermanentNodeDeletionExpected condition to false", func() { verifyConditionMatches(commonconditions.PermanentNodeDeletionExpectedType, metav1.ConditionUnknown, v1alpha1.MachineDeletionOnUndefinedProviderReason) + verifyEvents([]expectedEvent{ + {v1.EventTypeNormal, + "PermanentNodeDeletionExpected", + "Machine will be deleted and the unhealthy node replaced. Unknown cluster provider: no information about the new node's name", + true}, + }) }) }) }) @@ -327,6 +369,10 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.ProcessingType, metav1.ConditionFalse, remediationSkippedNodeNotFound}, {commonconditions.SucceededType, metav1.ConditionFalse, remediationSkippedNodeNotFound}}) verifyConditionUnset(commonconditions.PermanentNodeDeletionExpectedType) + verifyEvents([]expectedEvent{ + {v1.EventTypeWarning, "RemediationSkippedNodeNotFound", "failed to fetch node", true}, + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, false}, + }) }) }) @@ -346,6 +392,10 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.ProcessingType, metav1.ConditionFalse, remediationFailed}, {commonconditions.SucceededType, metav1.ConditionFalse, remediationFailed}}) verifyConditionUnset(commonconditions.PermanentNodeDeletionExpectedType) + verifyEvents([]expectedEvent{ + {v1.EventTypeWarning, "RemediationFailed", unrecoverableError.Error(), true}, + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, false}, + }) }) }) @@ -365,6 +415,10 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.ProcessingType, metav1.ConditionFalse, remediationFailed}, {commonconditions.SucceededType, metav1.ConditionFalse, remediationFailed}}) verifyConditionUnset(commonconditions.PermanentNodeDeletionExpectedType) + verifyEvents([]expectedEvent{ + {v1.EventTypeWarning, "RemediationFailed", unrecoverableError.Error(), true}, + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, false}, + }) }) }) @@ -384,6 +438,10 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.ProcessingType, metav1.ConditionFalse, remediationFailed}, {commonconditions.SucceededType, metav1.ConditionFalse, remediationFailed}}) verifyConditionUnset(commonconditions.PermanentNodeDeletionExpectedType) + verifyEvents([]expectedEvent{ + {v1.EventTypeWarning, "RemediationFailed", unrecoverableError.Error(), true}, + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, false}, + }) }) }) @@ -403,6 +461,10 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.ProcessingType, metav1.ConditionFalse, remediationSkippedMachineNotFound}, {commonconditions.SucceededType, metav1.ConditionFalse, remediationSkippedMachineNotFound}}) verifyConditionUnset(commonconditions.PermanentNodeDeletionExpectedType) + verifyEvents([]expectedEvent{ + {v1.EventTypeWarning, "RemediationSkippedMachineNotFound", "failed to fetch machine of node", true}, + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, false}, + }) }) }) @@ -423,6 +485,10 @@ var _ = Describe("Machine Deletion Remediation CR", func() { // beginning. As a result, the first attempt to get the Machine is via CR's annotation, it fails, // and the condition cannot be set. Normally, the first attempt is via Node's annotation instead. verifyConditionUnset(commonconditions.PermanentNodeDeletionExpectedType) + verifyEvents([]expectedEvent{ + {v1.EventTypeWarning, "RemediationFailed", unrecoverableError.Error(), true}, + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, false}, + }) }) }) @@ -445,6 +511,9 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.SucceededType, metav1.ConditionUnknown, remediationStarted}, // Cluster provider is not set in this test {commonconditions.PermanentNodeDeletionExpectedType, metav1.ConditionUnknown, v1alpha1.MachineDeletionOnUndefinedProviderReason}}) + verifyEvents([]expectedEvent{ + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, false}, + }) }) }) @@ -461,6 +530,10 @@ var _ = Describe("Machine Deletion Remediation CR", func() { // beginning. As a result, the first attempt to get the Machine is via CR's annotation, it fails, // and the condition cannot be set. Normally, the first attempt is via Node's annotation instead. verifyConditionUnset(commonconditions.PermanentNodeDeletionExpectedType) + verifyEvents([]expectedEvent{ + {v1.EventTypeNormal, "RemediationStopped", "NHC added the timed-out annotation, remediation will be stopped", true}, + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, false}, + }) }) }) }) @@ -502,6 +575,9 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.SucceededType, metav1.ConditionTrue, remediationFinishedMachineDeleted}, // Cluster provider is not set in this test {commonconditions.PermanentNodeDeletionExpectedType, metav1.ConditionUnknown, v1alpha1.MachineDeletionOnUndefinedProviderReason}}) + verifyEvents([]expectedEvent{ + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, true}, + }) }) }) @@ -525,6 +601,9 @@ var _ = Describe("Machine Deletion Remediation CR", func() { {commonconditions.SucceededType, metav1.ConditionTrue, remediationFinishedMachineDeleted}, // Cluster provider is not set in this test {commonconditions.PermanentNodeDeletionExpectedType, metav1.ConditionUnknown, v1alpha1.MachineDeletionOnUndefinedProviderReason}}) + verifyEvents([]expectedEvent{ + {v1.EventTypeNormal, machineDeletionRequestedEventReason, machineDeletionRequestedEventMessage, true}, + }) }) }) }) @@ -669,13 +748,13 @@ func verifyMachineNotDeleted(machineName string) { Consistently( func() error { return k8sClient.Get(context.Background(), client.ObjectKey{Namespace: machineNamespace, Name: machineName}, createDummyMachine()) - }).ShouldNot(HaveOccurred()) + }).ShouldNot(HaveOccurred(), "Machine %s should not have been deleted", machineName) } func verifyMachineIsDeleted(machineName string) { Eventually(func() bool { return errors.IsNotFound(k8sClient.Get(context.Background(), client.ObjectKey{Namespace: machineNamespace, Name: machineName}, createDummyMachine())) - }).Should(BeTrue()) + }).Should(BeTrue(), "Machine %s should have been deleted", machineName) } func deleteIgnoreNotFound() func(ctx context.Context, obj client.Object) error { @@ -756,3 +835,36 @@ func setMachineProviderID(machine *machinev1beta1.Machine, providerID string) { machine.Spec.ProviderID = &providerID Expect(k8sClient.Update(context.TODO(), machine)).To(Succeed()) } + +type expectedEvent struct { + eventType, reason, message string + expected bool +} + +func verifyEvents(expectedEvents []expectedEvent) { + By("verifying that the Events are emitted (or not) as expected") + + // building events message map + toBeTestedEventsMap := make(map[string]bool) + for _, e := range expectedEvents { + formattedMessage := fmt.Sprintf("%s %s [remediation] %s", e.eventType, e.reason, e.message) + toBeTestedEventsMap[formattedMessage] = e.expected + } + actuallyReceivedEventMap := make(map[string]bool) + for { + select { + case got := <-fakeRecorder.Events: + if _, exist := toBeTestedEventsMap[got]; exist { + actuallyReceivedEventMap[got] = true + } + continue + case <-time.After(1 * time.Second): + } + break + + } + for formattedEventMessage, expected := range toBeTestedEventsMap { + _, exists := actuallyReceivedEventMap[formattedEventMessage] + Expect(exists).To(Equal(expected), "event test failed.\nEvent '%s': expected %v, received %v", formattedEventMessage, expected, exists) + } +} diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 261625b9..a2f46d96 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -27,6 +27,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" @@ -44,12 +45,13 @@ import ( // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. var ( - cclient customClient - k8sClient client.Client - testEnv *envtest.Environment - ctx context.Context - cancel context.CancelFunc - plogs *peekLogger + cclient customClient + k8sClient client.Client + testEnv *envtest.Environment + ctx context.Context + cancel context.CancelFunc + plogs *peekLogger + fakeRecorder *record.FakeRecorder ) // peekLogger allows to inspect operator's log for testing purpose. @@ -135,9 +137,12 @@ var _ = BeforeSuite(func() { cclient = customClient{Client: k8sClient} + fakeRecorder = record.NewFakeRecorder(30) + err = (&MachineDeletionRemediationReconciler{ - Client: &cclient, - Log: ctrl.Log.WithName("controllers").WithName("machine-deletion-controller"), + Client: &cclient, + Log: ctrl.Log.WithName("controllers").WithName("machine-deletion-controller"), + Recorder: fakeRecorder, }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) diff --git a/go.mod b/go.mod index 412b086b..0d1d6f00 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/go-logr/logr v1.2.4 - github.com/medik8s/common v1.7.0 + github.com/medik8s/common v1.12.0 github.com/onsi/ginkgo/v2 v2.11.0 github.com/onsi/gomega v1.27.10 github.com/openshift/api v0.0.0-20230831095235-8891815aa476 // release-4.13 diff --git a/go.sum b/go.sum index f6d275a8..68466fc3 100644 --- a/go.sum +++ b/go.sum @@ -75,8 +75,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= -github.com/medik8s/common v1.7.0 h1:JwimhWigPTAszGG2jYJmh+uVHq2nFUPRRljw7ZhlQhg= -github.com/medik8s/common v1.7.0/go.mod h1:ZT/3hfMXJLmZEcqmxRWB5LGC8Wl+qKGGQ4zM8hOE7PY= +github.com/medik8s/common v1.12.0 h1:UJ5VS4rbo/K0snfuqRiYam1NhXTwo4Q7fTng34YSlmA= +github.com/medik8s/common v1.12.0/go.mod h1:Q6YR2rgyiLl6ob4Mx2uDBmybAB3d94fImwoHPbeiE54= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= diff --git a/main.go b/main.go index e048cc3c..b3280284 100644 --- a/main.go +++ b/main.go @@ -105,9 +105,10 @@ func main() { } if err = (&controllers.MachineDeletionRemediationReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("MachineDeletionRemediation"), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("MachineDeletionRemediation"), + Scheme: mgr.GetScheme(), + Recorder: mgr.GetEventRecorderFor("MachineDeletionRemediation"), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "MachineDeletionRemediation") os.Exit(1) diff --git a/vendor/github.com/medik8s/common/pkg/events/events.go b/vendor/github.com/medik8s/common/pkg/events/events.go new file mode 100644 index 00000000..7550d3c8 --- /dev/null +++ b/vendor/github.com/medik8s/common/pkg/events/events.go @@ -0,0 +1,51 @@ +package events + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/record" +) + +// Event message format "medik8s " +const customFmt = "[remediation] %s" + +// NormalEvent will record an event with type Normal and fixed message. +func NormalEvent(recorder record.EventRecorder, object runtime.Object, reason, message string) { + recorder.Event(object, corev1.EventTypeNormal, reason, fmt.Sprintf(customFmt, message)) +} + +// NormalEventf will record an event with type Normal and formatted message. +func NormalEventf(recorder record.EventRecorder, object runtime.Object, reason, messageFmt string, a ...interface{}) { + message := fmt.Sprintf(messageFmt, a...) + recorder.Event(object, corev1.EventTypeNormal, reason, fmt.Sprintf(customFmt, message)) +} + +// WarningEvent will record an event with type Warning and fixed message. +func WarningEvent(recorder record.EventRecorder, object runtime.Object, reason, message string) { + recorder.Event(object, corev1.EventTypeWarning, reason, fmt.Sprintf(customFmt, message)) +} + +// WarningEventf will record an event with type Warning and formatted message. +func WarningEventf(recorder record.EventRecorder, object runtime.Object, reason, messageFmt string, a ...interface{}) { + message := fmt.Sprintf(messageFmt, a...) + recorder.Event(object, corev1.EventTypeWarning, reason, fmt.Sprintf(customFmt, message)) +} + +// Special case events + +// RemediationStarted will record a Normal event with reason RemediationStarted and message Remediation started. +func RemediationStarted(recorder record.EventRecorder, object runtime.Object) { + NormalEvent(recorder, object, "RemediationStarted", "Remediation started") +} + +// RemediationStoppedByNHC will record a Normal event with reason RemediationStopped. +func RemediationStoppedByNHC(recorder record.EventRecorder, object runtime.Object) { + NormalEvent(recorder, object, "RemediationStopped", "NHC added the timed-out annotation, remediation will be stopped") +} + +// RemediationFinished will record a Normal event with reason RemediationFinished and message Remediation finished. +func RemediationFinished(recorder record.EventRecorder, object runtime.Object) { + NormalEvent(recorder, object, "RemediationFinished", "Remediation finished") +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 9b726fc8..65c90b37 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -92,10 +92,11 @@ github.com/mailru/easyjson/jwriter # github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 ## explicit; go 1.19 github.com/matttproud/golang_protobuf_extensions/v2/pbutil -# github.com/medik8s/common v1.7.0 +# github.com/medik8s/common v1.12.0 ## explicit; go 1.20 github.com/medik8s/common/pkg/annotations github.com/medik8s/common/pkg/conditions +github.com/medik8s/common/pkg/events # github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd ## explicit github.com/modern-go/concurrent