Skip to content

Commit d983c19

Browse files
authored
Merge pull request #21 from ryotarai/delete-node-op-if-remediated
Delete NodeOperation if the Node becomes remediated.
2 parents 3a2954d + e44f865 commit d983c19

2 files changed

Lines changed: 129 additions & 11 deletions

File tree

controllers/noderemediation_controller.go

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222

2323
nodeopsv1alpha1 "github.com/pfnet-research/node-operation-controller/api/v1alpha1"
2424
corev1 "k8s.io/api/core/v1"
25-
"k8s.io/apimachinery/pkg/api/errors"
25+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2626
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2727
"k8s.io/apimachinery/pkg/runtime"
2828
"k8s.io/apimachinery/pkg/types"
@@ -65,11 +65,7 @@ func (r *NodeRemediationReconciler) Reconcile(ctx context.Context, req ctrl.Requ
6565

6666
var remediation nodeopsv1alpha1.NodeRemediation
6767
if err := r.Get(ctx, req.NamespacedName, &remediation); err != nil {
68-
sterr, ok := err.(*errors.StatusError)
69-
if ok && sterr.Status().Code == 404 {
70-
return ctrl.Result{}, nil
71-
}
72-
return ctrl.Result{}, err
68+
return ctrl.Result{}, client.IgnoreNotFound(err)
7369
}
7470

7571
var node corev1.Node
@@ -115,11 +111,6 @@ func (r *NodeRemediationReconciler) Reconcile(ctx context.Context, req ctrl.Requ
115111
return ctrl.Result{}, err
116112
}
117113

118-
if remediation.Status.ActiveNodeOperation.Name != "" {
119-
// active operation exists
120-
return ctrl.Result{}, nil
121-
}
122-
123114
// Check node condition
124115
switch remediation.Status.NodeStatus {
125116
case nodeopsv1alpha1.NodeStatusUnknown:
@@ -131,6 +122,33 @@ func (r *NodeRemediationReconciler) Reconcile(ctx context.Context, req ctrl.Requ
131122
if err := r.Status().Update(ctx, &remediation); err != nil {
132123
return ctrl.Result{}, err
133124
}
125+
126+
if ref := remediation.Status.ActiveNodeOperation; ref.Name != "" {
127+
// active operation exists
128+
var nodeOp nodeopsv1alpha1.NodeOperation
129+
if err := r.Get(ctx, client.ObjectKey{Namespace: ref.Namespace, Name: ref.Name}, &nodeOp); apierrors.IsNotFound(err) {
130+
// Do nothing
131+
} else if err != nil {
132+
return ctrl.Result{}, err
133+
} else {
134+
if err := r.Delete(ctx, &nodeOp); err != nil {
135+
return ctrl.Result{}, err
136+
}
137+
138+
r.eventRecorder.Eventf(&remediation, corev1.EventTypeNormal, "DeleteNodeOperation", `Deleted NodeOperation %s because the Node is remediated`, nodeOp.Name)
139+
}
140+
141+
remediation.Status.ActiveNodeOperation = corev1.ObjectReference{}
142+
if err := r.Status().Update(ctx, &remediation); err != nil {
143+
return ctrl.Result{}, err
144+
}
145+
}
146+
147+
return ctrl.Result{}, nil
148+
}
149+
150+
if remediation.Status.ActiveNodeOperation.Name != "" {
151+
// active operation exists
134152
return ctrl.Result{}, nil
135153
}
136154

controllers/suite_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535

3636
batchv1 "k8s.io/api/batch/v1"
3737
corev1 "k8s.io/api/core/v1"
38+
apierrors "k8s.io/apimachinery/pkg/api/errors"
3839
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3940
"k8s.io/client-go/kubernetes/scheme"
4041
"k8s.io/client-go/rest"
@@ -725,4 +726,103 @@ var _ = Describe("NodeRemediation", func() {
725726
return false
726727
}, eventuallyTimeout).Should(BeTrue())
727728
})
729+
730+
It("deletes NodeOperation when the Node becomes remediated", func() {
731+
ctx := context.Background()
732+
nodeName := nodeNames[1]
733+
734+
template := nodeopsv1alpha1.NodeOperationTemplate{
735+
ObjectMeta: metav1.ObjectMeta{
736+
Name: "test-remediation-2",
737+
},
738+
Spec: nodeopsv1alpha1.NodeOperationTemplateSpec{
739+
Template: nodeopsv1alpha1.NodeOperationTemplateTemplateSpec{
740+
Spec: nodeopsv1alpha1.NodeOperationSpecTemplate{
741+
JobTemplate: nodeopsv1alpha1.JobTemplateSpec{
742+
Metadata: metav1.ObjectMeta{
743+
Namespace: "default",
744+
},
745+
Spec: batchv1.JobSpec{
746+
Template: corev1.PodTemplateSpec{
747+
Spec: corev1.PodSpec{
748+
Containers: []corev1.Container{{
749+
Name: "c",
750+
Image: "busybox",
751+
Command: []string{"sleep", "infinity"},
752+
}},
753+
RestartPolicy: corev1.RestartPolicyNever,
754+
Tolerations: []corev1.Toleration{
755+
{Key: controllerTaint.Key, Operator: corev1.TolerationOpExists},
756+
},
757+
},
758+
},
759+
},
760+
},
761+
},
762+
},
763+
},
764+
}
765+
Expect(k8sClient.Create(ctx, &template)).NotTo(HaveOccurred())
766+
767+
remediation := nodeopsv1alpha1.NodeRemediation{
768+
ObjectMeta: metav1.ObjectMeta{
769+
Name: "test-remediation-2",
770+
},
771+
Spec: nodeopsv1alpha1.NodeRemediationSpec{
772+
NodeRemediationSpecTemplate: nodeopsv1alpha1.NodeRemediationSpecTemplate{
773+
Rule: nodeopsv1alpha1.NodeRemediationRule{
774+
Conditions: []nodeopsv1alpha1.NodeConditionMatcher{
775+
{Type: "TestRemediation2", Status: corev1.ConditionTrue},
776+
},
777+
},
778+
NodeOperationTemplateName: template.Name,
779+
},
780+
NodeName: nodeName,
781+
},
782+
}
783+
Expect(k8sClient.Create(ctx, &remediation)).NotTo(HaveOccurred())
784+
785+
node := corev1.Node{}
786+
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: nodeName}, &node)).NotTo(HaveOccurred())
787+
788+
node.Status.Conditions = append(node.Status.Conditions, corev1.NodeCondition{
789+
Type: "TestRemediation2",
790+
Status: corev1.ConditionTrue,
791+
Reason: "testing",
792+
Message: "testing",
793+
LastHeartbeatTime: metav1.NewTime(time.Now()),
794+
LastTransitionTime: metav1.NewTime(time.Now()),
795+
})
796+
Expect(k8sClient.Status().Update(ctx, &node)).NotTo(HaveOccurred())
797+
798+
var nodeOp *nodeopsv1alpha1.NodeOperation
799+
Eventually(func() bool {
800+
nodeOpList := nodeopsv1alpha1.NodeOperationList{}
801+
Expect(k8sClient.List(ctx, &nodeOpList)).NotTo(HaveOccurred())
802+
803+
for _, op := range nodeOpList.Items {
804+
for _, owner := range op.OwnerReferences {
805+
if owner.Kind == "NodeRemediation" && owner.Name == remediation.Name {
806+
nodeOp = &op
807+
return true
808+
}
809+
}
810+
}
811+
812+
return false
813+
}, eventuallyTimeout).Should(BeTrue())
814+
815+
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: nodeName}, &node)).NotTo(HaveOccurred())
816+
node.Status.Conditions[len(node.Status.Conditions)-1].Status = corev1.ConditionFalse
817+
Expect(k8sClient.Status().Update(ctx, &node)).NotTo(HaveOccurred())
818+
819+
Eventually(func() bool {
820+
err := k8sClient.Get(ctx, client.ObjectKey{
821+
Namespace: nodeOp.Namespace,
822+
Name: nodeOp.Name,
823+
}, &nodeopsv1alpha1.NodeOperation{})
824+
825+
return apierrors.IsNotFound(err)
826+
}, eventuallyTimeout).Should(BeTrue())
827+
})
728828
})

0 commit comments

Comments
 (0)