Skip to content

Commit

Permalink
Merge pull request #133 from mshitrit/match_labels
Browse files Browse the repository at this point in the history
Match labels
  • Loading branch information
openshift-merge-robot authored Aug 3, 2023
2 parents 044ff33 + e5e5301 commit 9f835af
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 16 deletions.
9 changes: 6 additions & 3 deletions controllers/selfnoderemediation_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,8 +543,9 @@ func verifyNodeIsUnschedulable() *v1.Node {
func verifySelfNodeRemediationPodExist() {
podList := &v1.PodList{}
selector := labels.NewSelector()
requirement, _ := labels.NewRequirement("app", selection.Equals, []string{"self-node-remediation-agent"})
selector = selector.Add(*requirement)
nameRequirement, _ := labels.NewRequirement("app.kubernetes.io/name", selection.Equals, []string{"self-node-remediation"})
componentRequirement, _ := labels.NewRequirement("app.kubernetes.io/component", selection.Equals, []string{"agent"})
selector = selector.Add(*nameRequirement, *componentRequirement)

EventuallyWithOffset(1, func() (int, error) {
err := k8sClient.Client.List(context.Background(), podList, &client.ListOptions{LabelSelector: selector})
Expand All @@ -567,7 +568,9 @@ func createSNR(strategy v1alpha1.RemediationStrategyType) {
func createSelfNodeRemediationPod() {
pod := &v1.Pod{}
pod.Spec.NodeName = unhealthyNodeName
pod.Labels = map[string]string{"app": "self-node-remediation-agent"}
pod.Labels = map[string]string{"app.kubernetes.io/name": "self-node-remediation",
"app.kubernetes.io/component": "agent"}

pod.Name = "self-node-remediation"
pod.Namespace = namespace
container := v1.Container{
Expand Down
40 changes: 40 additions & 0 deletions controllers/selfnoderemediationconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ import (
"os"

"github.com/go-logr/logr"
pkgerrors "github.com/pkg/errors"

v1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
Expand All @@ -38,6 +40,10 @@ import (
"github.com/medik8s/self-node-remediation/pkg/render"
)

const (
lastChangedAnnotationKey = "snr.medik8s.io/force-deletion-revision"
)

// SelfNodeRemediationConfigReconciler reconciles a SelfNodeRemediationConfig object
type SelfNodeRemediationConfigReconciler struct {
client.Client
Expand Down Expand Up @@ -143,6 +149,9 @@ func (r *SelfNodeRemediationConfigReconciler) syncConfigDaemonSet(ctx context.Co

// Sync DaemonSets
for _, obj := range objs {
if err := r.removeOldDsOnOperatorUpdate(ctx, obj.GetName(), obj.GetAnnotations()[lastChangedAnnotationKey]); err != nil {
return err
}
err = r.syncK8sResource(ctx, snrConfig, obj)
if err != nil {
logger.Error(err, "Couldn't sync self-node-remediation daemons objects")
Expand Down Expand Up @@ -243,3 +252,34 @@ func (r *SelfNodeRemediationConfigReconciler) convertTolerationsToUnstructed(tol
}
return convertedTolerations, nil
}

func (r *SelfNodeRemediationConfigReconciler) removeOldDsOnOperatorUpdate(ctx context.Context, dsName string, lastVersion string) error {
ds := &v1.DaemonSet{}
key := types.NamespacedName{
Namespace: r.Namespace,
Name: dsName,
}

if err := r.Client.Get(ctx, key, ds); err != nil {
if !errors.IsNotFound(err) {
r.Log.Error(err, "snr install/update failed error when trying to fetch old daemonset")
return pkgerrors.Wrap(err, "unable to fetch daemon set")
}
r.Log.Info("snr didn't find old daemonset to be deleted")
return nil

}

if lastChangedFoundVal, _ := ds.Annotations[lastChangedAnnotationKey]; lastChangedFoundVal == lastVersion {
//ds is up-to-date this is not an update scenario
return nil
}

if err := r.Client.Delete(ctx, ds); err != nil {
r.Log.Error(err, "snr update failed could not delete old daemonset")
return pkgerrors.Wrap(err, "unable to delete old daemon set")
}
r.Log.Info("snr update old daemonset deleted")
return nil

}
97 changes: 89 additions & 8 deletions controllers/selfnoderemediationconfig_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ var _ = Describe("snrc controller Test", func() {
})

Context("DS installation", func() {
key := types.NamespacedName{
Namespace: namespace,
Name: dsName,
}

JustBeforeEach(func() {
Expect(k8sClient.Create(context.Background(), config)).To(Succeed())
DeferCleanup(func() {
Expand Down Expand Up @@ -69,10 +74,6 @@ var _ = Describe("snrc controller Test", func() {
})

It("Daemonset should be created", func() {
key := types.NamespacedName{
Namespace: namespace,
Name: dsName,
}
Eventually(func() error {
return k8sClient.Get(context.Background(), key, ds)
}, 10*time.Second, 250*time.Millisecond).Should(BeNil())
Expand All @@ -96,10 +97,6 @@ var _ = Describe("snrc controller Test", func() {
config.Spec.CustomDsTolerations = []corev1.Toleration{expectedToleration}
})
It("Daemonset should have customized tolerations", func() {
key := types.NamespacedName{
Namespace: namespace,
Name: dsName,
}
Eventually(func() error {
return k8sClient.Get(context.Background(), key, ds)
}, 10*time.Second, 250*time.Millisecond).Should(BeNil())
Expand All @@ -122,6 +119,49 @@ var _ = Describe("snrc controller Test", func() {

})
})

Context("DS Recreation on Operator Update", func() {
var timeToWaitForDsUpdate = 6 * time.Second
var oldDsVersion, currentDsVersion = "0", "1"

JustBeforeEach(func() {
Expect(k8sClient.Create(context.Background(), ds)).To(Succeed())
Eventually(func() error {
return k8sClient.Get(context.Background(), key, ds)
}, 2*time.Second, 250*time.Millisecond).Should(BeNil())

})
When("ds version has not changed", func() {
BeforeEach(func() {
ds = generateDs(dsName, namespace, currentDsVersion)
})
It("Daemonset should not recreated", func() {
//Wait to make sure DS isn't recreated
time.Sleep(timeToWaitForDsUpdate)
Expect(k8sClient.Get(context.Background(), key, ds)).To(BeNil())
Expect(ds.Annotations["original-ds"]).To(Equal("true"))

})
})

When("ds version has changed", func() {
BeforeEach(func() {
//creating an DS with old version
ds = generateDs(dsName, namespace, oldDsVersion)
})
It("Daemonset should be recreated", func() {
//Wait until DS is recreated
Eventually(func() bool {
if err := k8sClient.Get(context.Background(), key, ds); err == nil {
return ds.Annotations["snr.medik8s.io/force-deletion-revision"] == currentDsVersion
}
return false
}, timeToWaitForDsUpdate, 250*time.Millisecond).Should(BeTrue())
Expect(ds.Annotations["original-ds"]).To(Equal(""))

})
})
})
})

Context("SNRC defaults", func() {
Expand Down Expand Up @@ -219,3 +259,44 @@ func getEnvVarMap(vars []corev1.EnvVar) map[string]corev1.EnvVar {
}
return m
}

func generateDs(name, namespace, version string) *appsv1.DaemonSet {
return &appsv1.DaemonSet{
TypeMeta: metav1.TypeMeta{
Kind: "DaemonSet",
APIVersion: "apps/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{"snr.medik8s.io/force-deletion-revision": version, "original-ds": "true"},
},
Spec: appsv1.DaemonSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "example",
},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": "example",
},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "example-container",
Image: "busybox",
Command: []string{
"/bin/sh",
"-c",
"while true; do echo hello; sleep 10;done",
},
},
},
},
},
},
}
}
9 changes: 6 additions & 3 deletions install/self-node-remediation-deamonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ metadata:
namespace: {{.Namespace}}
labels:
k8s-app: self-node-remediation
annotations:
snr.medik8s.io/force-deletion-revision: "1"
spec:
selector:
matchLabels:
control-plane: controller-manager
app.kubernetes.io/name: self-node-remediation
app.kubernetes.io/component: agent
template:
metadata:
creationTimestamp: null
labels:
control-plane: controller-manager
app: self-node-remediation-agent
app.kubernetes.io/name: self-node-remediation
app.kubernetes.io/component: agent
spec:
volumes:
- name: devices
Expand Down
5 changes: 3 additions & 2 deletions pkg/utils/pods.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ func GetSelfNodeRemediationAgentPod(nodeName string, r client.Reader) (*v1.Pod,
podList := &v1.PodList{}

selector := labels.NewSelector()
requirement, _ := labels.NewRequirement("app", selection.Equals, []string{"self-node-remediation-agent"})
selector = selector.Add(*requirement)
nameRequirement, _ := labels.NewRequirement("app.kubernetes.io/name", selection.Equals, []string{"self-node-remediation"})
componentRequirement, _ := labels.NewRequirement("app.kubernetes.io/component", selection.Equals, []string{"agent"})
selector = selector.Add(*nameRequirement, *componentRequirement)

err := r.List(context.Background(), podList, &client.ListOptions{LabelSelector: selector})
if err != nil {
Expand Down

0 comments on commit 9f835af

Please sign in to comment.