1+ // Copyright 2023 TriggerMesh Inc.
2+ // SPDX-License-Identifier: Apache-2.0
3+
14package server
25
36import (
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
2224type 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
4246func (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