diff --git a/PROJECT b/PROJECT index 28e5dc37..e5a431ed 100644 --- a/PROJECT +++ b/PROJECT @@ -33,6 +33,7 @@ resources: path: github.com/medik8s/fence-agents-remediation/api/v1alpha1 version: v1alpha1 webhooks: + defaulting: true validation: true webhookVersion: v1 version: "3" diff --git a/api/v1alpha1/fenceagentsremediation_webhook.go b/api/v1alpha1/fenceagentsremediation_webhook.go index 633eb6e8..43660d61 100644 --- a/api/v1alpha1/fenceagentsremediation_webhook.go +++ b/api/v1alpha1/fenceagentsremediation_webhook.go @@ -47,6 +47,7 @@ func (r *FenceAgentsRemediation) SetupWebhookWithManager(mgr ctrl.Manager) error // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. // +kubebuilder:webhook:path=/validate-fence-agents-remediation-medik8s-io-v1alpha1-fenceagentsremediation,mutating=false,failurePolicy=fail,sideEffects=None,groups=fence-agents-remediation.medik8s.io,resources=fenceagentsremediations,verbs=create;update,versions=v1alpha1,name=vfenceagentsremediation.kb.io,admissionReviewVersions=v1 + var _ webhook.Validator = &FenceAgentsRemediation{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type diff --git a/api/v1alpha1/fenceagentsremediationtemplate_webhook.go b/api/v1alpha1/fenceagentsremediationtemplate_webhook.go index 524f613c..a645bcb7 100644 --- a/api/v1alpha1/fenceagentsremediationtemplate_webhook.go +++ b/api/v1alpha1/fenceagentsremediationtemplate_webhook.go @@ -17,6 +17,8 @@ limitations under the License. package v1alpha1 import ( + commonAnnotations "github.com/medik8s/common/pkg/annotations" + "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" @@ -37,8 +39,24 @@ func (r *FenceAgentsRemediationTemplate) SetupWebhookWithManager(mgr ctrl.Manage // TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// +kubebuilder:webhook:path=/mutate-fence-agents-remediation-medik8s-io-v1alpha1-fenceagentsremediationtemplate,mutating=true,failurePolicy=fail,sideEffects=None,groups=fence-agents-remediation.medik8s.io,resources=fenceagentsremediationtemplates,verbs=create;update,versions=v1alpha1,name=mfenceagentsremediationtemplate.kb.io,admissionReviewVersions=v1 + +var _ webhook.Defaulter = &FenceAgentsRemediationTemplate{} + +// Default implements webhook.Defaulter so a webhook will be registered for the type +func (farTemplate *FenceAgentsRemediationTemplate) Default() { + webhookFARTemplateLog.Info("default", "name", farTemplate.Name) + if farTemplate.GetAnnotations() == nil { + farTemplate.Annotations = make(map[string]string) + } + if _, isSameKindAnnotationSet := farTemplate.GetAnnotations()[commonAnnotations.MultipleTemplatesSupportedAnnotation]; !isSameKindAnnotationSet { + farTemplate.Annotations[commonAnnotations.MultipleTemplatesSupportedAnnotation] = "true" + } +} + // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. // +kubebuilder:webhook:path=/validate-fence-agents-remediation-medik8s-io-v1alpha1-fenceagentsremediationtemplate,mutating=false,failurePolicy=fail,sideEffects=None,groups=fence-agents-remediation.medik8s.io,resources=fenceagentsremediationtemplates,verbs=create;update,versions=v1alpha1,name=vfenceagentsremediationtemplate.kb.io,admissionReviewVersions=v1 + var _ webhook.Validator = &FenceAgentsRemediationTemplate{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type diff --git a/bundle/manifests/fence-agents-remediation.clusterserviceversion.yaml b/bundle/manifests/fence-agents-remediation.clusterserviceversion.yaml index 40534e6a..bd9c0c91 100644 --- a/bundle/manifests/fence-agents-remediation.clusterserviceversion.yaml +++ b/bundle/manifests/fence-agents-remediation.clusterserviceversion.yaml @@ -410,6 +410,26 @@ spec: replaces: fence-agents-remediation.v0.0.1 version: 0.0.1 webhookdefinitions: + - admissionReviewVersions: + - v1 + containerPort: 443 + deploymentName: fence-agents-remediation-controller-manager + failurePolicy: Fail + generateName: mfenceagentsremediationtemplate.kb.io + rules: + - apiGroups: + - fence-agents-remediation.medik8s.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - fenceagentsremediationtemplates + sideEffects: None + targetPort: 9443 + type: MutatingAdmissionWebhook + webhookPath: /mutate-fence-agents-remediation-medik8s-io-v1alpha1-fenceagentsremediationtemplate - admissionReviewVersions: - v1 containerPort: 443 diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 034d8214..ee9c8985 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -1,5 +1,31 @@ --- apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: mutating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-fence-agents-remediation-medik8s-io-v1alpha1-fenceagentsremediationtemplate + failurePolicy: Fail + name: mfenceagentsremediationtemplate.kb.io + rules: + - apiGroups: + - fence-agents-remediation.medik8s.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - fenceagentsremediationtemplates + sideEffects: None +--- +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: validating-webhook-configuration diff --git a/controllers/fenceagentsremediation_controller.go b/controllers/fenceagentsremediation_controller.go index e3f623c5..926b0420 100644 --- a/controllers/fenceagentsremediation_controller.go +++ b/controllers/fenceagentsremediation_controller.go @@ -120,13 +120,13 @@ func (r *FenceAgentsRemediationReconciler) Reconcile(ctx context.Context, req ct // Validate FAR CR name to match a nodeName from the cluster r.Log.Info("Check FAR CR's name") - node, err := utils.GetNodeWithName(r.Client, req.Name) + node, err := utils.GetNodeWithName(r.Client, getNodeName(far)) if err != nil { r.Log.Error(err, "Unexpected error when validating CR's name with nodes' names", "CR's Name", req.Name) return emptyResult, err } if node == nil { - r.Log.Error(err, "Didn't find a node matching the CR's name", "CR's Name", req.Name) + r.Log.Error(err, "Could not find CR's target node", "CR's Name", req.Name, "Expected node name", getNodeName(far)) utils.UpdateConditions(utils.RemediationFinishedNodeNotFound, far, r.Log) commonEvents.WarningEvent(r.Recorder, far, utils.EventReasonCrNodeNotFound, utils.EventMessageCrNodeNotFound) return emptyResult, err @@ -168,7 +168,7 @@ func (r *FenceAgentsRemediationReconciler) Reconcile(ctx context.Context, req ct // remove node's taints taint := utils.CreateRemediationTaint() - if err := utils.RemoveTaint(r.Client, far.Name, taint); err != nil { + if err := utils.RemoveTaint(r.Client, node.Name, taint); err != nil { if apiErrors.IsConflict(err) { r.Log.Info("Failed to remove taint from node due to node update, retrying... ,", "node name", node.Name, "taint key", taint.Key, "taint effect", taint.Effect) return ctrl.Result{RequeueAfter: time.Second}, nil @@ -179,7 +179,7 @@ func (r *FenceAgentsRemediationReconciler) Reconcile(ctx context.Context, req ct } } - r.Log.Info("FAR remediation taint was removed", "Node Name", req.Name) + r.Log.Info("FAR remediation taint was removed", "Node Name", node.Name) commonEvents.NormalEvent(r.Recorder, node, utils.EventReasonRemoveRemediationTaint, utils.EventMessageRemoveRemediationTaint) // remove finalizer controllerutil.RemoveFinalizer(far, v1alpha1.FARFinalizer) @@ -191,11 +191,11 @@ func (r *FenceAgentsRemediationReconciler) Reconcile(ctx context.Context, req ct return emptyResult, nil } // Add FAR (medik8s) remediation taint - taintAdded, err := utils.AppendTaint(r.Client, far.Name) + taintAdded, err := utils.AppendTaint(r.Client, node.Name) if err != nil { return emptyResult, err } else if taintAdded { - r.Log.Info("FAR remediation taint was added", "Node Name", req.Name) + r.Log.Info("FAR remediation taint was added", "Node Name", node.Name) commonEvents.NormalEvent(r.Recorder, node, utils.EventReasonAddRemediationTaint, utils.EventMessageAddRemediationTaint) } @@ -204,19 +204,19 @@ func (r *FenceAgentsRemediationReconciler) Reconcile(ctx context.Context, req ct // The remeditation has already been processed, thus we can begin with executing the FA for the node if r.Executor.Exists(far.GetUID()) { - r.Log.Info("A Fence Agent is already running", "Fence Agent", far.Spec.Agent, "Node Name", req.Name, "FAR uid", far.GetUID()) + r.Log.Info("A Fence Agent is already running", "Fence Agent", far.Spec.Agent, "Node Name", node.Name, "FAR uid", far.GetUID()) return emptyResult, nil } - r.Log.Info("Build fence agent command line", "Fence Agent", far.Spec.Agent, "Node Name", req.Name) + r.Log.Info("Build fence agent command line", "Fence Agent", far.Spec.Agent, "Node Name", node.Name) faParams, err := buildFenceAgentParams(far) if err != nil { - r.Log.Error(err, "Invalid shared or node parameters from CR", "Name", req.Name) + r.Log.Error(err, "Invalid shared or node parameters from CR", "Node Name", node.Name, "CR Name", req.Name) return emptyResult, nil } cmd := append([]string{far.Spec.Agent}, faParams...) - r.Log.Info("Execute the fence agent", "Fence Agent", far.Spec.Agent, "Node Name", req.Name, "FAR uid", far.GetUID()) + r.Log.Info("Execute the fence agent", "Fence Agent", far.Spec.Agent, "Node Name", node.Name, "FAR uid", far.GetUID()) r.Executor.AsyncExecute(ctx, far.GetUID(), cmd, far.Spec.RetryCount, far.Spec.RetryInterval.Duration, far.Spec.Timeout.Duration) commonEvents.NormalEvent(r.Recorder, far, utils.EventReasonFenceAgentExecuted, utils.EventMessageFenceAgentExecuted) return emptyResult, nil @@ -228,16 +228,16 @@ func (r *FenceAgentsRemediationReconciler) Reconcile(ctx context.Context, req ct // - try to remove workloads // - clean up Executor routine - r.Log.Info("Manual workload deletion", "Node Name", req.Name) + r.Log.Info("Manual workload deletion", "Node Name", node.Name) commonEvents.NormalEvent(r.Recorder, node, utils.EventReasonDeleteResources, utils.EventMessageDeleteResources) - if err := commonResources.DeletePods(ctx, r.Client, req.Name); err != nil { + if err := commonResources.DeletePods(ctx, r.Client, node.Name); err != nil { r.Log.Error(err, "Manual workload deletion has failed", "CR's Name", req.Name) return emptyResult, err } utils.UpdateConditions(utils.RemediationFinishedSuccessfully, far, r.Log) r.Executor.Remove(far.GetUID()) - r.Log.Info("FenceAgentsRemediation CR has completed to remediate the node", "Node Name", req.Name) + r.Log.Info("FenceAgentsRemediation CR has completed to remediate the node", "Node Name", node.Name) commonEvents.NormalEvent(r.Recorder, node, utils.EventReasonNodeRemediationCompleted, utils.EventMessageNodeRemediationCompleted) commonEvents.RemediationFinished(r.Recorder, far) } @@ -287,6 +287,18 @@ func (r *FenceAgentsRemediationReconciler) updateStatus(ctx context.Context, far return nil } +// getNodeName checks for the node name in far's commonAnnotations.NodeNameAnnotation if it does not exist it assumes the node name equals to far CR's name and return it. +func getNodeName(far *v1alpha1.FenceAgentsRemediation) string { + ann := far.GetAnnotations() + if ann == nil { + return far.GetName() + } + if nodeName, isNodeNameAnnotationExist := ann[commonAnnotations.NodeNameAnnotation]; isNodeNameAnnotationExist { + return nodeName + } + return far.GetName() +} + // buildFenceAgentParams collects the FAR's parameters for the node based on FAR CR, and if the CR is missing parameters // or the CR's name don't match nodeParameter name or it has an action which is different than reboot, then return an error func buildFenceAgentParams(far *v1alpha1.FenceAgentsRemediation) ([]string, error) { @@ -314,7 +326,7 @@ func buildFenceAgentParams(far *v1alpha1.FenceAgentsRemediation) ([]string, erro fenceAgentParams = appendParamToSlice(fenceAgentParams, parameterActionName, parameterActionValue) // append node parameters - nodeName := v1alpha1.NodeName(far.Name) + nodeName := v1alpha1.NodeName(getNodeName(far)) for paramName, nodeMap := range far.Spec.NodeParameters { if nodeVal, isFound := nodeMap[nodeName]; isFound { fenceAgentParams = appendParamToSlice(fenceAgentParams, paramName, nodeVal) diff --git a/controllers/fenceagentsremediation_controller_test.go b/controllers/fenceagentsremediation_controller_test.go index 30e21d77..dd791452 100644 --- a/controllers/fenceagentsremediation_controller_test.go +++ b/controllers/fenceagentsremediation_controller_test.go @@ -163,12 +163,8 @@ var _ = Describe("FAR Controller", func() { }) When("creating valid FAR CR", func() { - BeforeEach(func() { - node = utils.GetNode("", workerNode) - underTestFAR = getFenceAgentsRemediation(workerNode, fenceAgentIPMI, testShareParam, testNodeParam) - }) - It("should have finalizer, taint, while the two VAs and one pod will be deleted", func() { + testSuccessfulRemediation := func() { Eventually(func(g Gomega) { g.Expect(storedCommand).To(ConsistOf([]string{ "fence_ipmilan", @@ -180,7 +176,7 @@ var _ = Describe("FAR Controller", func() { "--ipport=6233"})) }, timeoutPreRemediation, pollInterval).Should(Succeed()) - underTestFAR = verifyPreRemediationSucceed(underTestFAR, workerNode, defaultNamespace, &farRemediationTaint) + underTestFAR = verifyPreRemediationSucceed(underTestFAR, defaultNamespace, &farRemediationTaint) By("Not having any test pod") verifyPodDeleted(testPodName) @@ -194,7 +190,23 @@ var _ = Describe("FAR Controller", func() { conditionStatusPointer(metav1.ConditionTrue)) // SucceededTypeStatus verifyEvent(corev1.EventTypeNormal, utils.EventReasonFenceAgentSucceeded, utils.EventMessageFenceAgentSucceeded) verifyEvent(corev1.EventTypeNormal, utils.EventReasonNodeRemediationCompleted, utils.EventMessageNodeRemediationCompleted) + } + BeforeEach(func() { + node = utils.GetNode("", workerNode) + underTestFAR = getFenceAgentsRemediation(workerNode, fenceAgentIPMI, testShareParam, testNodeParam) + }) + When("node name is stored in remediation name", func() { + It("should have finalizer, taint, while the two VAs and one pod will be deleted", testSuccessfulRemediation) + }) + //remediation is created from escalation remediation supporting same kind template + When("node name is stored in remediation's annotation", func() { + BeforeEach(func() { + underTestFAR.Name = fmt.Sprintf("%s-%s", workerNode, "pseudo-random-test-sufix") + underTestFAR.Annotations = map[string]string{"remediation.medik8s.io/node-name": workerNode} + }) + It("should have finalizer, taint, while the two VAs and one pod will be deleted", testSuccessfulRemediation) }) + }) When("creating invalid FAR CR Name", func() { @@ -255,7 +267,7 @@ var _ = Describe("FAR Controller", func() { }) It("should exit immediately without trying to update the status conditions", func() { - underTestFAR = verifyPreRemediationSucceed(underTestFAR, workerNode, defaultNamespace, &farRemediationTaint) + underTestFAR = verifyPreRemediationSucceed(underTestFAR, defaultNamespace, &farRemediationTaint) By("Wait some retries") Eventually(func() int { @@ -285,7 +297,7 @@ var _ = Describe("FAR Controller", func() { }) It("should exit immediately without trying to update the status conditions", func() { - underTestFAR = verifyPreRemediationSucceed(underTestFAR, workerNode, defaultNamespace, &farRemediationTaint) + underTestFAR = verifyPreRemediationSucceed(underTestFAR, defaultNamespace, &farRemediationTaint) By("Deleting FAR CR") Expect(k8sClient.Delete(context.Background(), underTestFAR)).To(Succeed()) @@ -308,7 +320,7 @@ var _ = Describe("FAR Controller", func() { }) It("should retry the fence agent command as configured and update the status accordingly", func() { - underTestFAR = verifyPreRemediationSucceed(underTestFAR, workerNode, defaultNamespace, &farRemediationTaint) + underTestFAR = verifyPreRemediationSucceed(underTestFAR, defaultNamespace, &farRemediationTaint) By("Still having one test pod") verifyPodExists(testPodName) @@ -338,7 +350,7 @@ var _ = Describe("FAR Controller", func() { }) It("should stop Fence Agent execution and update the status accordingly", func() { - underTestFAR = verifyPreRemediationSucceed(underTestFAR, workerNode, defaultNamespace, &farRemediationTaint) + underTestFAR = verifyPreRemediationSucceed(underTestFAR, defaultNamespace, &farRemediationTaint) By("Still having one test pod") verifyPodExists(testPodName) @@ -492,16 +504,16 @@ func verifyStatusCondition(far *v1alpha1.FenceAgentsRemediation, nodeName, condi } // verifyPreRemediationSucceed checks if the remediation CR already has a finazliaer and a remediation taint -func verifyPreRemediationSucceed(underTestFAR *v1alpha1.FenceAgentsRemediation, nodeName, namespace string, taint *corev1.Taint) *v1alpha1.FenceAgentsRemediation { +func verifyPreRemediationSucceed(underTestFAR *v1alpha1.FenceAgentsRemediation, namespace string, taint *corev1.Taint) *v1alpha1.FenceAgentsRemediation { By("Searching for finalizer ") - Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: nodeName, Namespace: namespace}, underTestFAR)).To(Succeed()) + Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: underTestFAR.GetName(), Namespace: namespace}, underTestFAR)).To(Succeed()) Expect(controllerutil.ContainsFinalizer(underTestFAR, v1alpha1.FARFinalizer)).To(BeTrue()) verifyEvent(corev1.EventTypeNormal, utils.EventReasonRemediationStarted, utils.EventMessageRemediationStarted) By("Searching for remediation taint if we have a finalizer") Eventually(func(g Gomega) { node := &corev1.Node{} - g.Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: nodeName}, node)).To(Succeed()) + g.Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: getNodeName(underTestFAR)}, node)).To(Succeed()) g.Expect(utils.TaintExists(node.Spec.Taints, taint)).To(BeTrue(), "remediation taint should exist") }, timeoutPreRemediation, pollInterval).Should(Succeed()) verifyEvent(corev1.EventTypeNormal, utils.EventReasonAddRemediationTaint, utils.EventMessageAddRemediationTaint) diff --git a/go.mod b/go.mod index 27ed2996..1a88f6ea 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/go-logr/logr v1.4.1 - github.com/medik8s/common v1.12.0 + github.com/medik8s/common v1.17.0 github.com/onsi/ginkgo/v2 v2.14.0 github.com/onsi/gomega v1.30.0 github.com/openshift/api v0.0.0-20230621174358-ea40115b9fa6 diff --git a/go.sum b/go.sum index 8af475cd..575464c1 100644 --- a/go.sum +++ b/go.sum @@ -78,8 +78,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.12.0 h1:UJ5VS4rbo/K0snfuqRiYam1NhXTwo4Q7fTng34YSlmA= -github.com/medik8s/common v1.12.0/go.mod h1:Q6YR2rgyiLl6ob4Mx2uDBmybAB3d94fImwoHPbeiE54= +github.com/medik8s/common v1.17.0 h1:AmJKx0tzqGZF27Ot0A4ak85q0F0zqUkVyCvYmm67rtY= +github.com/medik8s/common v1.17.0/go.mod h1:A9jYldC6PZcAuBowNNm712FqWdASB2ey5Vjp8MYN/PY= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= diff --git a/vendor/github.com/medik8s/common/pkg/annotations/annotations.go b/vendor/github.com/medik8s/common/pkg/annotations/annotations.go index 739e694f..aa993cc1 100644 --- a/vendor/github.com/medik8s/common/pkg/annotations/annotations.go +++ b/vendor/github.com/medik8s/common/pkg/annotations/annotations.go @@ -3,4 +3,11 @@ package annotations const ( // NhcTimeOut is the annotation set by NHC to signal the operator that it surpassed its timeout and shall stop its remediation NhcTimedOut = "remediation.medik8s.io/nhc-timed-out" + + // MultipleTemplatesSupportedAnnotation is an annotation that indicates whether multiple templates of the same kind are supported by the template's remediator + MultipleTemplatesSupportedAnnotation = "remediation.medik8s.io/multiple-templates-support" + + // NodeNameAnnotation is an annotation that contains the node name and is placed on CRs of remediators which supports multiple templates of the same kind. + // It's required in order for the remediator to "know" which unhealthy node the CR represents . + NodeNameAnnotation = "remediation.medik8s.io/node-name" ) diff --git a/vendor/github.com/medik8s/common/pkg/events/events.go b/vendor/github.com/medik8s/common/pkg/events/events.go index 7550d3c8..07d50a0d 100644 --- a/vendor/github.com/medik8s/common/pkg/events/events.go +++ b/vendor/github.com/medik8s/common/pkg/events/events.go @@ -9,9 +9,20 @@ import ( ) // Event message format "medik8s " -const customFmt = "[remediation] %s" +const ( + customFmt = "[remediation] %s" -// NormalEvent will record an event with type Normal and fixed message. + RemediationStartedEventReason = "RemediationStarted" + RemediationStoppedEventReason = "RemediationStopped" + RemediationFinishedEventReason = "RemediationFinished" + RemediationCannotStartEventReason = "RemediationCannotStart" + remediationStartedEventMessage = "Remediation started" + remediationStoppedEventMessage = "NHC added the timed-out annotation, remediation will be stopped" + remediationFinishedEventMessage = "Remediation finished" + remediationCannotStartTargetNodeFailedEventMessage = "Could not get remediation target Node" +) + +// NormalEvent will record an event with type Normal and custom message. func NormalEvent(recorder record.EventRecorder, object runtime.Object, reason, message string) { recorder.Event(object, corev1.EventTypeNormal, reason, fmt.Sprintf(customFmt, message)) } @@ -22,7 +33,7 @@ func NormalEventf(recorder record.EventRecorder, object runtime.Object, reason, recorder.Event(object, corev1.EventTypeNormal, reason, fmt.Sprintf(customFmt, message)) } -// WarningEvent will record an event with type Warning and fixed message. +// WarningEvent will record an event with type Warning and custom message. func WarningEvent(recorder record.EventRecorder, object runtime.Object, reason, message string) { recorder.Event(object, corev1.EventTypeWarning, reason, fmt.Sprintf(customFmt, message)) } @@ -35,17 +46,29 @@ func WarningEventf(recorder record.EventRecorder, object runtime.Object, reason, // Special case events -// RemediationStarted will record a Normal event with reason RemediationStarted and message Remediation started. +// RemediationStarted will record a Normal event to signal that the remediation has started. func RemediationStarted(recorder record.EventRecorder, object runtime.Object) { - NormalEvent(recorder, object, "RemediationStarted", "Remediation started") + NormalEvent(recorder, object, RemediationStartedEventReason, remediationStartedEventMessage) } -// RemediationStoppedByNHC will record a Normal event with reason RemediationStopped. +// RemediationStoppedByNHC will record a Normal event to signal that the remediation was stopped by the Node Healthcheck operator. func RemediationStoppedByNHC(recorder record.EventRecorder, object runtime.Object) { - NormalEvent(recorder, object, "RemediationStopped", "NHC added the timed-out annotation, remediation will be stopped") + NormalEvent(recorder, object, RemediationStoppedEventReason, remediationStoppedEventMessage) } -// RemediationFinished will record a Normal event with reason RemediationFinished and message Remediation finished. +// RemediationFinished will record a Normal event to signal that the remediation has finished. func RemediationFinished(recorder record.EventRecorder, object runtime.Object) { - NormalEvent(recorder, object, "RemediationFinished", "Remediation finished") + NormalEvent(recorder, object, RemediationFinishedEventReason, remediationFinishedEventMessage) +} + +// RemediationCannotStart will record a Warning event to signal that the remediation cannot start. A custom message can +// be used to further explain the reason. +func RemediationCannotStart(recorder record.EventRecorder, object runtime.Object, message string) { + WarningEvent(recorder, object, RemediationCannotStartEventReason, message) +} + +// GetTargetNodeFailed will record a Warning event to signal that the remediation cannot start because the target Node +// could not be found. +func GetTargetNodeFailed(recorder record.EventRecorder, object runtime.Object) { + RemediationCannotStart(recorder, object, remediationCannotStartTargetNodeFailedEventMessage) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 7729deb0..5cec6d45 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -96,7 +96,7 @@ 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.12.0 +# github.com/medik8s/common v1.17.0 ## explicit; go 1.20 github.com/medik8s/common/pkg/annotations github.com/medik8s/common/pkg/conditions