1
1
package main
2
2
3
3
import (
4
- "bytes"
5
4
"context"
6
5
"encoding/json"
7
6
"fmt"
7
+ "github.com/google/uuid"
8
8
"github.com/keptn-contrib/prometheus-service/eventhandling"
9
9
"github.com/keptn-contrib/prometheus-service/utils"
10
10
keptn "github.com/keptn/go-utils/pkg/lib"
@@ -14,27 +14,16 @@ import (
14
14
"os"
15
15
16
16
cloudevents "github.com/cloudevents/sdk-go/v2"
17
- "github.com/google/uuid"
18
17
"github.com/kelseyhightower/envconfig"
19
18
keptncommon "github.com/keptn/go-utils/pkg/lib/keptn"
20
19
keptnv2 "github.com/keptn/go-utils/pkg/lib/v0_2_0"
21
20
)
22
21
23
- type ceTest struct {
24
- Specversion string `json:"specversion" yaml:"specversion"`
25
- }
26
-
27
22
var (
28
23
env utils.EnvConfig
29
24
)
30
25
31
26
func main () {
32
- /**
33
- Note that prometheus-service requires to open multiple ports:
34
- * 8080 (default port; exposed) - acts as the ingest for prometheus alerts, and also proxies CloudEvents to port 8082
35
- * 8081 (Keptn distributor) - Port that keptn/distributor is listening too (default port for Keptn distributor)
36
- * 8082 (CloudEvents; env.Port) - Port that the CloudEvents sdk is listening to; this port is not exposed, but will be used for internal communication
37
- */
38
27
logger := keptncommon .NewLogger ("" , "" , utils .ServiceName )
39
28
40
29
env = utils.EnvConfig {}
@@ -46,12 +35,6 @@ func main() {
46
35
logger .Debug (fmt .Sprintf ("Configuration service: %s" , env .ConfigurationServiceURL ))
47
36
logger .Debug (fmt .Sprintf ("Port: %d, Path: %s" , env .Port , env .Path ))
48
37
49
- // listen on port 8080 for any HTTP request (cloudevents are also handled, but forwarded to env.Port internally)
50
- logger .Debug ("Starting server on port 8080..." )
51
- http .HandleFunc ("/" , Handler )
52
- http .HandleFunc ("/health" , HealthHandler )
53
- go http .ListenAndServe (":8080" , nil )
54
-
55
38
// start internal CloudEvents handler (on port env.Port)
56
39
os .Exit (_main (env ))
57
40
}
@@ -60,17 +43,19 @@ func _main(env utils.EnvConfig) int {
60
43
ctx := context .Background ()
61
44
ctx = cloudevents .WithEncodingStructured (ctx )
62
45
63
- p , err := cloudevents .NewHTTP (cloudevents . WithPath ( env . Path ), cloudevents . WithPort ( env . Port ) )
46
+ p , err := cloudevents .NewHTTP ()
64
47
if err != nil {
65
- log .Fatalf ("failed to create client, %v " , err )
48
+ log .Fatalf ("failed to create protocol: %s " , err . Error () )
66
49
}
67
- // Create CloudEvents client
68
- c , err := cloudevents .NewClient ( p )
50
+
51
+ ceHandler , err := cloudevents .NewHTTPReceiveHandler ( ctx , p , gotEvent )
69
52
if err != nil {
70
- log .Fatalf ("failed to create client, %v " , err )
53
+ log .Fatalf ("failed to create handler: %s " , err . Error () )
71
54
}
72
- // Start CloudEvents receiver
73
- log .Fatal (c .StartReceiver (ctx , gotEvent ))
55
+
56
+ http .HandleFunc ("/" , HTTPGetHandler )
57
+ http .Handle (env .Path , ceHandler )
58
+ http .ListenAndServe (":8080" , nil )
74
59
75
60
return 0
76
61
}
@@ -80,6 +65,8 @@ func gotEvent(event cloudevents.Event) error {
80
65
var shkeptncontext string
81
66
_ = event .Context .ExtensionAs ("shkeptncontext" , & shkeptncontext )
82
67
68
+ logger := keptncommon .NewLogger (shkeptncontext , "" , utils .ServiceName )
69
+
83
70
// convert v0.1.4 spec monitoring.configure CloudEvent into a v0.2.0 spec configure-monitoring.triggered CloudEvent
84
71
if event .Type () == keptn .ConfigureMonitoringEventType {
85
72
event .SetType (keptnv2 .GetTriggeredEventType (keptnv2 .ConfigureMonitoringTaskName ))
@@ -91,13 +78,34 @@ func gotEvent(event cloudevents.Event) error {
91
78
return fmt .Errorf ("could not create Keptn handler: %v" , err )
92
79
}
93
80
94
- logger := keptncommon .NewLogger (shkeptncontext , event .Context .GetID (), utils .ServiceName )
95
-
96
81
return eventhandling .NewEventHandler (event , logger , keptnHandler ).HandleEvent ()
97
82
}
98
83
99
- // HealthHandler provides a basic health check
100
- func HealthHandler (w http.ResponseWriter , r * http.Request ) {
84
+ // HTTPGetHandler will handle all requests for '/health' and '/ready'
85
+ func HTTPGetHandler (w http.ResponseWriter , r * http.Request ) {
86
+ switch r .URL .Path {
87
+ case "/" :
88
+ shkeptncontext := uuid .New ().String ()
89
+ logger := keptncommon .NewLogger (shkeptncontext , "" , utils .ServiceName )
90
+
91
+ body , err := ioutil .ReadAll (r .Body )
92
+ if err != nil {
93
+ logger .Error (fmt .Sprintf ("Failed to read body from requst: %s" , err ))
94
+ return
95
+ }
96
+
97
+ eventhandling .ProcessAndForwardAlertEvent (w , body , logger , shkeptncontext )
98
+ case "/health" :
99
+ healthEndpointHandler (w , r )
100
+ case "/ready" :
101
+ healthEndpointHandler (w , r )
102
+ default :
103
+ endpointNotFoundHandler (w , r )
104
+ }
105
+ }
106
+
107
+ // HealthHandler rerts a basic health check back
108
+ func healthEndpointHandler (w http.ResponseWriter , r * http.Request ) {
101
109
type StatusBody struct {
102
110
Status string `json:"status"`
103
111
}
@@ -114,51 +122,20 @@ func HealthHandler(w http.ResponseWriter, r *http.Request) {
114
122
}
115
123
}
116
124
117
- // Handler takes all http request and forwards it to the corresponding event handler (e.g., prometheus alert);
118
- // Note: cloudevents are also forwarded
119
- func Handler (rw http.ResponseWriter , req * http.Request ) {
120
- shkeptncontext := uuid .New ().String ()
121
- logger := keptncommon .NewLogger (shkeptncontext , "" , utils .ServiceName )
122
- logger .Debug (fmt .Sprintf ("%s %s" , req .Method , req .URL ))
123
- logger .Debug ("Receiving event which will be dispatched" )
124
-
125
- body , err := ioutil .ReadAll (req .Body )
126
- if err != nil {
127
- logger .Error (fmt .Sprintf ("Failed to read body from requst: %s" , err ))
128
- return
125
+ // endpointNotFoundHandler will return 404 for requests
126
+ func endpointNotFoundHandler (w http.ResponseWriter , r * http.Request ) {
127
+ type StatusBody struct {
128
+ Status string `json:"status"`
129
129
}
130
130
131
- // try to deserialize the event to check if it contains specversion
132
- event := ceTest {}
133
- if err = json .Unmarshal (body , & event ); err != nil {
134
- logger .Debug ("Failed to read body: " + err .Error () + "; content=" + string (body ))
135
- return
136
- }
131
+ status := StatusBody {Status : "NOT FOUND" }
137
132
138
- // check event whether event contains specversion to forward it to 8081; otherwise process it as prometheus alert
139
- if event .Specversion == "" {
140
- // this is a prometheus alert
141
- eventhandling .ProcessAndForwardAlertEvent (rw , body , logger , shkeptncontext )
142
- } else {
143
- // this is a CloudEvent retrieved on port 8080 that needs to be forwarded to 8082 (env.Port)
144
- forwardPath := fmt .Sprintf ("http://localhost:%d%s" , env .Port , env .Path )
145
- logger .Debug ("Forwarding cloudevent to " + forwardPath )
146
- // forward cloudevent to cloudevents lister on env.Port (see main())
147
- proxyReq , err := http .NewRequest (req .Method , forwardPath , bytes .NewReader (body ))
148
- proxyReq .Header .Set ("Content-Type" , "application/cloudevents+json" )
149
- resp , err := http .DefaultClient .Do (proxyReq )
150
- if err != nil {
151
- logger .Error ("Could not send cloud event: " + err .Error ())
152
- return
153
- }
154
- defer resp .Body .Close ()
155
-
156
- if resp .StatusCode < 200 || resp .StatusCode > 299 {
157
- logger .Error (fmt .Sprintf ("Could not process cloud event: Handler returned status %s" , resp .Status ))
158
- rw .WriteHeader (500 )
159
- } else {
160
- logger .Debug ("event successfully sent to port 8081" )
161
- rw .WriteHeader (201 )
162
- }
133
+ body , _ := json .Marshal (status )
134
+
135
+ w .Header ().Set ("content-type" , "application/json" )
136
+
137
+ _ , err := w .Write (body )
138
+ if err != nil {
139
+ log .Println (err )
163
140
}
164
141
}
0 commit comments