-
Notifications
You must be signed in to change notification settings - Fork 26
/
gohook.go
166 lines (137 loc) · 5.09 KB
/
gohook.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package kind
import (
"context"
log "github.com/sirupsen/logrus"
"github.com/flant/addon-operator/pkg/module_manager/go_hook"
"github.com/flant/addon-operator/pkg/module_manager/go_hook/metrics"
"github.com/flant/addon-operator/pkg/utils"
sh_hook "github.com/flant/shell-operator/pkg/hook"
"github.com/flant/shell-operator/pkg/hook/binding_context"
"github.com/flant/shell-operator/pkg/hook/config"
"github.com/flant/shell-operator/pkg/hook/controller"
"github.com/flant/shell-operator/pkg/kube/object_patch"
)
type GoHook struct {
basicHook sh_hook.Hook
config *go_hook.HookConfig
reconcileFunc ReconcileFunc
}
// NewGoHook creates a new go hook
func NewGoHook(config *go_hook.HookConfig, f ReconcileFunc) *GoHook {
return &GoHook{
config: config,
reconcileFunc: f,
}
}
// BackportHookConfig passes config for shell-operator to make HookController and GetConfigDescription workable.
func (h *GoHook) BackportHookConfig(cfg *config.HookConfig) {
h.basicHook.Config = cfg
h.basicHook.RateLimiter = sh_hook.CreateRateLimiter(cfg)
}
// Run start ReconcileFunc
func (h *GoHook) Run(input *go_hook.HookInput) error {
return h.reconcileFunc(input)
}
// AddMetadata add hook metadata, name and path which are resolved by SDK registry
func (h *GoHook) AddMetadata(meta *go_hook.HookMetadata) {
h.basicHook.Name = meta.Name
h.basicHook.Path = meta.Path
}
// WithHookController sets dependency "hook controller" for shell-operator
func (h *GoHook) WithHookController(hookController controller.HookController) {
h.basicHook.HookController = hookController
}
// GetHookController returns HookController
func (h *GoHook) GetHookController() controller.HookController {
return h.basicHook.HookController
}
// GetBasicHook returns hook for shell-operator
// Deprecated: don't use it for production purposes. You don't need such a low level for working with hooks
func (h *GoHook) GetBasicHook() sh_hook.Hook {
return h.basicHook
}
// WithTmpDir injects temp directory from operator
func (h *GoHook) WithTmpDir(tmpDir string) {
h.basicHook.TmpDir = tmpDir
}
// RateLimitWait runs query rate limiter pause
func (h *GoHook) RateLimitWait(ctx context.Context) error {
return h.basicHook.RateLimitWait(ctx)
}
// GetHookConfigDescription get part of hook config for logging/debugging
func (h *GoHook) GetHookConfigDescription() string {
return h.basicHook.GetConfigDescription()
}
// Execute runs the hook and return the result of the execution
func (h *GoHook) Execute(_ string, bContext []binding_context.BindingContext, _ string, configValues, values utils.Values, logLabels map[string]string) (result *HookResult, err error) {
// Values are patched in-place, so an error can occur.
patchableValues, err := go_hook.NewPatchableValues(values)
if err != nil {
return nil, err
}
patchableConfigValues, err := go_hook.NewPatchableValues(configValues)
if err != nil {
return nil, err
}
bindingActions := new([]go_hook.BindingAction)
logEntry := log.WithFields(utils.LabelsToLogFields(logLabels)).
WithField("output", "gohook")
formattedSnapshots := make(go_hook.Snapshots, len(bContext))
for _, bc := range bContext {
for snapBindingName, snaps := range bc.Snapshots {
for _, snapshot := range snaps {
goSnapshot := snapshot.FilterResult
formattedSnapshots[snapBindingName] = append(formattedSnapshots[snapBindingName], goSnapshot)
}
}
}
metricsCollector := metrics.NewCollector(h.GetName())
patchCollector := object_patch.NewPatchCollector()
err = h.Run(&go_hook.HookInput{
Snapshots: formattedSnapshots,
Values: patchableValues,
ConfigValues: patchableConfigValues,
PatchCollector: patchCollector,
LogEntry: logEntry,
MetricsCollector: metricsCollector,
BindingActions: bindingActions,
})
if err != nil {
// on error we have to check if status collector has any status patches to apply
// return non-nil HookResult if there are status patches
if statusPatches := object_patch.GetPatchStatusOperationsOnHookError(patchCollector.Operations()); len(statusPatches) > 0 {
return &HookResult{
ObjectPatcherOperations: statusPatches,
}, err
}
return nil, err
}
result = &HookResult{
Patches: map[utils.ValuesPatchType]*utils.ValuesPatch{
utils.MemoryValuesPatch: {Operations: patchableValues.GetPatches()},
utils.ConfigMapPatch: {Operations: patchableConfigValues.GetPatches()},
},
Metrics: metricsCollector.CollectedMetrics(),
ObjectPatcherOperations: patchCollector.Operations(),
BindingActions: *bindingActions,
}
return result, nil
}
// GetConfig returns hook config, which was set by user, while defining the hook
func (h *GoHook) GetConfig() *go_hook.HookConfig {
return h.config
}
// GetName returns the hook's name
func (h *GoHook) GetName() string {
return h.basicHook.Name
}
// GetPath returns hook's path on the filesystem
func (h *GoHook) GetPath() string {
return h.basicHook.Path
}
// GetKind returns kind of the hook
func (h *GoHook) GetKind() HookKind {
return HookKindGo
}
// ReconcileFunc function which holds the main logic of the hook
type ReconcileFunc func(input *go_hook.HookInput) error