Skip to content

Commit

Permalink
Go hooks improvements (#180)
Browse files Browse the repository at this point in the history
second experiment with Go hooks
  • Loading branch information
zuzzas authored Apr 2, 2021
1 parent b12cbf5 commit 5a3d3d4
Show file tree
Hide file tree
Showing 22 changed files with 560 additions and 892 deletions.
31 changes: 9 additions & 22 deletions examples/700-go-hook/global-hooks/global-go-hook.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,15 @@
package global_hooks

import "github.com/flant/addon-operator/sdk"
import (
"github.com/flant/addon-operator/pkg/module_manager/go_hook"
"github.com/flant/addon-operator/sdk"
)

var _ = sdk.Register(&GoHook{})
var _ = sdk.RegisterFunc(&go_hook.HookConfig{
OnStartup: &go_hook.OrderedConfig{Order: 10},
}, handler)

type GoHook struct {
sdk.CommonGoHook
}

func (h *GoHook) Metadata() sdk.HookMetadata {
return h.CommonMetadataFromRuntime()
}

func (h *GoHook) Config() *sdk.HookConfig {
return h.CommonGoHook.Config(&sdk.HookConfig{
YamlConfig: `
configVersion: v1
onStartup: 10
`,
MainHandler: h.Main,
})
}

func (h *GoHook) Main(input *sdk.BindingInput) (*sdk.BindingOutput, error) {
func handler(input *go_hook.HookInput) error {
input.LogEntry.Infof("Start Global Go hook")
return nil, nil
return nil
}
175 changes: 41 additions & 134 deletions examples/700-go-hook/modules/001-module-go-hooks/hooks/go_hooks.go
Original file line number Diff line number Diff line change
@@ -1,183 +1,90 @@
package hooks

import (
"encoding/json"
"fmt"
"time"

v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"

"github.com/flant/addon-operator/pkg/utils"
"github.com/flant/addon-operator/pkg/utils/values_store"
"github.com/flant/addon-operator/pkg/module_manager/go_hook"
"github.com/flant/addon-operator/sdk"

"github.com/flant/shell-operator/pkg/app"
"github.com/flant/shell-operator/pkg/kube"
"github.com/flant/shell-operator/pkg/kube_events_manager/types"
"github.com/flant/shell-operator/pkg/metric_storage/operation"
)

var _ = sdk.Register(&GoHook{})

type GoHook struct {
sdk.CommonGoHook
kubeClient kube.KubernetesClient
}
type podSpecFilteredObj v1.PodSpec

func (h *GoHook) Metadata() sdk.HookMetadata {
return sdk.HookMetadata{
Name: "go_hook.go",
Path: "001-module-go-hooks/hooks/go_hook.go",
Module: true,
ModuleName: "module-go-hooks",
func (ps *podSpecFilteredObj) ApplyFilter(obj *unstructured.Unstructured) (go_hook.FilterResult, error) {
pod := &v1.Pod{}
err := go_hook.ConvertUnstructured(obj, pod)
if err != nil {
return nil, err
}

podSpec := pod.Spec

return &podSpec, nil
}

func (h *GoHook) Config() *sdk.HookConfig {
return h.CommonGoHook.Config(&sdk.HookConfig{
OnStartup: &sdk.OrderedConfig{
type GoHook struct{}

func (h *GoHook) Config() *go_hook.HookConfig {
return &go_hook.HookConfig{
OnStartup: &go_hook.OrderedConfig{
Order: 10,
Handler: func(input *sdk.BindingInput) (*sdk.BindingOutput, error) {
input.LogEntry.Infof("Hello from module 'hooks-only' golang hook 'go_hooks'!\n")
return nil, nil
},
},

OnBeforeHelm: &sdk.OrderedConfig{
OnBeforeHelm: &go_hook.OrderedConfig{
Order: 10,
Handler: func(input *sdk.BindingInput) (*sdk.BindingOutput, error) {
input.LogEntry.Infof("Hello from module 'hooks-only' golang hook 'go_hooks' beforeHelm!\n")
vs := values_store.NewValuesStoreFromValues(input.Values)

input.LogEntry.Infof("go_hooks beforeHelm hook got values: %s", vs.GetAsYaml())

return nil, nil
},
},

Kubernetes: []sdk.KubernetesConfig{
Kubernetes: []go_hook.KubernetesConfig{
{
Name: "pods-for-hooks-only",
ApiVersion: "v1",
Kind: "Pods",
IncludeSnapshotsFrom: []string{"pods"},
//JqFilter: ".spec",
FilterFunc: func(obj *unstructured.Unstructured) (string, error) {
var pod v1.Pod
err := runtime.DefaultUnstructuredConverter.
FromUnstructured(obj.UnstructuredContent(), &pod)
if err != nil {
return "", err
}

res, err := json.Marshal(pod.Spec)
if err != nil {
return "", err
}
fmt.Printf("got pod.spec: %s\n", string(res))
return string(res), nil
},
ExecuteHookOnEvents: []types.WatchEventType{types.WatchEventAdded, types.WatchEventModified, types.WatchEventDeleted},
ExecuteHookOnSynchronization: true,
Handler: func(input *sdk.BindingInput) (*sdk.BindingOutput, error) {
input.LogEntry.Infof("Hello from on_kube.pods2! I have %d snapshots for '%s' event\n",
len(input.BindingContext.Snapshots),
input.BindingContext.WatchEvent)

vs := values_store.NewValuesStoreFromValues(input.Values)

input.LogEntry.Infof("go_hooks kube hook got values: %s", vs.GetAsYaml())

return nil, nil
},
Name: "pods",
ApiVersion: "v1",
Kind: "Pods",
Filterable: &podSpecFilteredObj{},
ExecuteHookOnSynchronization: go_hook.Bool(true),
},
},

Schedule: []sdk.ScheduleConfig{
Schedule: []go_hook.ScheduleConfig{
{
Name: "metrics",
Crontab: "*/5 * * * * *",
Handler: h.SendMetrics,
},
},
})
}

// Go hook has no kubectl, but it can initialize its own kubernetes client!
func (h *GoHook) initKubeClient() error {
if h.kubeClient != nil {
return nil
}

h.kubeClient = kube.NewKubernetesClient()
h.kubeClient.WithContextName(app.KubeContext)
h.kubeClient.WithConfigPath(app.KubeConfig)
h.kubeClient.WithRateLimiterSettings(app.KubeClientQps, app.KubeClientBurst)
// Initialize kube client for kube events hooks.
err := h.kubeClient.Init()
if err != nil {
return err
}
return nil
}

func (h *GoHook) SendMetrics(input *sdk.BindingInput) (*sdk.BindingOutput, error) {
err := h.initKubeClient()
if err != nil {
input.LogEntry.Errorf("Fatal: initialize kube client: %s", err)
return nil, err
}

podList, err := h.kubeClient.CoreV1().Pods("").List(metav1.ListOptions{})
if err != nil {
input.LogEntry.Errorf("Fatal: cannot list pods: %s", err)
return nil, err
func (h *GoHook) Metadata() *go_hook.HookMetadata {
return &go_hook.HookMetadata{
Name: "go_hook.go",
Path: "001-module-go-hooks/hooks/go_hook.go",
Module: true,
ModuleName: "module-go-hooks",
}
}

input.LogEntry.Infof("Get %d pods:", len(podList.Items))
for i, pod := range podList.Items {
input.LogEntry.Infof("%02d. Pod/%s in ns/%s", i, pod.Name, pod.Namespace)
func (h *GoHook) Run(input *go_hook.HookInput) error {
for _, o := range input.Snapshots["pods"] {
podSpec := o.(*podSpecFilteredObj)
input.LogEntry.Infof("Got podSpec: %+v", podSpec)
}

input.LogEntry.Infof("Hello from on_kube.pods2! I have %d snapshots for '%s' event\n",
len(input.BindingContext.Snapshots),
input.BindingContext.WatchEvent)

vs := values_store.NewValuesStoreFromValues(input.Values)

input.LogEntry.Infof("go_hooks schedule hook got values: %s", vs.GetAsYaml())

out := &sdk.BindingOutput{
Metrics: []operation.MetricOperation{},
}
input.LogEntry.Infof("Hello from on_kube.pods2! I have %d snapshots\n",
len(input.Snapshots))

v := 1.0
out.Metrics = append(out.Metrics, operation.MetricOperation{
*input.Metrics = append(*input.Metrics, operation.MetricOperation{
Name: "addon_go_hooks_total",
Add: &v,
})

out.ConfigValuesPatches = &utils.ValuesPatch{
[]*utils.ValuesPatchOperation{
{
Op: "add",
Path: "/moduleGoHooks/time",
Value: fmt.Sprintf("%d", time.Now().Unix()),
},
},
}
input.ConfigValues.Set("moduleGoHooks.time", time.Now().Unix())
input.Values.Set("moduleGoHooks.timeTemp", time.Now().Unix())

out.MemoryValuesPatches = &utils.ValuesPatch{
[]*utils.ValuesPatchOperation{
{
Op: "add",
Path: "/moduleGoHooks/time_temp",
Value: fmt.Sprintf("%d", time.Now().Unix()),
},
},
}
return out, nil
return nil
}
18 changes: 10 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
module github.com/flant/addon-operator

go 1.12
go 1.15

require (
github.com/Jeffail/gabs v1.4.0
github.com/davecgh/go-spew v1.1.1
github.com/evanphx/json-patch v4.9.0+incompatible
github.com/flant/shell-operator v1.0.0-rc.2.0.20210318171436-f4a0b109c0e3 // branch: master
github.com/flant/shell-operator v1.0.1-0.20210402061915-a583609302e9 // branch: master
github.com/go-chi/chi v4.0.3+incompatible
github.com/go-openapi/spec v0.19.3
github.com/go-openapi/strfmt v0.19.3
Expand All @@ -18,18 +19,19 @@ require (
github.com/prometheus/client_golang v1.0.0
github.com/segmentio/go-camelcase v0.0.0-20160726192923-7085f1e3c734
github.com/sirupsen/logrus v1.4.2
github.com/stretchr/testify v1.4.0
github.com/tidwall/gjson v1.3.4
github.com/tidwall/sjson v1.0.4
github.com/stretchr/testify v1.6.1
github.com/tidwall/gjson v1.6.3
github.com/tidwall/match v1.0.2 // indirect
github.com/tidwall/sjson v1.1.2
golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
golang.org/x/text v0.3.5 // indirect
gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/satori/go.uuid.v1 v1.2.0
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
k8s.io/api v0.17.0
k8s.io/apimachinery v0.17.0
k8s.io/client-go v0.17.0
sigs.k8s.io/yaml v1.2.0
)

replace github.com/go-openapi/validate => github.com/flant/go-openapi-validate v0.19.4-0.20200313141509-0c0fba4d39e1 // branch: fix_in_body_0_19_7

//replace github.com/flant/shell-operator => ../shell-operator
Loading

0 comments on commit 5a3d3d4

Please sign in to comment.