@@ -6,12 +6,16 @@ import (
66 "encoding/json"
77 "fmt"
88 "io"
9+ "log"
910 "net/http"
1011 "net/url"
1112 "os"
1213 "path/filepath"
14+ "strconv"
1315 "strings"
16+ "time"
1417
18+ "github.com/openfaas/faas-provider/logs"
1519 "github.com/openfaas/faas-provider/types"
1620)
1721
@@ -59,6 +63,7 @@ func (s *Client) do(req *http.Request) (*http.Response, error) {
5963 req .Body = io .NopCloser (strings .NewReader (buf .String ()))
6064 }
6165 }
66+
6267 return s .client .Do (req )
6368}
6469
@@ -843,3 +848,95 @@ func (s *Client) DeleteSecret(ctx context.Context, secretName, namespace string)
843848 }
844849 return nil
845850}
851+
852+ func generateLogRequest (functionName , namespace string , follow bool , tail int , since * time.Time ) url.Values {
853+ query := url.Values {}
854+ query .Add ("name" , functionName )
855+ if len (namespace ) > 0 {
856+ query .Add ("namespace" , namespace )
857+ }
858+
859+ if follow {
860+ query .Add ("follow" , "1" )
861+ } else {
862+ query .Add ("follow" , "0" )
863+ }
864+
865+ if since != nil {
866+ query .Add ("since" , since .Format (time .RFC3339 ))
867+ }
868+
869+ if tail != 0 {
870+ query .Add ("tail" , strconv .Itoa (tail ))
871+ }
872+
873+ return query
874+ }
875+
876+ func (s * Client ) GetLogs (ctx context.Context , functionName , namespace string , follow bool , tail int , since * time.Time ) (<- chan logs.Message , error ) {
877+
878+ var err error
879+
880+ u := s .GatewayURL
881+ u .Path = "/system/logs"
882+
883+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , u .String (), nil )
884+ if err != nil {
885+ return nil , fmt .Errorf ("cannot connect to OpenFaaS on URL: %s, error: %s" , u .String (), err )
886+ }
887+
888+ req .URL .RawQuery = generateLogRequest (functionName , namespace , follow , tail , since ).Encode ()
889+ log .Printf ("%s" , req .URL .RawQuery )
890+
891+ if s .ClientAuth != nil {
892+ if err := s .ClientAuth .Set (req ); err != nil {
893+ return nil , fmt .Errorf ("unable to set Authorization header: %w" , err )
894+ }
895+ }
896+
897+ res , err := s .do (req )
898+ if err != nil {
899+ return nil , fmt .Errorf ("cannot connect to OpenFaaS on URL: %s, error: %s" , s .GatewayURL , err )
900+
901+ }
902+
903+ logStream := make (chan logs.Message , 1000 )
904+
905+ switch res .StatusCode {
906+ case http .StatusOK :
907+ go func () {
908+ defer func () {
909+ close (logStream )
910+ }()
911+
912+ if res .Body != nil {
913+ defer res .Body .Close ()
914+ }
915+
916+ decoder := json .NewDecoder (res .Body )
917+
918+ for decoder .More () {
919+ msg := logs.Message {}
920+ err := decoder .Decode (& msg )
921+ if err != nil {
922+ log .Printf ("cannot parse log results: %s" , err .Error ())
923+ return
924+ }
925+ logStream <- msg
926+ }
927+ }()
928+
929+ case http .StatusNotFound :
930+ return nil , fmt .Errorf ("function: %s not found" , functionName )
931+
932+ case http .StatusUnauthorized :
933+ return nil , fmt .Errorf ("unauthorized action, please setup authentication for this server" )
934+
935+ default :
936+ bytesOut , err := io .ReadAll (res .Body )
937+ if err == nil {
938+ return nil , fmt .Errorf ("unexpected status code: %d, message: %q" , res .StatusCode , string (bytesOut ))
939+ }
940+ }
941+ return logStream , nil
942+ }
0 commit comments