Skip to content
This repository was archived by the owner on Dec 11, 2023. It is now read-only.

Commit c47aca1

Browse files
author
odacremolbap
committed
finish kuard example
1 parent a6bb74a commit c47aca1

File tree

8 files changed

+124
-66
lines changed

8 files changed

+124
-66
lines changed

cmd/triggermesh-hook/main.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Copyright 2023 TriggerMesh Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
14
package main
25

36
import (

cmd/triggermesh-hook/start/start.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ package start
55

66
import (
77
commoncmd "github.com/triggermesh/scoby-hook-triggermesh/pkg/common/cmd"
8+
"github.com/triggermesh/scoby-hook-triggermesh/pkg/handler"
9+
"github.com/triggermesh/scoby-hook-triggermesh/pkg/handler/kuards"
10+
811
"github.com/triggermesh/scoby-hook-triggermesh/pkg/server"
912
)
1013

@@ -16,6 +19,11 @@ type Cmd struct {
1619
func (c *Cmd) Run(g *commoncmd.Globals) error {
1720
g.Logger.Debug("Creating TriggerMesh hook server")
1821

19-
s := server.New(c.Path, c.Address, g.KubeClient, g.Logger)
22+
r := handler.NewRegistry([]handler.Handler{
23+
// Kuards is a temporary playground
24+
kuards.New(),
25+
})
26+
27+
s := server.New(c.Path, c.Address, r, g.DynClient, g.Logger)
2028
return s.Start(g.Context)
2129
}

pkg/common/cmd/globals.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Copyright 2023 TriggerMesh Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
14
package cmd
25

36
import (

pkg/handlers/handler.go renamed to pkg/handler/handler.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
package handlers
1+
// Copyright 2023 TriggerMesh Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package handler
25

36
import (
47
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -24,5 +27,5 @@ type Handler interface {
2427

2528
// HandlerFinalizable exposes methods for hook handler finalize operation.
2629
type HandlerFinalizable interface {
27-
Finalize(obj metav1.Object) hookv1.HookResponse
30+
Finalize(obj metav1.Object) *hookv1.HookResponse
2831
}

pkg/handlers/kuards/kuards.go renamed to pkg/handler/kuards/kuards.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
package myhandler
1+
// Copyright 2023 TriggerMesh Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package kuards
25

36
import (
47
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -8,15 +11,15 @@ import (
811
hookv1 "github.com/triggermesh/scoby/pkg/hook/v1"
912
corev1 "k8s.io/api/core/v1"
1013

11-
"github.com/triggermesh/scoby-hook-triggermesh/pkg/handlers"
14+
"github.com/triggermesh/scoby-hook-triggermesh/pkg/handler"
1215
)
1316

1417
type KuardHandler struct {
1518
gvr schema.GroupVersionResource
1619
kind string
1720
}
1821

19-
var _ handlers.Handler = (*KuardHandler)(nil)
22+
var _ handler.Handler = (*KuardHandler)(nil)
2023

2124
func New() *KuardHandler {
2225
return &KuardHandler{
@@ -64,3 +67,13 @@ func (h *KuardHandler) Reconcile(obj metav1.Object) *hookv1.HookResponse {
6467
},
6568
}
6669
}
70+
71+
func (h *KuardHandler) Finalize(obj metav1.Object) *hookv1.HookResponse {
72+
return &hookv1.HookResponse{
73+
Status: &hookv1.HookStatus{
74+
Annotations: map[string]string{
75+
"io.triggermesh.hook/my-annotation": "deletion ok",
76+
},
77+
},
78+
}
79+
}

pkg/handler/registry.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2023 TriggerMesh Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package handler
5+
6+
import (
7+
"k8s.io/apimachinery/pkg/runtime/schema"
8+
)
9+
10+
type Registry map[schema.GroupVersionKind]Handler
11+
12+
func NewRegistry(h []Handler) Registry {
13+
r := make(map[schema.GroupVersionKind]Handler, len(h))
14+
15+
for i := range h {
16+
gvr := h[i].GroupVersionResource()
17+
r[schema.GroupVersionKind{
18+
Group: gvr.Group,
19+
Version: gvr.Version,
20+
Kind: h[i].Kind(),
21+
}] = h[i]
22+
}
23+
24+
return r
25+
}

pkg/kubernetes/client.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Copyright 2023 TriggerMesh Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
14
package kubernetes
25

36
import (

pkg/server/server.go

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,46 @@
1+
// Copyright 2023 TriggerMesh Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
14
package server
25

36
import (
47
"context"
58
"encoding/json"
69
"errors"
7-
"log"
10+
"fmt"
811
"net/http"
912
"time"
1013

1114
"go.uber.org/zap"
1215

13-
corev1 "k8s.io/api/core/v1"
1416
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17+
"k8s.io/apimachinery/pkg/runtime/schema"
1518
kdclient "k8s.io/client-go/dynamic"
16-
kclient "k8s.io/client-go/kubernetes"
1719

18-
commonv1alpha1 "github.com/triggermesh/scoby/pkg/apis/common/v1alpha1"
20+
"github.com/triggermesh/scoby-hook-triggermesh/pkg/handler"
1921
hookv1 "github.com/triggermesh/scoby/pkg/hook/v1"
2022
)
2123

2224
type Server struct {
2325
path string
2426
address string
25-
client kclient.Interface
26-
dyn kdclient.Interface
27+
reg handler.Registry
28+
29+
dyn kdclient.Interface
2730

28-
logger *zap.SugaredLogger `kong:"-"`
29-
handlers map[string]interface{}
31+
logger *zap.SugaredLogger `kong:"-"`
3032
}
3133

32-
func New(path, address string, client kclient.Interface, logger *zap.SugaredLogger) *Server {
34+
func New(path, address string, reg handler.Registry, dyn kdclient.Interface, logger *zap.SugaredLogger) *Server {
3335
return &Server{
3436
path: path,
3537
address: address,
36-
client: client,
38+
reg: reg,
39+
dyn: dyn,
3740

3841
logger: logger,
3942
}
43+
4044
}
4145

4246
func (s *Server) Start(ctx context.Context) error {
@@ -58,14 +62,14 @@ func (s *Server) Start(ctx context.Context) error {
5862
close(errCh)
5963
}()
6064

61-
pods, err := s.client.CoreV1().Pods("default").List(ctx, metav1.ListOptions{})
62-
if err != nil {
63-
return err
64-
}
65+
// pods, err := s.client.CoreV1().Pods("default").List(ctx, metav1.ListOptions{})
66+
// if err != nil {
67+
// return err
68+
// }
6569

66-
for _, p := range pods.Items {
67-
s.logger.Infow("pod", zap.String("name", p.Name))
68-
}
70+
// for _, p := range pods.Items {
71+
// s.logger.Infow("pod", zap.String("name", p.Name))
72+
// }
6973

7074
select {
7175
case err := <-errCh:
@@ -91,63 +95,59 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
9195

9296
s.logger.Debug("Received request", zap.Any("request", hreq))
9397

94-
// Is the object registered?
98+
gv, err := schema.ParseGroupVersion(hreq.Object.APIVersion)
99+
if err != nil {
100+
msg := "cannot parse APIVersion from HookRequest: " + err.Error()
101+
s.logger.Error("Error parsing HookRequest", zap.Error(errors.New(msg)))
102+
http.Error(w, msg, http.StatusBadRequest)
103+
return
104+
}
105+
106+
gvk := gv.WithKind(hreq.Object.Kind)
107+
h, ok := s.reg[gvk]
108+
if !ok {
109+
msg := fmt.Sprintf("the hook does not contain a handler for %q", gvk.String())
110+
s.logger.Error("Error serving HookRequest", zap.Error(errors.New(msg)))
111+
http.Error(w, msg, http.StatusBadRequest)
112+
return
113+
}
95114

96-
// Retrieve object
115+
obj, err := s.dyn.Resource(*h.GroupVersionResource()).
116+
Namespace(hreq.Object.Namespace).
117+
Get(r.Context(), hreq.Object.Name, metav1.GetOptions{})
118+
if err != nil {
119+
msg := "object at the HookRequest cannot be found: " + err.Error()
120+
s.logger.Error("Error processing request", zap.Error(errors.New(msg)))
97121

98-
// Call function Reconcile/Finalize
122+
// Using no content, to make clear that the API and the handler
123+
// for the registered object exists, but the object cannot be retrieved.
124+
http.Error(w, msg, http.StatusNoContent)
125+
return
126+
}
99127

128+
var hres *hookv1.HookResponse
100129
switch hreq.Operation {
101130
case hookv1.OperationReconcile:
131+
hres = h.Reconcile(obj)
102132

103-
log.Printf("received reconcile request: %v\n", *hreq)
104133
case hookv1.OperationFinalize:
105-
log.Printf("received finalize request: %v\n", *hreq)
134+
f, ok := h.(handler.HandlerFinalizable)
135+
if !ok {
136+
msg := "hook handler does not support Finalizers"
137+
s.logger.Error("Error processing request", zap.Error(errors.New(msg)))
138+
http.Error(w, msg, http.StatusBadRequest)
139+
return
140+
}
141+
hres = f.Finalize(obj)
142+
106143
default:
107144
msg := "request must be either " + string(hookv1.OperationReconcile) +
108145
" or " + string(hookv1.OperationFinalize)
109-
log.Println(msg)
146+
s.logger.Error("Error parsing request", zap.Error(errors.New(msg)))
110147
http.Error(w, msg, http.StatusBadRequest)
111148
return
112149
}
113150

114-
hres := &hookv1.HookResponse{
115-
Status: &hookv1.HookStatus{
116-
Conditions: commonv1alpha1.Conditions{
117-
{
118-
Type: "HookReportedStatus",
119-
Status: metav1.ConditionTrue,
120-
Reason: "HOOKREPORTSOK",
121-
},
122-
},
123-
Annotations: map[string]string{
124-
"io.triggermesh.hook/my-annotation": "annotation from hook",
125-
},
126-
},
127-
EnvVars: []corev1.EnvVar{
128-
{
129-
Name: "FROM_HOOK",
130-
Value: "env from hook",
131-
},
132-
},
133-
}
134-
135151
w.Header().Set("Content-Type", "application/json")
136152
json.NewEncoder(w).Encode(hres)
137153
}
138-
139-
type handlerIndex struct {
140-
apiVersion string
141-
kind string
142-
}
143-
144-
type Handler struct {
145-
}
146-
147-
func (h *Handler) Reconcile(namespace, name string) {
148-
149-
}
150-
151-
func (h *Handler) Finalize(namespace, name string) {
152-
153-
}

0 commit comments

Comments
 (0)