diff --git a/Dockerfile b/Dockerfile index b1b6bc17a..ccf30f4ce 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,6 +39,8 @@ RUN GOARCH=${TARGETARCH} make bin/node-problem-detector bin/health-checker bin/l ARG BASEIMAGE FROM --platform=${TARGETPLATFORM} ${BASEIMAGE} +RUN echo foo + LABEL maintainer="Random Liu " RUN clean-install util-linux bash libsystemd-dev diff --git a/README.md b/README.md index 3ef9df432..baea2a631 100644 --- a/README.md +++ b/README.md @@ -142,20 +142,19 @@ For example, to run without auth, use the following config: ### Tainting Nodes You can enable node tainting feature to the response of permanent node problems. For example, on the file [config/kernel-monitor.json](config/kernel-monitor.json), -set boolean flag `taintEnabled` as `true` if you wish to taint your nodes when `ReadOnlyFileSystem` problem and untaint the node when the -problem is resolved. This feature is disabled by default but you can enable it like below: +put a `TaintConfig` object as following for required `Condition` as you need. You can omit the `TaintConfig` or disable it by setting `enabled` as false. By default, it is disabled and will not be enabled until you need it. ```json -...omitted for brevity... { "type": "ReadonlyFilesystem", "reason": "FilesystemIsNotReadOnly", "message": "Filesystem is not read-only", - "taintEnabled": true, - "taintKey": "node-problem-detector", - "taintValue": "ReadonlyFilesystem", - "taintEffect": "NoSchedule" + "taintConfig": { + "enabled": false, + "key": "node-problem-detector/read-only-filesystem", + "value": "true", + "effect": "NoSchedule" + } } -...omitted for brevity... ``` ## Build Image diff --git a/config/kernel-monitor.json b/config/kernel-monitor.json index a699ccbe3..b688361f3 100644 --- a/config/kernel-monitor.json +++ b/config/kernel-monitor.json @@ -10,19 +10,23 @@ "type": "KernelDeadlock", "reason": "KernelHasNoDeadlock", "message": "kernel has no deadlock", - "taintEnabled": false, - "taintKey": "node-problem-detector", - "taintValue": "KernelDeadlock", - "taintEffect": "NoSchedule" + "taintConfig": { + "enabled": false, + "key": "node-problem-detector/kernel-deadlock", + "value": "true", + "effect": "NoSchedule" + } }, { "type": "ReadonlyFilesystem", "reason": "FilesystemIsNotReadOnly", "message": "Filesystem is not read-only", - "taintEnabled": false, - "taintKey": "node-problem-detector", - "taintValue": "ReadonlyFilesystem", - "taintEffect": "NoSchedule" + "taintConfig": { + "enabled": false, + "key": "node-problem-detector/read-only-filesystem", + "value": "true", + "effect": "NoSchedule" + } } ], "rules": [ @@ -71,35 +75,17 @@ "reason": "MemoryReadError", "pattern": "CE memory read error .*" }, - { - "type": "permanent", - "condition": "KernelDeadlock", - "reason": "AUFSUmountHung", - "pattern": "task umount\\.aufs:\\w+ blocked for more than \\w+ seconds\\.", - "taintEnabled": false, - "taintKey": "node-problem-detector", - "taintValue": "KernelDeadlock", - "taintEffect": "NoSchedule" - }, { "type": "permanent", "condition": "KernelDeadlock", "reason": "DockerHung", - "pattern": "task docker:\\w+ blocked for more than \\w+ seconds\\.", - "taintEnabled": false, - "taintKey": "node-problem-detector", - "taintValue": "KernelDeadlock", - "taintEffect": "NoSchedule" + "pattern": "task docker:\\w+ blocked for more than \\w+ seconds\\." }, { "type": "permanent", "condition": "ReadonlyFilesystem", "reason": "FilesystemIsReadOnly", - "pattern": "Remounting filesystem read-only", - "taintEnabled": true, - "taintKey": "node-problem-detector", - "taintValue": "ReadonlyFilesystem", - "taintEffect": "NoSchedule" + "pattern": "Remounting filesystem read-only" } ] } diff --git a/deployment/node-problem-detector-config.yaml b/deployment/node-problem-detector-config.yaml index 3162f6ace..b3ae25235 100644 --- a/deployment/node-problem-detector-config.yaml +++ b/deployment/node-problem-detector-config.yaml @@ -12,19 +12,23 @@ data: "type": "KernelDeadlock", "reason": "KernelHasNoDeadlock", "message": "kernel has no deadlock", - "taintEnabled": false, - "taintKey": "node-problem-detector", - "taintValue": "KernelDeadlock", - "taintEffect": "NoSchedule" + "taintConfig": { + "enabled": false, + "key": "node-problem-detector/kernel-deadlock", + "value": "true", + "effect": "NoSchedule" + } }, { "type": "ReadonlyFilesystem", "reason": "FilesystemIsNotReadOnly", "message": "Filesystem is not read-only", - "taintEnabled": false, - "taintKey": "node-problem-detector", - "taintValue": "ReadonlyFilesystem", - "taintEffect": "NoSchedule" + "taintConfig": { + "enabled": true, + "key": "node-problem-detector/read-only-filesystem", + "value": "true", + "effect": "NoSchedule" + } } ], "rules": [ @@ -62,31 +66,19 @@ data: "type": "permanent", "condition": "KernelDeadlock", "reason": "AUFSUmountHung", - "pattern": "task umount\\.aufs:\\w+ blocked for more than \\w+ seconds\\.", - "taintEnabled": false, - "taintKey": "node-problem-detector", - "taintValue": "KernelDeadlock", - "taintEffect": "NoSchedule" + "pattern": "task umount\\.aufs:\\w+ blocked for more than \\w+ seconds\\." }, { "type": "permanent", "condition": "KernelDeadlock", "reason": "DockerHung", - "pattern": "task docker:\\w+ blocked for more than \\w+ seconds\\.", - "taintEnabled": false, - "taintKey": "node-problem-detector", - "taintValue": "KernelDeadlock", - "taintEffect": "NoSchedule" + "pattern": "task docker:\\w+ blocked for more than \\w+ seconds\\." }, { "type": "permanent", "condition": "ReadonlyFilesystem", "reason": "FilesystemIsReadOnly", - "pattern": "Remounting filesystem read-only", - "taintEnabled": false, - "taintKey": "node-problem-detector", - "taintValue": "ReadonlyFilesystem", - "taintEffect": "NoSchedule" + "pattern": "Remounting filesystem read-only" } ] } diff --git a/pkg/exporters/k8sexporter/condition/manager.go b/pkg/exporters/k8sexporter/condition/manager.go index 3d2f02b1d..8df4ccbf7 100644 --- a/pkg/exporters/k8sexporter/condition/manager.go +++ b/pkg/exporters/k8sexporter/condition/manager.go @@ -163,22 +163,54 @@ func (c *conditionManager) sync(ctx context.Context) { for i := range c.conditions { conditions = append(conditions, problemutil.ConvertToAPICondition(c.conditions[i])) - if c.conditions[i].TaintEnabled && c.conditions[i].Status == types.True { - taintString := fmt.Sprintf("%s=%s:%s", c.conditions[i].TaintKey, c.conditions[i].TaintValue, - c.conditions[i].TaintEffect) - glog.Infof("tainting is enabled and condition status is True, tainting with %s\n", taintString) - if err := c.client.TaintNode(ctx, c.conditions[i]); err != nil { - glog.Errorf("failed to add taint %v to node: %v", taintString, err) - return + condition := c.conditions[i] + if condition.TaintConfig == nil || !condition.TaintConfig.Enabled { + // we are skipping tainting since TaintConfig of our condition is nil or disabled + continue + } + + taintStr := fmt.Sprintf("%s=%s:%s", c.conditions[i].TaintConfig.Key, c.conditions[i].TaintConfig.Value, + c.conditions[i].TaintConfig.Effect) + + node, err := c.client.GetNode(ctx) + if err != nil { + glog.Errorf("failed to get node: %v", err) + continue + } + + taintExists := problemclient.CheckIfTaintAlreadyExists(node, *condition.TaintConfig) + + switch condition.Status { + case types.True: + if taintExists { + // we are skipping here since node is already tainted with our TaintConfig + continue + } + + glog.Infof("for condition %s, tainting is enabled and status is True, tainting with %s", + condition.Type, taintStr) + + if err := c.client.TaintNode(ctx, node, condition); err != nil { + glog.Errorf("failed to add taint %v: %v", taintStr, err) + continue } - } else if c.conditions[i].TaintEnabled && c.conditions[i].Status == types.False { - taintString := fmt.Sprintf("%s=%s:%s", c.conditions[i].TaintKey, c.conditions[i].TaintValue, - c.conditions[i].TaintEffect) - glog.Infof("tainting is enabled and condition status is False, removing taint %s\n", taintString) - if err := c.client.UntaintNode(ctx, c.conditions[i]); err != nil { - glog.Errorf("failed to remove taint %v from node: %v", taintString, err) - return + + glog.Infof("successfully tainted node with %s", taintStr) + case types.False: + if !taintExists { + // we are skipping here since node is not tainted with our TaintConfig + continue } + + glog.Infof("for condition %s, tainting is enabled and condition status is False, removing taint %s", + condition.Type, taintStr) + + if err := c.client.UntaintNode(ctx, node, condition); err != nil { + glog.Errorf("failed to remove taint %v: %v", taintStr, err) + continue + } + + glog.Infof("successfully removed taint %s from node", taintStr) } } if err := c.client.SetConditions(ctx, conditions); err != nil { diff --git a/pkg/exporters/k8sexporter/condition/manager_test.go b/pkg/exporters/k8sexporter/condition/manager_test.go index bea833f93..69c6b6af6 100644 --- a/pkg/exporters/k8sexporter/condition/manager_test.go +++ b/pkg/exporters/k8sexporter/condition/manager_test.go @@ -22,6 +22,8 @@ import ( "testing" "time" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/stretchr/testify/assert" "k8s.io/node-problem-detector/pkg/exporters/k8sexporter/problemclient" @@ -126,6 +128,220 @@ func TestResync(t *testing.T) { assert.True(t, m.needResync(), "Should resync after resync period and resync is needed") } +func TestSync(t *testing.T) { + cases := []struct { + caseName string + condition types.Condition + node *v1.Node + injectError bool + errorKey string + }{ + {"Sync success with Status True and nil taint config", + types.Condition{ + Type: "ReadonlyFilesystem", + Status: "True", + }, &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-node", + }, + Spec: v1.NodeSpec{ + Taints: []v1.Taint{ + { + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + }, false, "TaintNode", + }, + {"Sync success with Status True and disabled taint config", + types.Condition{ + Type: "ReadonlyFilesystem", + Status: "True", + TaintConfig: &types.TaintConfig{ + Enabled: false, + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: string(v1.TaintEffectNoSchedule), + }, + }, &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-node", + }, + Spec: v1.NodeSpec{ + Taints: []v1.Taint{ + { + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + }, false, "", + }, + {"Sync failure with Status True and TaintNode error", + types.Condition{ + Type: "ReadonlyFilesystem", + Status: "True", + TaintConfig: &types.TaintConfig{ + Enabled: true, + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: string(v1.TaintEffectNoSchedule), + }, + }, &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-node", + }, + Spec: v1.NodeSpec{}, + }, true, "TaintNode"}, + {"Sync failure with Status True and GetNode error", + types.Condition{ + Type: "ReadonlyFilesystem", + Status: "True", + TaintConfig: &types.TaintConfig{ + Enabled: true, + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: string(v1.TaintEffectNoSchedule), + }, + }, nil, true, "GetNode"}, + {"Sync success with Status True and non-nil and enabled taint config", + types.Condition{ + Type: "ReadonlyFilesystem", + Status: "True", + TaintConfig: &types.TaintConfig{ + Enabled: true, + Key: "node-problem-detector/read-only", + Value: "true", + Effect: string(v1.TaintEffectNoSchedule), + }, + }, &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-node", + }, + Spec: v1.NodeSpec{ + Taints: []v1.Taint{ + { + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + }, false, "", + }, + {"Sync success with Status True and already tainted node", + types.Condition{ + Type: "ReadonlyFilesystem", + Status: "True", + TaintConfig: &types.TaintConfig{ + Enabled: true, + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: string(v1.TaintEffectNoSchedule), + }, + }, &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-node", + }, + Spec: v1.NodeSpec{ + Taints: []v1.Taint{ + { + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + }, false, "", + }, + {"Sync success with Status False", + types.Condition{ + Type: "ReadonlyFilesystem", + Status: "False", + TaintConfig: &types.TaintConfig{ + Enabled: true, + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: string(v1.TaintEffectNoSchedule), + }, + }, &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-node", + }, + Spec: v1.NodeSpec{ + Taints: []v1.Taint{ + { + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + }, false, "", + }, + {"Sync success with Status False and taint not exists", + types.Condition{ + Type: "ReadonlyFilesystem", + Status: "False", + TaintConfig: &types.TaintConfig{ + Enabled: true, + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: string(v1.TaintEffectNoSchedule), + }, + }, &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-node", + }, + Spec: v1.NodeSpec{}, + }, false, "", + }, + {"Sync failure with Status False", + types.Condition{ + Type: "ReadonlyFilesystem", + Status: "False", + TaintConfig: &types.TaintConfig{ + Enabled: true, + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: string(v1.TaintEffectNoSchedule), + }, + }, &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-node", + }, + Spec: v1.NodeSpec{ + Taints: []v1.Taint{ + { + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + }, true, "UntaintNode", + }, + } + + for _, tc := range cases { + m, fakeClient, _ := newTestManager() + m.conditions = map[string]types.Condition{tc.condition.Type: tc.condition} + + if tc.node != nil { + fakeClient.InjectNode("mynode", tc.node) + } + + if tc.injectError { + fakeClient.InjectError(tc.errorKey, fmt.Errorf("injected error")) + } + + m.sync(context.Background()) + } +} + func TestHeartbeat(t *testing.T) { m, fakeClient, fakeClock := newTestManager() condition := newTestCondition("TestCondition") diff --git a/pkg/exporters/k8sexporter/problemclient/fake_problem_client.go b/pkg/exporters/k8sexporter/problemclient/fake_problem_client.go index ee802ff6f..58c515ab6 100644 --- a/pkg/exporters/k8sexporter/problemclient/fake_problem_client.go +++ b/pkg/exporters/k8sexporter/problemclient/fake_problem_client.go @@ -22,9 +22,8 @@ import ( "reflect" "sync" - "k8s.io/node-problem-detector/pkg/types" - v1 "k8s.io/api/core/v1" + "k8s.io/node-problem-detector/pkg/types" ) // FakeProblemClient is a fake problem client for debug. @@ -32,6 +31,7 @@ type FakeProblemClient struct { sync.Mutex conditions map[v1.NodeConditionType]v1.NodeCondition errors map[string]error + nodes map[string]*v1.Node } // NewFakeProblemClient creates a new fake problem client. @@ -39,6 +39,7 @@ func NewFakeProblemClient() *FakeProblemClient { return &FakeProblemClient{ conditions: make(map[v1.NodeConditionType]v1.NodeCondition), errors: make(map[string]error), + nodes: make(map[string]*v1.Node), } } @@ -49,6 +50,13 @@ func (f *FakeProblemClient) InjectError(fun string, err error) { f.errors[fun] = err } +// InjectNode injects node to specific function. +func (f *FakeProblemClient) InjectNode(fun string, node *v1.Node) { + f.Lock() + defer f.Unlock() + f.nodes[fun] = node +} + // AssertConditions asserts that the internal conditions in fake problem client should match // the expected conditions. func (f *FakeProblemClient) AssertConditions(expected []v1.NodeCondition) error { @@ -76,13 +84,21 @@ func (f *FakeProblemClient) SetConditions(ctx context.Context, conditions []v1.N } // TaintNode taints the node if tainting is enabled and problem occurred -func (f *FakeProblemClient) TaintNode(ctx context.Context, condition types.Condition) error { - return fmt.Errorf("TaintNode() not implemented") +func (f *FakeProblemClient) TaintNode(ctx context.Context, node *v1.Node, condition types.Condition) error { + if err, ok := f.errors["TaintNode"]; ok { + return err + } + + return nil } // UntaintNode removes taint from node if tainting is enabled and problem resolved -func (f *FakeProblemClient) UntaintNode(ctx context.Context, condition types.Condition) error { - return fmt.Errorf("UntaintNode() not implemented") +func (f *FakeProblemClient) UntaintNode(ctx context.Context, node *v1.Node, condition types.Condition) error { + if err, ok := f.errors["UntaintNode"]; ok { + return err + } + + return nil } // GetConditions is a fake mimic of GetConditions, it returns the conditions cached internally. @@ -107,5 +123,9 @@ func (f *FakeProblemClient) Eventf(eventType string, source, reason, messageFmt } func (f *FakeProblemClient) GetNode(ctx context.Context) (*v1.Node, error) { - return nil, fmt.Errorf("GetNode() not implemented") + if err, ok := f.errors["GetNode"]; ok { + return nil, err + } + + return f.nodes["mynode"], nil } diff --git a/pkg/exporters/k8sexporter/problemclient/problem_client.go b/pkg/exporters/k8sexporter/problemclient/problem_client.go index 89f46ce64..64e82e8c3 100644 --- a/pkg/exporters/k8sexporter/problemclient/problem_client.go +++ b/pkg/exporters/k8sexporter/problemclient/problem_client.go @@ -53,9 +53,9 @@ type Client interface { // node-problem-detector runs. GetNode(ctx context.Context) (*v1.Node, error) // TaintNode taints the node if tainting is enabled on the config file on specific conditions - TaintNode(ctx context.Context, condition types2.Condition) error + TaintNode(ctx context.Context, node *v1.Node, condition types2.Condition) error // UntaintNode removes taint from node if tainting is enabled on the config file on specific conditions, and problem recovered - UntaintNode(ctx context.Context, condition types2.Condition) error + UntaintNode(ctx context.Context, node *v1.Node, condition types2.Condition) error } type nodeProblemClient struct { @@ -142,22 +142,11 @@ func (c *nodeProblemClient) GetNode(ctx context.Context) (*v1.Node, error) { } // TaintNode taints the node if tainting is enabled and problem occurred -func (c *nodeProblemClient) TaintNode(ctx context.Context, condition types2.Condition) error { - node, err := c.client.Nodes().Get(ctx, c.nodeName, metav1.GetOptions{}) - if err != nil { - return err - } - - for _, v := range node.Spec.Taints { - if v.Key == condition.TaintKey && v.Value == condition.TaintValue && v.Effect == v1.TaintEffect(condition.TaintEffect) { - return nil - } - } - +func (c *nodeProblemClient) TaintNode(ctx context.Context, node *v1.Node, condition types2.Condition) (err error) { node.Spec.Taints = append(node.Spec.Taints, v1.Taint{ - Key: condition.TaintKey, - Value: condition.TaintValue, - Effect: v1.TaintEffect(condition.TaintEffect), + Key: condition.TaintConfig.Key, + Value: condition.TaintConfig.Value, + Effect: v1.TaintEffect(condition.TaintConfig.Effect), }) _, err = c.client.Nodes().Update(ctx, node, metav1.UpdateOptions{}) @@ -169,15 +158,10 @@ func (c *nodeProblemClient) TaintNode(ctx context.Context, condition types2.Cond } // UntaintNode removes taint from node if tainting is enabled on the config file on specific conditions, and problem recovered -func (c *nodeProblemClient) UntaintNode(ctx context.Context, condition types2.Condition) error { - node, err := c.client.Nodes().Get(ctx, c.nodeName, metav1.GetOptions{}) - if err != nil { - return err - } - +func (c *nodeProblemClient) UntaintNode(ctx context.Context, node *v1.Node, condition types2.Condition) (err error) { var taints []v1.Taint for _, v := range node.Spec.Taints { - if v.Key == condition.TaintKey && v.Value == condition.TaintValue && v.Effect == v1.TaintEffect(condition.TaintEffect) { + if v.Key == condition.TaintConfig.Key && v.Value == condition.TaintConfig.Value && v.Effect == v1.TaintEffect(condition.TaintConfig.Effect) { continue } @@ -220,3 +204,14 @@ func getNodeRef(namespace, nodeName string) *v1.ObjectReference { Namespace: namespace, } } + +func CheckIfTaintAlreadyExists(node *v1.Node, config types2.TaintConfig) bool { + for _, v := range node.Spec.Taints { + // returning true since our target node is already tainted + if v.Key == config.Key && v.Value == config.Value && v.Effect == v1.TaintEffect(config.Effect) { + return true + } + } + + return false +} diff --git a/pkg/exporters/k8sexporter/problemclient/problem_client_test.go b/pkg/exporters/k8sexporter/problemclient/problem_client_test.go index 9f80c5d81..a4ba1c261 100644 --- a/pkg/exporters/k8sexporter/problemclient/problem_client_test.go +++ b/pkg/exporters/k8sexporter/problemclient/problem_client_test.go @@ -19,6 +19,7 @@ package problemclient import ( "encoding/json" "fmt" + "k8s.io/node-problem-detector/pkg/types" "testing" "time" @@ -86,3 +87,58 @@ func TestEvent(t *testing.T) { t.Errorf("expected event %q, got %q", expected, got) } } + +func TestCheckIfTaintAlreadyExists(t *testing.T) { + cases := []struct { + node *v1.Node + conf types.TaintConfig + result bool + }{ + {&v1.Node{ + Spec: v1.NodeSpec{ + Taints: []v1.Taint{ + { + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + }, types.TaintConfig{ + Enabled: false, + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: string(v1.TaintEffectNoSchedule), + }, + true, + }, + {&v1.Node{ + Spec: v1.NodeSpec{ + Taints: []v1.Taint{ + { + Key: "node-problem-detector/read-only-filesystem", + Value: "true", + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + }, types.TaintConfig{ + Enabled: false, + Key: "node-problem-detector/read-write-filesystem", + Value: "true", + Effect: string(v1.TaintEffectNoSchedule), + }, + false, + }, + } + + for _, tc := range cases { + exists := CheckIfTaintAlreadyExists(tc.node, tc.conf) + + if tc.result { + assert.True(t, exists) + } else { + assert.False(t, exists) + } + } +} diff --git a/pkg/systemlogmonitor/log_monitor.go b/pkg/systemlogmonitor/log_monitor.go index de18e1409..254ae5448 100644 --- a/pkg/systemlogmonitor/log_monitor.go +++ b/pkg/systemlogmonitor/log_monitor.go @@ -197,10 +197,6 @@ func (l *logMonitor) generateStatus(logs []*systemlogtypes.Log, rule systemlogty } condition.Status = types.True condition.Reason = rule.Reason - condition.TaintEnabled = rule.TaintEnabled - condition.TaintKey = rule.TaintKey - condition.TaintValue = rule.TaintValue - condition.TaintEffect = rule.TaintEffect changedConditions = append(changedConditions, condition) break } diff --git a/pkg/systemlogmonitor/types/types.go b/pkg/systemlogmonitor/types/types.go index 6b4eaae2a..b46facd48 100644 --- a/pkg/systemlogmonitor/types/types.go +++ b/pkg/systemlogmonitor/types/types.go @@ -42,12 +42,4 @@ type Rule struct { // Pattern is the regular expression to match the problem in log. // Notice that the pattern must match to the end of the line. Pattern string `json:"pattern"` - // TaintEnabled is a boolean flag to taint node on specific node problems - TaintEnabled bool `json:"taintEnabled"` - // TaintKey is a key of taint when taintEnabled is true and relevant problem occured - TaintKey string `json:"taintKey"` - // TaintValue is a value of taint when taintEnabled is true and relevant problem occured - TaintValue string `json:"taintValue"` - // TaintEffect is a effect of taint when taintEnabled is true and relevant problem occured - TaintEffect string `json:"taintEffect"` } diff --git a/pkg/types/types.go b/pkg/types/types.go index 26c280be1..bc022bf89 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -65,14 +65,8 @@ type Condition struct { Reason string `json:"reason"` // Message is a human-readable message of why node goes into this condition. Message string `json:"message"` - // TaintEnabled is a boolean flag to taint node on specific node problems - TaintEnabled bool `json:"taintEnabled"` - // TaintKey is a key of taint when taintEnabled is true and relevant problem occured - TaintKey string `json:"taintKey"` - // TaintValue is a value of taint when taintEnabled is true and relevant problem occured - TaintValue string `json:"taintValue"` - // TaintEffect is a effect of taint when taintEnabled is true and relevant problem occured - TaintEffect string `json:"taintEffect"` + // TaintConfig is the per Condition configuration that can be enabled, disabled or ignored + *TaintConfig `json:"taintConfig"` } // Event is the event used internally by node problem detector. @@ -156,3 +150,15 @@ type ExporterHandler struct { type CommandLineOptions interface { SetFlags(*pflag.FlagSet) } + +// TaintConfig is the per Condition configuration that can be enabled, disabled or ignored +type TaintConfig struct { + // Enabled specifies that tainting should occur on node problems or not + Enabled bool `json:"enabled,omitempty"` + // Key is the key field of your desired taint if you wish to taint your nodes on specific problems + Key string `json:"key,omitempty"` + // Value is the value field of your desired taint if you wish to taint your nodes on specific problems + Value string `json:"value,omitempty"` + // Effect is the effect field of your desired taint if you wish to taint your nodes on specific problems + Effect string `json:"effect,omitempty"` +}