-
Notifications
You must be signed in to change notification settings - Fork 311
/
hooks.go
118 lines (100 loc) · 3.41 KB
/
hooks.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
Copyright 2022 The Koordinator Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package hooks
import (
"fmt"
"k8s.io/klog/v2"
"github.com/koordinator-sh/koordinator/pkg/koordlet/resourceexecutor"
"github.com/koordinator-sh/koordinator/pkg/koordlet/runtimehooks/protocol"
rmconfig "github.com/koordinator-sh/koordinator/pkg/runtimeproxy/config"
)
type Hook struct {
name string
stage rmconfig.RuntimeHookType
description string
fn HookFn
}
type Options struct {
Reader resourceexecutor.CgroupReader
Executor resourceexecutor.ResourceUpdateExecutor
}
type HookFn func(protocol.HooksProtocol) error
var globalStageHooks map[rmconfig.RuntimeHookType][]*Hook
func Register(stage rmconfig.RuntimeHookType, name, description string, hookFn HookFn) *Hook {
h, err := generateNewHook(stage, name)
if err != nil {
klog.Fatalf("hook %s register failed, reason: %v", name, err)
}
klog.V(1).Infof("hook %s is registered", name)
h.description = description
h.fn = hookFn
return h
}
func generateNewHook(stage rmconfig.RuntimeHookType, name string) (*Hook, error) {
stageHooks, stageExist := globalStageHooks[stage]
if !stageExist {
return nil, fmt.Errorf("stage %s is invalid", stage)
}
for _, hook := range stageHooks {
if hook.name == name {
return hook, fmt.Errorf("hook %s with stage %s is conflict since already registered", name, stage)
}
}
newHook := &Hook{name: name, stage: stage}
globalStageHooks[stage] = append(globalStageHooks[stage], newHook)
return newHook, nil
}
func getHooksByStage(stage rmconfig.RuntimeHookType) []*Hook {
if hooks, exist := globalStageHooks[stage]; exist {
return hooks
} else {
return []*Hook{}
}
}
func RunHooks(failPolicy rmconfig.FailurePolicyType, stage rmconfig.RuntimeHookType, protocol protocol.HooksProtocol) error {
hooks := getHooksByStage(stage)
klog.V(5).Infof("start run %v hooks at %s", len(hooks), stage)
for _, hook := range hooks {
klog.V(5).Infof("call hook %v", hook.name)
if err := hook.fn(protocol); err != nil {
klog.Errorf("failed to run hook %s in stage %s, reason: %v", hook.name, stage, err)
if failPolicy == rmconfig.PolicyFail {
return err
}
}
}
return nil
}
func init() {
globalStageHooks = map[rmconfig.RuntimeHookType][]*Hook{
rmconfig.PreRunPodSandbox: make([]*Hook, 0),
rmconfig.PreCreateContainer: make([]*Hook, 0),
rmconfig.PreStartContainer: make([]*Hook, 0),
rmconfig.PostStartContainer: make([]*Hook, 0),
rmconfig.PostStopContainer: make([]*Hook, 0),
rmconfig.PostStopPodSandbox: make([]*Hook, 0),
rmconfig.PreUpdateContainerResources: make([]*Hook, 0),
}
}
func GetStages(disable map[string]struct{}) []rmconfig.RuntimeHookType {
var stages []rmconfig.RuntimeHookType
for stage, hooks := range globalStageHooks {
if _, ok := disable[string(stage)]; ok {
continue
}
if len(hooks) > 0 {
stages = append(stages, stage)
}
}
return stages
}