@@ -19,6 +19,7 @@ import (
19
19
"errors"
20
20
"fmt"
21
21
"net/http"
22
+ "strconv"
22
23
"sync"
23
24
"time"
24
25
@@ -80,6 +81,7 @@ const (
80
81
TargetResourceResync EventTarget = "resourceResync"
81
82
TargetClusterCacheInfoUpdate EventTarget = "clusterCacheInfoUpdate"
82
83
TargetRepository EventTarget = "repository"
84
+ TargetContainerLog EventTarget = "containerlog"
83
85
)
84
86
85
87
const (
@@ -406,9 +408,9 @@ func (evs EventSource) NewResourceRequestEvent(gvr v1.GroupVersionResource, name
406
408
cev .SetSource (evs .source )
407
409
cev .SetSpecVersion (cloudEventSpecVersion )
408
410
cev .SetType (method )
409
- cev .SetDataSchema (TargetResource .String ())
410
411
cev .SetExtension (resourceID , reqUUID )
411
412
cev .SetExtension (eventID , reqUUID )
413
+ cev .SetDataSchema (TargetResource .String ())
412
414
err := cev .SetData (cloudevents .ApplicationJSON , rr )
413
415
return & cev , err
414
416
}
@@ -596,6 +598,8 @@ func Target(raw *cloudevents.Event) EventTarget {
596
598
return TargetRedis
597
599
case TargetClusterCacheInfoUpdate .String ():
598
600
return TargetClusterCacheInfoUpdate
601
+ case TargetContainerLog .String ():
602
+ return TargetContainerLog
599
603
}
600
604
return ""
601
605
}
@@ -950,3 +954,113 @@ func (ewm *EventWritersMap) Remove(agentName string) {
950
954
951
955
delete (ewm .eventWriters , agentName )
952
956
}
957
+
958
+ type ContainerLogRequest struct {
959
+ // UUID for request/response correlation
960
+ UUID string `json:"uuid"`
961
+
962
+ // Pod identification
963
+ Namespace string `json:"namespace"`
964
+ PodName string `json:"podName"`
965
+
966
+ // Container specification
967
+ Container string `json:"container,omitempty"` // Optional, defaults to first container
968
+
969
+ // Log streaming parameters
970
+ Follow bool `json:"follow,omitempty"` // Stream continuously
971
+ TailLines * int64 `json:"tailLines,omitempty"` // Number of lines from end
972
+ SinceSeconds * int64 `json:"sinceSeconds,omitempty"` // Relative time
973
+ SinceTime string `json:"sinceTime,omitempty"` // Absolute timestamp (RFC3339)
974
+ Timestamps bool `json:"timestamps,omitempty"` // Include timestamps
975
+ Previous bool `json:"previous,omitempty"` // Previous container logs
976
+
977
+ // Additional parameters from K8s logs API
978
+ InsecureSkipTLSVerifyBackend bool `json:"insecureSkipTLSVerifyBackend,omitempty"` // Skip TLS verification
979
+ LimitBytes * int64 `json:"limitBytes,omitempty"` // Limit output bytes
980
+ Pretty bool `json:"pretty,omitempty"` // Pretty print output
981
+ Stream string `json:"stream,omitempty"` // "All", "Stdout", or "Stderr"
982
+ }
983
+
984
+ // NewLogRequestEvent creates a cloud event for requesting logs
985
+ func (evs EventSource ) NewLogRequestEvent (namespace , podName , method string , params map [string ]string ) (* cloudevents.Event , error ) {
986
+ reqUUID := uuid .NewString ()
987
+
988
+ // Parse log-specific parameters
989
+ logReq := & ContainerLogRequest {
990
+ UUID : reqUUID ,
991
+ Namespace : namespace ,
992
+ PodName : podName ,
993
+ }
994
+
995
+ if container , ok := params ["container" ]; ok {
996
+ logReq .Container = container
997
+ }
998
+
999
+ // Parse query parameters
1000
+ if follow := params ["follow" ]; follow == "true" {
1001
+ logReq .Follow = true
1002
+ }
1003
+
1004
+ if tailLines := params ["tailLines" ]; tailLines != "" {
1005
+ if lines , err := strconv .ParseInt (tailLines , 10 , 64 ); err == nil {
1006
+ logReq .TailLines = & lines
1007
+ }
1008
+ }
1009
+
1010
+ if sinceSeconds := params ["sinceSeconds" ]; sinceSeconds != "" {
1011
+ if seconds , err := strconv .ParseInt (sinceSeconds , 10 , 64 ); err == nil {
1012
+ logReq .SinceSeconds = & seconds
1013
+ }
1014
+ }
1015
+
1016
+ if sinceTime := params ["sinceTime" ]; sinceTime != "" {
1017
+ logReq .SinceTime = sinceTime
1018
+ }
1019
+
1020
+ if timestamps := params ["timestamps" ]; timestamps == "true" {
1021
+ logReq .Timestamps = true
1022
+ }
1023
+
1024
+ if previous := params ["previous" ]; previous == "true" {
1025
+ logReq .Previous = true
1026
+ }
1027
+
1028
+ // Parse additional K8s logs API parameters
1029
+ if insecureSkipTLS := params ["insecureSkipTLSVerifyBackend" ]; insecureSkipTLS == "true" {
1030
+ logReq .InsecureSkipTLSVerifyBackend = true
1031
+ }
1032
+
1033
+ if limitBytes := params ["limitBytes" ]; limitBytes != "" {
1034
+ if bytes , err := strconv .ParseInt (limitBytes , 10 , 64 ); err == nil {
1035
+ logReq .LimitBytes = & bytes
1036
+ }
1037
+ }
1038
+
1039
+ if pretty := params ["pretty" ]; pretty == "true" {
1040
+ logReq .Pretty = true
1041
+ }
1042
+
1043
+ if stream := params ["stream" ]; stream != "" {
1044
+ // Validate stream parameter - must be "All", "Stdout", or "Stderr"
1045
+ if stream == "All" || stream == "Stdout" || stream == "Stderr" {
1046
+ logReq .Stream = stream
1047
+ }
1048
+ }
1049
+
1050
+ cev := cloudevents .NewEvent ()
1051
+ cev .SetSource (evs .source )
1052
+ cev .SetSpecVersion (cloudEventSpecVersion )
1053
+ cev .SetType (method ) // HTTP method
1054
+ cev .SetDataSchema (TargetContainerLog .String ())
1055
+ cev .SetExtension (resourceID , reqUUID )
1056
+ cev .SetExtension (eventID , reqUUID )
1057
+ err := cev .SetData (cloudevents .ApplicationJSON , logReq )
1058
+ return & cev , err
1059
+ }
1060
+
1061
+ // ContainerLogRequest extracts ContainerLogRequest data from event
1062
+ func (ev * Event ) ContainerLogRequest () (* ContainerLogRequest , error ) {
1063
+ logReq := & ContainerLogRequest {}
1064
+ err := ev .event .DataAs (logReq )
1065
+ return logReq , err
1066
+ }
0 commit comments