TUN-3470: Replace in-house logger calls with zerolog
This commit is contained in:
parent
06404bf3e8
commit
870f5fa907
|
|
@ -12,8 +12,9 @@ import (
|
|||
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/token"
|
||||
"github.com/cloudflare/cloudflared/h2mux"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type StartOptions struct {
|
||||
|
|
@ -49,7 +50,7 @@ func (c *StdinoutStream) Write(p []byte) (int, error) {
|
|||
// Helper to allow defering the response close with a check that the resp is not nil
|
||||
func closeRespBody(resp *http.Response) {
|
||||
if resp != nil {
|
||||
resp.Body.Close()
|
||||
_ = resp.Body.Close()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +104,7 @@ func Serve(remoteConn Connection, listener net.Listener, shutdownC <-chan struct
|
|||
// serveConnection handles connections for the Serve() call
|
||||
func serveConnection(remoteConn Connection, c net.Conn, options *StartOptions) {
|
||||
defer c.Close()
|
||||
remoteConn.ServeStream(options, c)
|
||||
_ = remoteConn.ServeStream(options, c)
|
||||
}
|
||||
|
||||
// IsAccessResponse checks the http Response to see if the url location
|
||||
|
|
@ -125,13 +126,13 @@ func IsAccessResponse(resp *http.Response) bool {
|
|||
}
|
||||
|
||||
// BuildAccessRequest builds an HTTP request with the Access token set
|
||||
func BuildAccessRequest(options *StartOptions, logger logger.Service) (*http.Request, error) {
|
||||
func BuildAccessRequest(options *StartOptions, log *zerolog.Logger) (*http.Request, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, options.OriginURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
token, err := token.FetchTokenWithRedirect(req.URL, logger)
|
||||
token, err := token.FetchTokenWithRedirect(req.URL, log)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ import (
|
|||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
ws "github.com/gorilla/websocket"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -43,8 +43,8 @@ func (s *testStreamer) Write(p []byte) (int, error) {
|
|||
|
||||
func TestStartClient(t *testing.T) {
|
||||
message := "Good morning Austin! Time for another sunny day in the great state of Texas."
|
||||
logger := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
wsConn := NewWSConnection(logger, false)
|
||||
log := zerolog.Nop()
|
||||
wsConn := NewWSConnection(&log, false)
|
||||
ts := newTestWebSocketServer()
|
||||
defer ts.Close()
|
||||
|
||||
|
|
@ -55,10 +55,10 @@ func TestStartClient(t *testing.T) {
|
|||
}
|
||||
err := StartClient(wsConn, buf, options)
|
||||
assert.NoError(t, err)
|
||||
buf.Write([]byte(message))
|
||||
_, _ = buf.Write([]byte(message))
|
||||
|
||||
readBuffer := make([]byte, len(message))
|
||||
buf.Read(readBuffer)
|
||||
_, _ = buf.Read(readBuffer)
|
||||
assert.Equal(t, message, string(readBuffer))
|
||||
}
|
||||
|
||||
|
|
@ -68,9 +68,9 @@ func TestStartServer(t *testing.T) {
|
|||
t.Fatalf("Error starting listener: %v", err)
|
||||
}
|
||||
message := "Good morning Austin! Time for another sunny day in the great state of Texas."
|
||||
logger := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
log := zerolog.Nop()
|
||||
shutdownC := make(chan struct{})
|
||||
wsConn := NewWSConnection(logger, false)
|
||||
wsConn := NewWSConnection(&log, false)
|
||||
ts := newTestWebSocketServer()
|
||||
defer ts.Close()
|
||||
options := &StartOptions{
|
||||
|
|
@ -86,10 +86,10 @@ func TestStartServer(t *testing.T) {
|
|||
}()
|
||||
|
||||
conn, err := net.Dial("tcp", listener.Addr().String())
|
||||
conn.Write([]byte(message))
|
||||
_, _ = conn.Write([]byte(message))
|
||||
|
||||
readBuffer := make([]byte, len(message))
|
||||
conn.Read(readBuffer)
|
||||
_, _ = conn.Read(readBuffer)
|
||||
assert.Equal(t, string(readBuffer), message)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,16 +8,17 @@ import (
|
|||
"net/http/httputil"
|
||||
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/token"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/socks"
|
||||
cfwebsocket "github.com/cloudflare/cloudflared/websocket"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// Websocket is used to carry data via WS binary frames over the tunnel from client to the origin
|
||||
// This implements the functions for glider proxy (sock5) and the carrier interface
|
||||
type Websocket struct {
|
||||
logger logger.Service
|
||||
log *zerolog.Logger
|
||||
isSocks bool
|
||||
}
|
||||
|
||||
|
|
@ -36,9 +37,9 @@ func (d *wsdialer) Dial(address string) (io.ReadWriteCloser, *socks.AddrSpec, er
|
|||
}
|
||||
|
||||
// NewWSConnection returns a new connection object
|
||||
func NewWSConnection(logger logger.Service, isSocks bool) Connection {
|
||||
func NewWSConnection(log *zerolog.Logger, isSocks bool) Connection {
|
||||
return &Websocket{
|
||||
logger: logger,
|
||||
log: log,
|
||||
isSocks: isSocks,
|
||||
}
|
||||
}
|
||||
|
|
@ -46,9 +47,9 @@ func NewWSConnection(logger logger.Service, isSocks bool) Connection {
|
|||
// ServeStream will create a Websocket client stream connection to the edge
|
||||
// it blocks and writes the raw data from conn over the tunnel
|
||||
func (ws *Websocket) ServeStream(options *StartOptions, conn io.ReadWriter) error {
|
||||
wsConn, err := createWebsocketStream(options, ws.logger)
|
||||
wsConn, err := createWebsocketStream(options, ws.log)
|
||||
if err != nil {
|
||||
ws.logger.Errorf("failed to connect to %s with error: %s", options.OriginURL, err)
|
||||
ws.log.Error().Msgf("failed to connect to %s with error: %s", options.OriginURL, err)
|
||||
return err
|
||||
}
|
||||
defer wsConn.Close()
|
||||
|
|
@ -58,7 +59,7 @@ func (ws *Websocket) ServeStream(options *StartOptions, conn io.ReadWriter) erro
|
|||
requestHandler := socks.NewRequestHandler(dialer)
|
||||
socksServer := socks.NewConnectionHandler(requestHandler)
|
||||
|
||||
socksServer.Serve(conn)
|
||||
_ = socksServer.Serve(conn)
|
||||
} else {
|
||||
cfwebsocket.Stream(wsConn, conn)
|
||||
}
|
||||
|
|
@ -68,13 +69,13 @@ func (ws *Websocket) ServeStream(options *StartOptions, conn io.ReadWriter) erro
|
|||
// StartServer creates a Websocket server to listen for connections.
|
||||
// This is used on the origin (tunnel) side to take data from the muxer and send it to the origin
|
||||
func (ws *Websocket) StartServer(listener net.Listener, remote string, shutdownC <-chan struct{}) error {
|
||||
return cfwebsocket.StartProxyServer(ws.logger, listener, remote, shutdownC, cfwebsocket.DefaultStreamHandler)
|
||||
return cfwebsocket.StartProxyServer(ws.log, listener, remote, shutdownC, cfwebsocket.DefaultStreamHandler)
|
||||
}
|
||||
|
||||
// createWebsocketStream will create a WebSocket connection to stream data over
|
||||
// It also handles redirects from Access and will present that flow if
|
||||
// the token is not present on the request
|
||||
func createWebsocketStream(options *StartOptions, logger logger.Service) (*cfwebsocket.Conn, error) {
|
||||
func createWebsocketStream(options *StartOptions, log *zerolog.Logger) (*cfwebsocket.Conn, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, options.OriginURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -82,13 +83,13 @@ func createWebsocketStream(options *StartOptions, logger logger.Service) (*cfweb
|
|||
req.Header = options.Headers
|
||||
|
||||
dump, err := httputil.DumpRequest(req, false)
|
||||
logger.Debugf("Websocket request: %s", string(dump))
|
||||
log.Debug().Msgf("Websocket request: %s", string(dump))
|
||||
|
||||
wsConn, resp, err := cfwebsocket.ClientConnect(req, nil)
|
||||
defer closeRespBody(resp)
|
||||
|
||||
if err != nil && IsAccessResponse(resp) {
|
||||
wsConn, err = createAccessAuthenticatedStream(options, logger)
|
||||
wsConn, err = createAccessAuthenticatedStream(options, log)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -104,8 +105,8 @@ func createWebsocketStream(options *StartOptions, logger logger.Service) (*cfweb
|
|||
// this probably means the token in storage is invalid (expired/revoked). If that
|
||||
// happens it deletes the token and runs the connection again, so the user can
|
||||
// login again and generate a new one.
|
||||
func createAccessAuthenticatedStream(options *StartOptions, logger logger.Service) (*websocket.Conn, error) {
|
||||
wsConn, resp, err := createAccessWebSocketStream(options, logger)
|
||||
func createAccessAuthenticatedStream(options *StartOptions, log *zerolog.Logger) (*websocket.Conn, error) {
|
||||
wsConn, resp, err := createAccessWebSocketStream(options, log)
|
||||
defer closeRespBody(resp)
|
||||
if err == nil {
|
||||
return wsConn, nil
|
||||
|
|
@ -123,7 +124,7 @@ func createAccessAuthenticatedStream(options *StartOptions, logger logger.Servic
|
|||
if err := token.RemoveTokenIfExists(originReq.URL); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wsConn, resp, err = createAccessWebSocketStream(options, logger)
|
||||
wsConn, resp, err = createAccessWebSocketStream(options, log)
|
||||
defer closeRespBody(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -133,23 +134,23 @@ func createAccessAuthenticatedStream(options *StartOptions, logger logger.Servic
|
|||
}
|
||||
|
||||
// createAccessWebSocketStream builds an Access request and makes a connection
|
||||
func createAccessWebSocketStream(options *StartOptions, logger logger.Service) (*websocket.Conn, *http.Response, error) {
|
||||
req, err := BuildAccessRequest(options, logger)
|
||||
func createAccessWebSocketStream(options *StartOptions, log *zerolog.Logger) (*websocket.Conn, *http.Response, error) {
|
||||
req, err := BuildAccessRequest(options, log)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
dump, err := httputil.DumpRequest(req, false)
|
||||
logger.Debugf("Access Websocket request: %s", string(dump))
|
||||
log.Debug().Msgf("Access Websocket request: %s", string(dump))
|
||||
|
||||
conn, resp, err := cfwebsocket.ClientConnect(req, nil)
|
||||
|
||||
if resp != nil {
|
||||
r, err := httputil.DumpResponse(resp, true)
|
||||
if r != nil {
|
||||
logger.Debugf("Websocket response: %q", r)
|
||||
log.Debug().Msgf("Websocket response: %q", r)
|
||||
} else if err != nil {
|
||||
logger.Debugf("Websocket response error: %v", err)
|
||||
log.Debug().Msgf("Websocket response error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,17 +5,18 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/cloudflare/cloudflared/carrier"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/h2mux"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/validation"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// StartForwarder starts a client side websocket forward
|
||||
func StartForwarder(forwarder config.Forwarder, shutdown <-chan struct{}, logger logger.Service) error {
|
||||
func StartForwarder(forwarder config.Forwarder, shutdown <-chan struct{}, log *zerolog.Logger) error {
|
||||
validURL, err := validation.ValidateUrl(forwarder.Listener)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error validating origin URL")
|
||||
|
|
@ -41,9 +42,9 @@ func StartForwarder(forwarder config.Forwarder, shutdown <-chan struct{}, logger
|
|||
}
|
||||
|
||||
// we could add a cmd line variable for this bool if we want the SOCK5 server to be on the client side
|
||||
wsConn := carrier.NewWSConnection(logger, false)
|
||||
wsConn := carrier.NewWSConnection(log, false)
|
||||
|
||||
logger.Infof("Start Websocket listener on: %s", validURL.Host)
|
||||
log.Info().Msgf("Start Websocket listener on: %s", validURL.Host)
|
||||
return carrier.StartForwarder(wsConn, validURL.Host, shutdown, options)
|
||||
}
|
||||
|
||||
|
|
@ -52,10 +53,7 @@ func StartForwarder(forwarder config.Forwarder, shutdown <-chan struct{}, logger
|
|||
// useful for proxying other protocols (like ssh) over websockets
|
||||
// (which you can put Access in front of)
|
||||
func ssh(c *cli.Context) error {
|
||||
logger, err := logger.CreateSSHLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return cliutil.PrintLoggerSetupError("error setting up logger", err)
|
||||
}
|
||||
log := logger.CreateSSHLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
|
||||
// get the hostname from the cmdline and error out if its not provided
|
||||
rawHostName := c.String(sshHostnameFlag)
|
||||
|
|
@ -85,19 +83,19 @@ func ssh(c *cli.Context) error {
|
|||
}
|
||||
|
||||
// we could add a cmd line variable for this bool if we want the SOCK5 server to be on the client side
|
||||
wsConn := carrier.NewWSConnection(logger, false)
|
||||
wsConn := carrier.NewWSConnection(log, false)
|
||||
|
||||
if c.NArg() > 0 || c.IsSet(sshURLFlag) {
|
||||
forwarder, err := config.ValidateUrl(c, true)
|
||||
if err != nil {
|
||||
logger.Errorf("Error validating origin URL: %s", err)
|
||||
log.Error().Msgf("Error validating origin URL: %s", err)
|
||||
return errors.Wrap(err, "error validating origin URL")
|
||||
}
|
||||
|
||||
logger.Infof("Start Websocket listener on: %s", forwarder.Host)
|
||||
log.Info().Msgf("Start Websocket listener on: %s", forwarder.Host)
|
||||
err = carrier.StartForwarder(wsConn, forwarder.Host, shutdownC, options)
|
||||
if err != nil {
|
||||
logger.Errorf("Error on Websocket listener: %s", err)
|
||||
log.Error().Msgf("Error on Websocket listener: %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,11 +17,12 @@ import (
|
|||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/sshgen"
|
||||
"github.com/cloudflare/cloudflared/validation"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/net/idna"
|
||||
|
||||
"github.com/getsentry/raven-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -205,20 +206,17 @@ func login(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
logger, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
|
||||
args := c.Args()
|
||||
rawURL := ensureURLScheme(args.First())
|
||||
appURL, err := url.Parse(rawURL)
|
||||
if args.Len() < 1 || err != nil {
|
||||
logger.Errorf("Please provide the url of the Access application\n")
|
||||
log.Error().Msgf("Please provide the url of the Access application\n")
|
||||
return err
|
||||
}
|
||||
if err := verifyTokenAtEdge(appURL, c, logger); err != nil {
|
||||
logger.Errorf("Could not verify token: %s", err)
|
||||
if err := verifyTokenAtEdge(appURL, c, log); err != nil {
|
||||
log.Error().Msgf("Could not verify token: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -250,19 +248,16 @@ func curl(c *cli.Context) error {
|
|||
if err := raven.SetDSN(sentryDSN); err != nil {
|
||||
return err
|
||||
}
|
||||
logger, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
|
||||
args := c.Args()
|
||||
if args.Len() < 1 {
|
||||
logger.Error("Please provide the access app and command you wish to run.")
|
||||
log.Error().Msg("Please provide the access app and command you wish to run.")
|
||||
return errors.New("incorrect args")
|
||||
}
|
||||
|
||||
cmdArgs, allowRequest := parseAllowRequest(args.Slice())
|
||||
appURL, err := getAppURL(cmdArgs, logger)
|
||||
appURL, err := getAppURL(cmdArgs, log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -270,12 +265,12 @@ func curl(c *cli.Context) error {
|
|||
tok, err := token.GetAppTokenIfExists(appURL)
|
||||
if err != nil || tok == "" {
|
||||
if allowRequest {
|
||||
logger.Info("You don't have an Access token set. Please run access token <access application> to fetch one.")
|
||||
log.Info().Msg("You don't have an Access token set. Please run access token <access application> to fetch one.")
|
||||
return shell.Run("curl", cmdArgs...)
|
||||
}
|
||||
tok, err = token.FetchToken(appURL, logger)
|
||||
tok, err = token.FetchToken(appURL, log)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to refresh token: %s", err)
|
||||
log.Error().Msgf("Failed to refresh token: %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -329,10 +324,7 @@ func sshConfig(c *cli.Context) error {
|
|||
|
||||
// sshGen generates a short lived certificate for provided hostname
|
||||
func sshGen(c *cli.Context) error {
|
||||
logger, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
|
||||
// get the hostname from the cmdline and error out if its not provided
|
||||
rawHostName := c.String(sshHostnameFlag)
|
||||
|
|
@ -349,7 +341,7 @@ func sshGen(c *cli.Context) error {
|
|||
// this fetchToken function mutates the appURL param. We should refactor that
|
||||
fetchTokenURL := &url.URL{}
|
||||
*fetchTokenURL = *originURL
|
||||
cfdToken, err := token.FetchTokenWithRedirect(fetchTokenURL, logger)
|
||||
cfdToken, err := token.FetchTokenWithRedirect(fetchTokenURL, log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -362,15 +354,15 @@ func sshGen(c *cli.Context) error {
|
|||
}
|
||||
|
||||
// getAppURL will pull the appURL needed for fetching a user's Access token
|
||||
func getAppURL(cmdArgs []string, logger logger.Service) (*url.URL, error) {
|
||||
func getAppURL(cmdArgs []string, log *zerolog.Logger) (*url.URL, error) {
|
||||
if len(cmdArgs) < 1 {
|
||||
logger.Error("Please provide a valid URL as the first argument to curl.")
|
||||
log.Error().Msg("Please provide a valid URL as the first argument to curl.")
|
||||
return nil, errors.New("not a valid url")
|
||||
}
|
||||
|
||||
u, err := processURL(cmdArgs[0])
|
||||
if err != nil {
|
||||
logger.Error("Please provide a valid URL as the first argument to curl.")
|
||||
log.Error().Msg("Please provide a valid URL as the first argument to curl.")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
@ -436,7 +428,7 @@ func isFileThere(candidate string) bool {
|
|||
// verifyTokenAtEdge checks for a token on disk, or generates a new one.
|
||||
// Then makes a request to to the origin with the token to ensure it is valid.
|
||||
// Returns nil if token is valid.
|
||||
func verifyTokenAtEdge(appUrl *url.URL, c *cli.Context, logger logger.Service) error {
|
||||
func verifyTokenAtEdge(appUrl *url.URL, c *cli.Context, log *zerolog.Logger) error {
|
||||
headers := buildRequestHeaders(c.StringSlice(sshHeaderFlag))
|
||||
if c.IsSet(sshTokenIDFlag) {
|
||||
headers.Add(h2mux.CFAccessClientIDHeader, c.String(sshTokenIDFlag))
|
||||
|
|
@ -446,7 +438,7 @@ func verifyTokenAtEdge(appUrl *url.URL, c *cli.Context, logger logger.Service) e
|
|||
}
|
||||
options := &carrier.StartOptions{OriginURL: appUrl.String(), Headers: headers}
|
||||
|
||||
if valid, err := isTokenValid(options, logger); err != nil {
|
||||
if valid, err := isTokenValid(options, log); err != nil {
|
||||
return err
|
||||
} else if valid {
|
||||
return nil
|
||||
|
|
@ -456,7 +448,7 @@ func verifyTokenAtEdge(appUrl *url.URL, c *cli.Context, logger logger.Service) e
|
|||
return err
|
||||
}
|
||||
|
||||
if valid, err := isTokenValid(options, logger); err != nil {
|
||||
if valid, err := isTokenValid(options, log); err != nil {
|
||||
return err
|
||||
} else if !valid {
|
||||
return errors.New("failed to verify token")
|
||||
|
|
@ -466,8 +458,8 @@ func verifyTokenAtEdge(appUrl *url.URL, c *cli.Context, logger logger.Service) e
|
|||
}
|
||||
|
||||
// isTokenValid makes a request to the origin and returns true if the response was not a 302.
|
||||
func isTokenValid(options *carrier.StartOptions, logger logger.Service) (bool, error) {
|
||||
req, err := carrier.BuildAccessRequest(options, logger)
|
||||
func isTokenValid(options *carrier.StartOptions, log *zerolog.Logger) (bool, error) {
|
||||
req, err := carrier.BuildAccessRequest(options, log)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "Could not create access request")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ package main
|
|||
import (
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/access"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// ForwardServiceType is used to identify what kind of overwatch service this is
|
||||
|
|
@ -15,12 +16,12 @@ const ForwardServiceType = "forward"
|
|||
type ForwarderService struct {
|
||||
forwarder config.Forwarder
|
||||
shutdown chan struct{}
|
||||
logger logger.Service
|
||||
log *zerolog.Logger
|
||||
}
|
||||
|
||||
// NewForwardService creates a new forwarder service
|
||||
func NewForwardService(f config.Forwarder, logger logger.Service) *ForwarderService {
|
||||
return &ForwarderService{forwarder: f, shutdown: make(chan struct{}, 1), logger: logger}
|
||||
func NewForwardService(f config.Forwarder, log *zerolog.Logger) *ForwarderService {
|
||||
return &ForwarderService{forwarder: f, shutdown: make(chan struct{}, 1), log: log}
|
||||
}
|
||||
|
||||
// Name is used to figure out this service is related to the others (normally the addr it binds to)
|
||||
|
|
@ -46,5 +47,5 @@ func (s *ForwarderService) Shutdown() {
|
|||
|
||||
// Run is the run loop that is started by the overwatch service
|
||||
func (s *ForwarderService) Run() error {
|
||||
return access.StartForwarder(s.forwarder, s.shutdown, s.logger)
|
||||
return access.StartForwarder(s.forwarder, s.shutdown, s.log)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@ package main
|
|||
|
||||
import (
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/tunneldns"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// ResolverServiceType is used to identify what kind of overwatch service this is
|
||||
|
|
@ -15,14 +16,14 @@ const ResolverServiceType = "resolver"
|
|||
type ResolverService struct {
|
||||
resolver config.DNSResolver
|
||||
shutdown chan struct{}
|
||||
logger logger.Service
|
||||
log *zerolog.Logger
|
||||
}
|
||||
|
||||
// NewResolverService creates a new resolver service
|
||||
func NewResolverService(r config.DNSResolver, logger logger.Service) *ResolverService {
|
||||
func NewResolverService(r config.DNSResolver, log *zerolog.Logger) *ResolverService {
|
||||
return &ResolverService{resolver: r,
|
||||
shutdown: make(chan struct{}),
|
||||
logger: logger,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +52,7 @@ func (s *ResolverService) Shutdown() {
|
|||
func (s *ResolverService) Run() error {
|
||||
// create a listener
|
||||
l, err := tunneldns.CreateListener(s.resolver.AddressOrDefault(), s.resolver.PortOrDefault(),
|
||||
s.resolver.UpstreamsOrDefault(), s.resolver.BootstrapsOrDefault(), s.logger)
|
||||
s.resolver.UpstreamsOrDefault(), s.resolver.BootstrapsOrDefault(), s.log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -60,14 +61,14 @@ func (s *ResolverService) Run() error {
|
|||
readySignal := make(chan struct{})
|
||||
err = l.Start(readySignal)
|
||||
if err != nil {
|
||||
l.Stop()
|
||||
_ = l.Stop()
|
||||
return err
|
||||
}
|
||||
<-readySignal
|
||||
s.logger.Infof("start resolver on: %s:%d", s.resolver.AddressOrDefault(), s.resolver.PortOrDefault())
|
||||
s.log.Info().Msgf("start resolver on: %s:%d", s.resolver.AddressOrDefault(), s.resolver.PortOrDefault())
|
||||
|
||||
// wait for shutdown signal
|
||||
<-s.shutdown
|
||||
s.logger.Infof("shutdown on: %s:%d", s.resolver.AddressOrDefault(), s.resolver.PortOrDefault())
|
||||
s.log.Info().Msgf("shutdown on: %s:%d", s.resolver.AddressOrDefault(), s.resolver.PortOrDefault())
|
||||
return l.Stop()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@ package main
|
|||
|
||||
import (
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/overwatch"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// AppService is the main service that runs when no command lines flags are passed to cloudflared
|
||||
|
|
@ -13,17 +14,17 @@ type AppService struct {
|
|||
serviceManager overwatch.Manager
|
||||
shutdownC chan struct{}
|
||||
configUpdateChan chan config.Root
|
||||
logger logger.Service
|
||||
log *zerolog.Logger
|
||||
}
|
||||
|
||||
// NewAppService creates a new AppService with needed supporting services
|
||||
func NewAppService(configManager config.Manager, serviceManager overwatch.Manager, shutdownC chan struct{}, logger logger.Service) *AppService {
|
||||
func NewAppService(configManager config.Manager, serviceManager overwatch.Manager, shutdownC chan struct{}, log *zerolog.Logger) *AppService {
|
||||
return &AppService{
|
||||
configManager: configManager,
|
||||
serviceManager: serviceManager,
|
||||
shutdownC: shutdownC,
|
||||
configUpdateChan: make(chan config.Root),
|
||||
logger: logger,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,14 +68,14 @@ func (s *AppService) handleConfigUpdate(c config.Root) {
|
|||
// handle the client forward listeners
|
||||
activeServices := map[string]struct{}{}
|
||||
for _, f := range c.Forwarders {
|
||||
service := NewForwardService(f, s.logger)
|
||||
service := NewForwardService(f, s.log)
|
||||
s.serviceManager.Add(service)
|
||||
activeServices[service.Name()] = struct{}{}
|
||||
}
|
||||
|
||||
// handle resolver changes
|
||||
if c.Resolver.Enabled {
|
||||
service := NewResolverService(c.Resolver, s.logger)
|
||||
service := NewResolverService(c.Resolver, s.log)
|
||||
s.serviceManager.Add(service)
|
||||
activeServices[service.Name()] = struct{}{}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
package buildinfo
|
||||
|
||||
import (
|
||||
"github.com/rs/zerolog"
|
||||
"runtime"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
)
|
||||
|
||||
type BuildInfo struct {
|
||||
|
|
@ -22,7 +21,7 @@ func GetBuildInfo(cloudflaredVersion string) *BuildInfo {
|
|||
}
|
||||
}
|
||||
|
||||
func (bi *BuildInfo) Log(logger logger.Service) {
|
||||
logger.Infof("Version %s", bi.CloudflaredVersion)
|
||||
logger.Infof("GOOS: %s, GOVersion: %s, GoArch: %s", bi.GoOS, bi.GoVersion, bi.GoArch)
|
||||
func (bi *BuildInfo) Log(log *zerolog.Logger) {
|
||||
log.Info().Msgf("Version %s", bi.CloudflaredVersion)
|
||||
log.Info().Msgf("GOOS: %s, GOVersion: %s, GoArch: %s", bi.GoOS, bi.GoVersion, bi.GoArch)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,6 @@ package cliutil
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
|
@ -27,8 +23,6 @@ func UsageError(format string, args ...interface{}) error {
|
|||
// Ensures exit with error code if actionFunc returns an error
|
||||
func ErrorHandler(actionFunc cli.ActionFunc) cli.ActionFunc {
|
||||
return func(ctx *cli.Context) error {
|
||||
defer logger.SharedWriteManager.Shutdown()
|
||||
|
||||
err := actionFunc(ctx)
|
||||
if err != nil {
|
||||
if _, ok := err.(usageError); ok {
|
||||
|
|
@ -41,15 +35,3 @@ func ErrorHandler(actionFunc cli.ActionFunc) cli.ActionFunc {
|
|||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// PrintLoggerSetupError returns an error to stdout to notify when a logger can't start
|
||||
func PrintLoggerSetupError(msg string, err error) error {
|
||||
l, le := logger.New()
|
||||
if le != nil {
|
||||
log.Printf("%s: %s", msg, err)
|
||||
} else {
|
||||
l.Errorf("%s: %s", msg, err)
|
||||
}
|
||||
|
||||
return errors.Wrap(err, msg)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@ import (
|
|||
"runtime"
|
||||
"time"
|
||||
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/validation"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -95,7 +95,7 @@ func FileExists(path string) (bool, error) {
|
|||
}
|
||||
return false, err
|
||||
}
|
||||
f.Close()
|
||||
_ = f.Close()
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ func FindOrCreateConfigPath() string {
|
|||
defer file.Close()
|
||||
|
||||
logDir := DefaultLogDirectory()
|
||||
os.MkdirAll(logDir, os.ModePerm) //try and create it. Doesn't matter if it succeed or not, only byproduct will be no logs
|
||||
_ = os.MkdirAll(logDir, os.ModePerm) //try and create it. Doesn't matter if it succeed or not, only byproduct will be no logs
|
||||
|
||||
c := Root{
|
||||
LogDirectory: logDir,
|
||||
|
|
@ -345,7 +345,7 @@ func GetConfiguration() *Configuration {
|
|||
// ReadConfigFile returns InputSourceContext initialized from the configuration file.
|
||||
// On repeat calls returns with the same file, returns without reading the file again; however,
|
||||
// if value of "config" flag changes, will read the new config file
|
||||
func ReadConfigFile(c *cli.Context, log logger.Service) (*configFileSettings, error) {
|
||||
func ReadConfigFile(c *cli.Context, log *zerolog.Logger) (*configFileSettings, error) {
|
||||
configFile := c.String("config")
|
||||
if configuration.Source() == configFile || configFile == "" {
|
||||
if configuration.Source() == "" {
|
||||
|
|
@ -354,7 +354,7 @@ func ReadConfigFile(c *cli.Context, log logger.Service) (*configFileSettings, er
|
|||
return &configuration, nil
|
||||
}
|
||||
|
||||
log.Debugf("Loading configuration from %s", configFile)
|
||||
log.Debug().Msgf("Loading configuration from %s", configFile)
|
||||
file, err := os.Open(configFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
|
|
@ -365,7 +365,7 @@ func ReadConfigFile(c *cli.Context, log logger.Service) (*configFileSettings, er
|
|||
defer file.Close()
|
||||
if err := yaml.NewDecoder(file).Decode(&configuration); err != nil {
|
||||
if err == io.EOF {
|
||||
log.Errorf("Configuration file %s was empty", configFile)
|
||||
log.Error().Msgf("Configuration file %s was empty", configFile)
|
||||
return &configuration, nil
|
||||
}
|
||||
return nil, errors.Wrap(err, "error parsing YAML in config file at "+configFile)
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ import (
|
|||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/watcher"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
|
|
@ -27,16 +28,16 @@ type FileManager struct {
|
|||
watcher watcher.Notifier
|
||||
notifier Notifier
|
||||
configPath string
|
||||
logger logger.Service
|
||||
ReadConfig func(string, logger.Service) (Root, error)
|
||||
log *zerolog.Logger
|
||||
ReadConfig func(string, *zerolog.Logger) (Root, error)
|
||||
}
|
||||
|
||||
// NewFileManager creates a config manager
|
||||
func NewFileManager(watcher watcher.Notifier, configPath string, logger logger.Service) (*FileManager, error) {
|
||||
func NewFileManager(watcher watcher.Notifier, configPath string, log *zerolog.Logger) (*FileManager, error) {
|
||||
m := &FileManager{
|
||||
watcher: watcher,
|
||||
configPath: configPath,
|
||||
logger: logger,
|
||||
log: log,
|
||||
ReadConfig: readConfigFromPath,
|
||||
}
|
||||
err := watcher.Add(configPath)
|
||||
|
|
@ -60,7 +61,7 @@ func (m *FileManager) Start(notifier Notifier) error {
|
|||
|
||||
// GetConfig reads the yaml file from the disk
|
||||
func (m *FileManager) GetConfig() (Root, error) {
|
||||
return m.ReadConfig(m.configPath, m.logger)
|
||||
return m.ReadConfig(m.configPath, m.log)
|
||||
}
|
||||
|
||||
// Shutdown stops the watcher
|
||||
|
|
@ -68,7 +69,7 @@ func (m *FileManager) Shutdown() {
|
|||
m.watcher.Shutdown()
|
||||
}
|
||||
|
||||
func readConfigFromPath(configPath string, log logger.Service) (Root, error) {
|
||||
func readConfigFromPath(configPath string, log *zerolog.Logger) (Root, error) {
|
||||
if configPath == "" {
|
||||
return Root{}, errors.New("unable to find config file")
|
||||
}
|
||||
|
|
@ -82,7 +83,7 @@ func readConfigFromPath(configPath string, log logger.Service) (Root, error) {
|
|||
var config Root
|
||||
if err := yaml.NewDecoder(file).Decode(&config); err != nil {
|
||||
if err == io.EOF {
|
||||
log.Errorf("Configuration file %s was empty", configPath)
|
||||
log.Error().Msgf("Configuration file %s was empty", configPath)
|
||||
return Root{}, nil
|
||||
}
|
||||
return Root{}, errors.Wrap(err, "error parsing YAML in config file at "+configPath)
|
||||
|
|
@ -98,14 +99,14 @@ func readConfigFromPath(configPath string, log logger.Service) (Root, error) {
|
|||
func (m *FileManager) WatcherItemDidChange(filepath string) {
|
||||
config, err := m.GetConfig()
|
||||
if err != nil {
|
||||
m.logger.Errorf("Failed to read new config: %s", err)
|
||||
m.log.Error().Msgf("Failed to read new config: %s", err)
|
||||
return
|
||||
}
|
||||
m.logger.Info("Config file has been updated")
|
||||
m.log.Info().Msg("Config file has been updated")
|
||||
m.notifier.ConfigDidUpdate(config)
|
||||
}
|
||||
|
||||
// WatcherDidError notifies of errors with the file watcher
|
||||
func (m *FileManager) WatcherDidError(err error) {
|
||||
m.logger.Errorf("Config watcher encountered an error: %s", err)
|
||||
m.log.Error().Msgf("Config watcher encountered an error: %s", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/watcher"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type mockNotifier struct {
|
||||
|
|
@ -46,8 +46,8 @@ func TestConfigChanged(t *testing.T) {
|
|||
f, err := os.Create(filePath)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
f.Close()
|
||||
os.Remove(filePath)
|
||||
_ = f.Close()
|
||||
_ = os.Remove(filePath)
|
||||
}()
|
||||
c := &Root{
|
||||
Forwarders: []Forwarder{
|
||||
|
|
@ -57,15 +57,15 @@ func TestConfigChanged(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
configRead := func(configPath string, log logger.Service) (Root, error) {
|
||||
configRead := func(configPath string, log *zerolog.Logger) (Root, error) {
|
||||
return *c, nil
|
||||
}
|
||||
wait := make(chan struct{})
|
||||
w := &mockFileWatcher{path: filePath, ready: wait}
|
||||
|
||||
logger := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
log := zerolog.Nop()
|
||||
|
||||
service, err := NewFileManager(w, filePath, logger)
|
||||
service, err := NewFileManager(w, filePath, &log)
|
||||
service.ReadConfig = configRead
|
||||
assert.NoError(t, err)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
cli "github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/tunnel"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func runApp(app *cli.App, shutdownC, graceShutdownC chan struct{}) {
|
||||
|
|
@ -21,7 +21,7 @@ func runApp(app *cli.App, shutdownC, graceShutdownC chan struct{}) {
|
|||
Name: "service",
|
||||
Usage: "Manages the Argo Tunnel system service",
|
||||
Subcommands: []*cli.Command{
|
||||
&cli.Command{
|
||||
{
|
||||
Name: "install",
|
||||
Usage: "Install Argo Tunnel as a system service",
|
||||
Action: cliutil.ErrorHandler(installLinuxService),
|
||||
|
|
@ -32,7 +32,7 @@ func runApp(app *cli.App, shutdownC, graceShutdownC chan struct{}) {
|
|||
},
|
||||
},
|
||||
},
|
||||
&cli.Command{
|
||||
{
|
||||
Name: "uninstall",
|
||||
Usage: "Uninstall the Argo Tunnel service",
|
||||
Action: cliutil.ErrorHandler(uninstallLinuxService),
|
||||
|
|
@ -190,7 +190,7 @@ func isSystemd() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func copyUserConfiguration(userConfigDir, userConfigFile, userCredentialFile string, logger logger.Service) error {
|
||||
func copyUserConfiguration(userConfigDir, userConfigFile, userCredentialFile string, log *zerolog.Logger) error {
|
||||
srcCredentialPath := filepath.Join(userConfigDir, userCredentialFile)
|
||||
destCredentialPath := filepath.Join(serviceConfigDir, serviceCredentialFile)
|
||||
if srcCredentialPath != destCredentialPath {
|
||||
|
|
@ -205,17 +205,14 @@ func copyUserConfiguration(userConfigDir, userConfigFile, userCredentialFile str
|
|||
if err := copyConfig(srcConfigPath, destConfigPath); err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Infof("Copied %s to %s", srcConfigPath, destConfigPath)
|
||||
log.Info().Msgf("Copied %s to %s", srcConfigPath, destConfigPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func installLinuxService(c *cli.Context) error {
|
||||
logger, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
|
||||
etPath, err := os.Executable()
|
||||
if err != nil {
|
||||
|
|
@ -232,8 +229,8 @@ func installLinuxService(c *cli.Context) error {
|
|||
userConfigDir := filepath.Dir(c.String("config"))
|
||||
userConfigFile := filepath.Base(c.String("config"))
|
||||
userCredentialFile := config.DefaultCredentialFile
|
||||
if err = copyUserConfiguration(userConfigDir, userConfigFile, userCredentialFile, logger); err != nil {
|
||||
logger.Errorf("Failed to copy user configuration: %s. Before running the service, ensure that %s contains two files, %s and %s", err,
|
||||
if err = copyUserConfiguration(userConfigDir, userConfigFile, userCredentialFile, log); err != nil {
|
||||
log.Error().Msgf("Failed to copy user configuration: %s. Before running the service, ensure that %s contains two files, %s and %s", err,
|
||||
serviceConfigDir, serviceCredentialFile, serviceConfigFile)
|
||||
return err
|
||||
}
|
||||
|
|
@ -241,7 +238,7 @@ func installLinuxService(c *cli.Context) error {
|
|||
"--origincert", serviceConfigDir + "/" + serviceCredentialFile,
|
||||
}
|
||||
} else {
|
||||
src, err := config.ReadConfigFile(c, logger)
|
||||
src, err := config.ReadConfigFile(c, log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -274,42 +271,42 @@ credentials-file: CREDENTIALS-FILE
|
|||
|
||||
switch {
|
||||
case isSystemd():
|
||||
logger.Infof("Using Systemd")
|
||||
return installSystemd(&templateArgs, logger)
|
||||
log.Info().Msgf("Using Systemd")
|
||||
return installSystemd(&templateArgs, log)
|
||||
default:
|
||||
logger.Infof("Using SysV")
|
||||
return installSysv(&templateArgs, logger)
|
||||
log.Info().Msgf("Using SysV")
|
||||
return installSysv(&templateArgs, log)
|
||||
}
|
||||
}
|
||||
|
||||
func installSystemd(templateArgs *ServiceTemplateArgs, logger logger.Service) error {
|
||||
func installSystemd(templateArgs *ServiceTemplateArgs, log *zerolog.Logger) error {
|
||||
for _, serviceTemplate := range systemdTemplates {
|
||||
err := serviceTemplate.Generate(templateArgs)
|
||||
if err != nil {
|
||||
logger.Errorf("error generating service template: %s", err)
|
||||
log.Error().Msgf("error generating service template: %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := runCommand("systemctl", "enable", "cloudflared.service"); err != nil {
|
||||
logger.Errorf("systemctl enable cloudflared.service error: %s", err)
|
||||
log.Error().Msgf("systemctl enable cloudflared.service error: %s", err)
|
||||
return err
|
||||
}
|
||||
if err := runCommand("systemctl", "start", "cloudflared-update.timer"); err != nil {
|
||||
logger.Errorf("systemctl start cloudflared-update.timer error: %s", err)
|
||||
log.Error().Msgf("systemctl start cloudflared-update.timer error: %s", err)
|
||||
return err
|
||||
}
|
||||
logger.Infof("systemctl daemon-reload")
|
||||
log.Info().Msgf("systemctl daemon-reload")
|
||||
return runCommand("systemctl", "daemon-reload")
|
||||
}
|
||||
|
||||
func installSysv(templateArgs *ServiceTemplateArgs, logger logger.Service) error {
|
||||
func installSysv(templateArgs *ServiceTemplateArgs, log *zerolog.Logger) error {
|
||||
confPath, err := sysvTemplate.ResolvePath()
|
||||
if err != nil {
|
||||
logger.Errorf("error resolving system path: %s", err)
|
||||
log.Error().Msgf("error resolving system path: %s", err)
|
||||
return err
|
||||
}
|
||||
if err := sysvTemplate.Generate(templateArgs); err != nil {
|
||||
logger.Errorf("error generating system template: %s", err)
|
||||
log.Error().Msgf("error generating system template: %s", err)
|
||||
return err
|
||||
}
|
||||
for _, i := range [...]string{"2", "3", "4", "5"} {
|
||||
|
|
@ -326,43 +323,40 @@ func installSysv(templateArgs *ServiceTemplateArgs, logger logger.Service) error
|
|||
}
|
||||
|
||||
func uninstallLinuxService(c *cli.Context) error {
|
||||
logger, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
|
||||
switch {
|
||||
case isSystemd():
|
||||
logger.Infof("Using Systemd")
|
||||
return uninstallSystemd(logger)
|
||||
log.Info().Msgf("Using Systemd")
|
||||
return uninstallSystemd(log)
|
||||
default:
|
||||
logger.Infof("Using SysV")
|
||||
return uninstallSysv(logger)
|
||||
log.Info().Msgf("Using SysV")
|
||||
return uninstallSysv(log)
|
||||
}
|
||||
}
|
||||
|
||||
func uninstallSystemd(logger logger.Service) error {
|
||||
func uninstallSystemd(log *zerolog.Logger) error {
|
||||
if err := runCommand("systemctl", "disable", "cloudflared.service"); err != nil {
|
||||
logger.Errorf("systemctl disable cloudflared.service error: %s", err)
|
||||
log.Error().Msgf("systemctl disable cloudflared.service error: %s", err)
|
||||
return err
|
||||
}
|
||||
if err := runCommand("systemctl", "stop", "cloudflared-update.timer"); err != nil {
|
||||
logger.Errorf("systemctl stop cloudflared-update.timer error: %s", err)
|
||||
log.Error().Msgf("systemctl stop cloudflared-update.timer error: %s", err)
|
||||
return err
|
||||
}
|
||||
for _, serviceTemplate := range systemdTemplates {
|
||||
if err := serviceTemplate.Remove(); err != nil {
|
||||
logger.Errorf("error removing service template: %s", err)
|
||||
log.Error().Msgf("error removing service template: %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
logger.Infof("Successfully uninstall cloudflared service")
|
||||
log.Info().Msgf("Successfully uninstall cloudflared service")
|
||||
return nil
|
||||
}
|
||||
|
||||
func uninstallSysv(logger logger.Service) error {
|
||||
func uninstallSysv(log *zerolog.Logger) error {
|
||||
if err := sysvTemplate.Remove(); err != nil {
|
||||
logger.Errorf("error removing service template: %s", err)
|
||||
log.Error().Msgf("error removing service template: %s", err)
|
||||
return err
|
||||
}
|
||||
for _, i := range [...]string{"2", "3", "4", "5"} {
|
||||
|
|
@ -375,6 +369,6 @@ func uninstallSysv(logger logger.Service) error {
|
|||
continue
|
||||
}
|
||||
}
|
||||
logger.Infof("Successfully uninstall cloudflared service")
|
||||
log.Info().Msgf("Successfully uninstall cloudflared service")
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ func runApp(app *cli.App, shutdownC, graceShutdownC chan struct{}) {
|
|||
},
|
||||
},
|
||||
})
|
||||
app.Run(os.Args)
|
||||
_ = app.Run(os.Args)
|
||||
}
|
||||
|
||||
func newLaunchdTemplate(installPath, stdoutPath, stderrPath string) *ServiceTemplate {
|
||||
|
|
@ -107,71 +107,61 @@ func stderrPath() (string, error) {
|
|||
}
|
||||
|
||||
func installLaunchd(c *cli.Context) error {
|
||||
logger, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
|
||||
if isRootUser() {
|
||||
logger.Infof("Installing Argo Tunnel client as a system launch daemon. " +
|
||||
log.Info().Msgf("Installing Argo Tunnel client as a system launch daemon. " +
|
||||
"Argo Tunnel client will run at boot")
|
||||
} else {
|
||||
logger.Infof("Installing Argo Tunnel client as an user launch agent. " +
|
||||
log.Info().Msgf("Installing Argo Tunnel client as an user launch agent. " +
|
||||
"Note that Argo Tunnel client will only run when the user is logged in. " +
|
||||
"If you want to run Argo Tunnel client at boot, install with root permission. " +
|
||||
"For more information, visit https://developers.cloudflare.com/argo-tunnel/reference/service/")
|
||||
}
|
||||
etPath, err := os.Executable()
|
||||
if err != nil {
|
||||
logger.Errorf("Error determining executable path: %s", err)
|
||||
log.Error().Msgf("Error determining executable path: %s", err)
|
||||
return fmt.Errorf("Error determining executable path: %v", err)
|
||||
}
|
||||
installPath, err := installPath()
|
||||
if err != nil {
|
||||
logger.Errorf("Error determining install path: %s", err)
|
||||
log.Error().Msgf("Error determining install path: %s", err)
|
||||
return errors.Wrap(err, "Error determining install path")
|
||||
}
|
||||
stdoutPath, err := stdoutPath()
|
||||
if err != nil {
|
||||
logger.Errorf("error determining stdout path: %s", err)
|
||||
log.Error().Msgf("error determining stdout path: %s", err)
|
||||
return errors.Wrap(err, "error determining stdout path")
|
||||
}
|
||||
stderrPath, err := stderrPath()
|
||||
if err != nil {
|
||||
logger.Errorf("error determining stderr path: %s", err)
|
||||
log.Error().Msgf("error determining stderr path: %s", err)
|
||||
return errors.Wrap(err, "error determining stderr path")
|
||||
}
|
||||
launchdTemplate := newLaunchdTemplate(installPath, stdoutPath, stderrPath)
|
||||
if err != nil {
|
||||
logger.Errorf("error creating launchd template: %s", err)
|
||||
return errors.Wrap(err, "error creating launchd template")
|
||||
}
|
||||
templateArgs := ServiceTemplateArgs{Path: etPath}
|
||||
err = launchdTemplate.Generate(&templateArgs)
|
||||
if err != nil {
|
||||
logger.Errorf("error generating launchd template: %s", err)
|
||||
log.Error().Msgf("error generating launchd template: %s", err)
|
||||
return err
|
||||
}
|
||||
plistPath, err := launchdTemplate.ResolvePath()
|
||||
if err != nil {
|
||||
logger.Errorf("error resolving launchd template path: %s", err)
|
||||
log.Error().Msgf("error resolving launchd template path: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Infof("Outputs are logged to %s and %s", stderrPath, stdoutPath)
|
||||
log.Info().Msgf("Outputs are logged to %s and %s", stderrPath, stdoutPath)
|
||||
return runCommand("launchctl", "load", plistPath)
|
||||
}
|
||||
|
||||
func uninstallLaunchd(c *cli.Context) error {
|
||||
logger, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
|
||||
if isRootUser() {
|
||||
logger.Infof("Uninstalling Argo Tunnel as a system launch daemon")
|
||||
log.Info().Msgf("Uninstalling Argo Tunnel as a system launch daemon")
|
||||
} else {
|
||||
logger.Infof("Uninstalling Argo Tunnel as an user launch agent")
|
||||
log.Info().Msgf("Uninstalling Argo Tunnel as an user launch agent")
|
||||
}
|
||||
installPath, err := installPath()
|
||||
if err != nil {
|
||||
|
|
@ -186,20 +176,17 @@ func uninstallLaunchd(c *cli.Context) error {
|
|||
return errors.Wrap(err, "error determining stderr path")
|
||||
}
|
||||
launchdTemplate := newLaunchdTemplate(installPath, stdoutPath, stderrPath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error creating launchd template")
|
||||
}
|
||||
plistPath, err := launchdTemplate.ResolvePath()
|
||||
if err != nil {
|
||||
logger.Errorf("error resolving launchd template path: %s", err)
|
||||
log.Error().Msgf("error resolving launchd template path: %s", err)
|
||||
return err
|
||||
}
|
||||
err = runCommand("launchctl", "unload", plistPath)
|
||||
if err != nil {
|
||||
logger.Errorf("error unloading: %s", err)
|
||||
log.Error().Msgf("error unloading: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Infof("Outputs are logged to %s and %s", stderrPath, stdoutPath)
|
||||
log.Info().Msgf("Outputs are logged to %s and %s", stderrPath, stdoutPath)
|
||||
return launchdTemplate.Remove()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,16 +10,16 @@ import (
|
|||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/tunnel"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/updater"
|
||||
log "github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/metrics"
|
||||
"github.com/cloudflare/cloudflared/overwatch"
|
||||
"github.com/cloudflare/cloudflared/tunneldns"
|
||||
"github.com/cloudflare/cloudflared/watcher"
|
||||
|
||||
"github.com/getsentry/raven-go"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -184,38 +184,33 @@ func captureError(err error) {
|
|||
|
||||
// cloudflared was started without any flags
|
||||
func handleServiceMode(c *cli.Context, shutdownC chan struct{}) error {
|
||||
defer log.SharedWriteManager.Shutdown()
|
||||
|
||||
logger, err := log.CreateLoggerFromContext(c, log.DisableTerminalLog)
|
||||
if err != nil {
|
||||
return cliutil.PrintLoggerSetupError("error setting up logger", err)
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.DisableTerminalLog)
|
||||
|
||||
// start the main run loop that reads from the config file
|
||||
f, err := watcher.NewFile()
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot load config file: %s", err)
|
||||
log.Error().Msgf("Cannot load config file: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
configPath := config.FindOrCreateConfigPath()
|
||||
configManager, err := config.NewFileManager(f, configPath, logger)
|
||||
configManager, err := config.NewFileManager(f, configPath, log)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot setup config file for monitoring: %s", err)
|
||||
log.Error().Msgf("Cannot setup config file for monitoring: %s", err)
|
||||
return err
|
||||
}
|
||||
logger.Infof("monitoring config file at: %s", configPath)
|
||||
log.Info().Msgf("monitoring config file at: %s", configPath)
|
||||
|
||||
serviceCallback := func(t string, name string, err error) {
|
||||
if err != nil {
|
||||
logger.Errorf("%s service: %s encountered an error: %s", t, name, err)
|
||||
log.Error().Msgf("%s service: %s encountered an error: %s", t, name, err)
|
||||
}
|
||||
}
|
||||
serviceManager := overwatch.NewAppManager(serviceCallback)
|
||||
|
||||
appService := NewAppService(configManager, serviceManager, shutdownC, logger)
|
||||
appService := NewAppService(configManager, serviceManager, shutdownC, log)
|
||||
if err := appService.Run(); err != nil {
|
||||
logger.Errorf("Failed to start app service: %s", err)
|
||||
log.Error().Msgf("Failed to start app service: %s", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@ import (
|
|||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/path"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/transfer"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/origin"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -97,7 +98,7 @@ func newLock(path string) *lock {
|
|||
func (l *lock) Acquire() error {
|
||||
// Intercept SIGINT and SIGTERM to release lock before exiting
|
||||
l.sigHandler.register(func() {
|
||||
l.deleteLockFile()
|
||||
_ = l.deleteLockFile()
|
||||
os.Exit(0)
|
||||
})
|
||||
|
||||
|
|
@ -143,18 +144,18 @@ func isTokenLocked(lockFilePath string) bool {
|
|||
|
||||
// FetchTokenWithRedirect will either load a stored token or generate a new one
|
||||
// it appends the full url as the redirect URL to the access cli request if opening the browser
|
||||
func FetchTokenWithRedirect(appURL *url.URL, logger logger.Service) (string, error) {
|
||||
return getToken(appURL, false, logger)
|
||||
func FetchTokenWithRedirect(appURL *url.URL, log *zerolog.Logger) (string, error) {
|
||||
return getToken(appURL, false, log)
|
||||
}
|
||||
|
||||
// FetchToken will either load a stored token or generate a new one
|
||||
// it appends the host of the appURL as the redirect URL to the access cli request if opening the browser
|
||||
func FetchToken(appURL *url.URL, logger logger.Service) (string, error) {
|
||||
return getToken(appURL, true, logger)
|
||||
func FetchToken(appURL *url.URL, log *zerolog.Logger) (string, error) {
|
||||
return getToken(appURL, true, log)
|
||||
}
|
||||
|
||||
// getToken will either load a stored token or generate a new one
|
||||
func getToken(appURL *url.URL, useHostOnly bool, logger logger.Service) (string, error) {
|
||||
func getToken(appURL *url.URL, useHostOnly bool, log *zerolog.Logger) (string, error) {
|
||||
if token, err := GetAppTokenIfExists(appURL); token != "" && err == nil {
|
||||
return token, nil
|
||||
}
|
||||
|
|
@ -179,7 +180,7 @@ func getToken(appURL *url.URL, useHostOnly bool, logger logger.Service) (string,
|
|||
var orgTokenPath string
|
||||
// Get auth domain to format into org token file path
|
||||
if authDomain, err := getAuthDomain(appURL); err != nil {
|
||||
logger.Errorf("failed to get auth domain: %s", err)
|
||||
log.Error().Msgf("failed to get auth domain: %s", err)
|
||||
} else {
|
||||
orgToken, err := GetOrgTokenIfExists(authDomain)
|
||||
if err != nil {
|
||||
|
|
@ -198,7 +199,7 @@ func getToken(appURL *url.URL, useHostOnly bool, logger logger.Service) (string,
|
|||
}
|
||||
if err == nil {
|
||||
if appToken, err := exchangeOrgToken(appURL, orgToken); err != nil {
|
||||
logger.Debugf("failed to exchange org token for app token: %s", err)
|
||||
log.Debug().Msgf("failed to exchange org token for app token: %s", err)
|
||||
} else {
|
||||
if err := ioutil.WriteFile(appTokenPath, []byte(appToken), 0600); err != nil {
|
||||
return "", errors.Wrap(err, "failed to write app token to disk")
|
||||
|
|
@ -207,19 +208,19 @@ func getToken(appURL *url.URL, useHostOnly bool, logger logger.Service) (string,
|
|||
}
|
||||
}
|
||||
}
|
||||
return getTokensFromEdge(appURL, appTokenPath, orgTokenPath, useHostOnly, logger)
|
||||
return getTokensFromEdge(appURL, appTokenPath, orgTokenPath, useHostOnly, log)
|
||||
|
||||
}
|
||||
|
||||
// getTokensFromEdge will attempt to use the transfer service to retrieve an app and org token, save them to disk,
|
||||
// and return the app token.
|
||||
func getTokensFromEdge(appURL *url.URL, appTokenPath, orgTokenPath string, useHostOnly bool, logger logger.Service) (string, error) {
|
||||
func getTokensFromEdge(appURL *url.URL, appTokenPath, orgTokenPath string, useHostOnly bool, log *zerolog.Logger) (string, error) {
|
||||
// If no org token exists or if it couldnt be exchanged for an app token, then run the transfer service flow.
|
||||
|
||||
// this weird parameter is the resource name (token) and the key/value
|
||||
// we want to send to the transfer service. the key is token and the value
|
||||
// is blank (basically just the id generated in the transfer service)
|
||||
resourceData, err := transfer.Run(appURL, keyName, keyName, "", true, useHostOnly, logger)
|
||||
resourceData, err := transfer.Run(appURL, keyName, keyName, "", true, useHostOnly, log)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to run transfer service")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import (
|
|||
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/encrypter"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/shell"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -27,7 +27,7 @@ const (
|
|||
// The "dance" we refer to is building a HTTP request, opening that in a browser waiting for
|
||||
// the user to complete an action, while it long polls in the background waiting for an
|
||||
// action to be completed to download the resource.
|
||||
func Run(transferURL *url.URL, resourceName, key, value string, shouldEncrypt bool, useHostOnly bool, logger logger.Service) ([]byte, error) {
|
||||
func Run(transferURL *url.URL, resourceName, key, value string, shouldEncrypt bool, useHostOnly bool, log *zerolog.Logger) ([]byte, error) {
|
||||
encrypterClient, err := encrypter.New("cloudflared_priv.pem", "cloudflared_pub.pem")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -48,7 +48,7 @@ func Run(transferURL *url.URL, resourceName, key, value string, shouldEncrypt bo
|
|||
var resourceData []byte
|
||||
|
||||
if shouldEncrypt {
|
||||
buf, key, err := transferRequest(baseStoreURL+"transfer/"+encrypterClient.PublicKey(), logger)
|
||||
buf, key, err := transferRequest(baseStoreURL+"transfer/"+encrypterClient.PublicKey(), log)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ func Run(transferURL *url.URL, resourceName, key, value string, shouldEncrypt bo
|
|||
|
||||
resourceData = decrypted
|
||||
} else {
|
||||
buf, _, err := transferRequest(baseStoreURL+encrypterClient.PublicKey(), logger)
|
||||
buf, _, err := transferRequest(baseStoreURL+encrypterClient.PublicKey(), log)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -96,17 +96,17 @@ func buildRequestURL(baseURL *url.URL, key, value string, cli, useHostOnly bool)
|
|||
}
|
||||
|
||||
// transferRequest downloads the requested resource from the request URL
|
||||
func transferRequest(requestURL string, logger logger.Service) ([]byte, string, error) {
|
||||
func transferRequest(requestURL string, log *zerolog.Logger) ([]byte, string, error) {
|
||||
client := &http.Client{Timeout: clientTimeout}
|
||||
const pollAttempts = 10
|
||||
// we do "long polling" on the endpoint to get the resource.
|
||||
for i := 0; i < pollAttempts; i++ {
|
||||
buf, key, err := poll(client, requestURL, logger)
|
||||
buf, key, err := poll(client, requestURL, log)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
} else if len(buf) > 0 {
|
||||
if err := putSuccess(client, requestURL); err != nil {
|
||||
logger.Errorf("Failed to update resource success: %s", err)
|
||||
log.Error().Msgf("Failed to update resource success: %s", err)
|
||||
}
|
||||
return buf, key, nil
|
||||
}
|
||||
|
|
@ -115,7 +115,7 @@ func transferRequest(requestURL string, logger logger.Service) ([]byte, string,
|
|||
}
|
||||
|
||||
// poll the endpoint for the request resource, waiting for the user interaction
|
||||
func poll(client *http.Client, requestURL string, logger logger.Service) ([]byte, string, error) {
|
||||
func poll(client *http.Client, requestURL string, log *zerolog.Logger) ([]byte, string, error) {
|
||||
resp, err := client.Get(requestURL)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
|
|
@ -128,7 +128,7 @@ func poll(client *http.Client, requestURL string, logger logger.Service) ([]byte
|
|||
return nil, "", fmt.Errorf("error on request %d", resp.StatusCode)
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
logger.Info("Waiting for login...")
|
||||
log.Info().Msg("Waiting for login...")
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import (
|
|||
"github.com/google/uuid"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v2/altsrc"
|
||||
)
|
||||
|
|
@ -42,8 +43,6 @@ import (
|
|||
const (
|
||||
sentryDSN = "https://56a9c9fa5c364ab28f34b14f35ea0f1b:3e8827f6f9f740738eb11138f7bebb68@sentry.io/189878"
|
||||
|
||||
sshLogFileDirectory = "/usr/local/var/log/cloudflared/"
|
||||
|
||||
// sshPortFlag is the port on localhost the cloudflared ssh server will run on
|
||||
sshPortFlag = "local-ssh-port"
|
||||
|
||||
|
|
@ -174,14 +173,14 @@ func runAdhocNamedTunnel(sc *subcommandContext, name string) error {
|
|||
return errors.Wrap(err, "failed to create tunnel")
|
||||
}
|
||||
} else {
|
||||
sc.logger.Infof("Tunnel already created with ID %s", tunnel.ID)
|
||||
sc.log.Info().Msgf("Tunnel already created with ID %s", tunnel.ID)
|
||||
}
|
||||
|
||||
if r, ok := routeFromFlag(sc.c); ok {
|
||||
if res, err := sc.route(tunnel.ID, r); err != nil {
|
||||
sc.logger.Errorf("failed to create route, please create it manually. err: %v.", err)
|
||||
sc.log.Error().Msgf("failed to create route, please create it manually. err: %v.", err)
|
||||
} else {
|
||||
sc.logger.Infof(res.SuccessSummary())
|
||||
sc.log.Info().Msgf(res.SuccessSummary())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -194,7 +193,7 @@ func runAdhocNamedTunnel(sc *subcommandContext, name string) error {
|
|||
|
||||
// runClassicTunnel creates a "classic" non-named tunnel
|
||||
func runClassicTunnel(sc *subcommandContext) error {
|
||||
return StartServer(sc.c, version, shutdownC, graceShutdownC, nil, sc.logger, sc.isUIEnabled)
|
||||
return StartServer(sc.c, version, shutdownC, graceShutdownC, nil, sc.log, sc.isUIEnabled)
|
||||
}
|
||||
|
||||
func routeFromFlag(c *cli.Context) (tunnelstore.Route, bool) {
|
||||
|
|
@ -213,7 +212,7 @@ func StartServer(
|
|||
shutdownC,
|
||||
graceShutdownC chan struct{},
|
||||
namedTunnel *connection.NamedTunnelConfig,
|
||||
generalLogger logger.Service,
|
||||
log *zerolog.Logger,
|
||||
isUIEnabled bool,
|
||||
) error {
|
||||
_ = raven.SetDSN(sentryDSN)
|
||||
|
|
@ -224,45 +223,45 @@ func StartServer(
|
|||
dnsReadySignal := make(chan struct{})
|
||||
|
||||
if config.GetConfiguration().Source() == "" {
|
||||
generalLogger.Infof(config.ErrNoConfigFile.Error())
|
||||
log.Info().Msg(config.ErrNoConfigFile.Error())
|
||||
}
|
||||
|
||||
if c.IsSet("trace-output") {
|
||||
tmpTraceFile, err := ioutil.TempFile("", "trace")
|
||||
if err != nil {
|
||||
generalLogger.Errorf("Failed to create new temporary file to save trace output: %s", err)
|
||||
log.Error().Msgf("Failed to create new temporary file to save trace output: %s", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := tmpTraceFile.Close(); err != nil {
|
||||
generalLogger.Errorf("Failed to close trace output file %s with error: %s", tmpTraceFile.Name(), err)
|
||||
log.Error().Msgf("Failed to close trace output file %s with error: %s", tmpTraceFile.Name(), err)
|
||||
}
|
||||
if err := os.Rename(tmpTraceFile.Name(), c.String("trace-output")); err != nil {
|
||||
generalLogger.Errorf("Failed to rename temporary trace output file %s to %s with error: %s", tmpTraceFile.Name(), c.String("trace-output"), err)
|
||||
log.Error().Msgf("Failed to rename temporary trace output file %s to %s with error: %s", tmpTraceFile.Name(), c.String("trace-output"), err)
|
||||
} else {
|
||||
err := os.Remove(tmpTraceFile.Name())
|
||||
if err != nil {
|
||||
generalLogger.Errorf("Failed to remove the temporary trace file %s with error: %s", tmpTraceFile.Name(), err)
|
||||
log.Error().Msgf("Failed to remove the temporary trace file %s with error: %s", tmpTraceFile.Name(), err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if err := trace.Start(tmpTraceFile); err != nil {
|
||||
generalLogger.Errorf("Failed to start trace: %s", err)
|
||||
log.Error().Msgf("Failed to start trace: %s", err)
|
||||
return errors.Wrap(err, "Error starting tracing")
|
||||
}
|
||||
defer trace.Stop()
|
||||
}
|
||||
|
||||
buildInfo := buildinfo.GetBuildInfo(version)
|
||||
buildInfo.Log(generalLogger)
|
||||
logClientOptions(c, generalLogger)
|
||||
buildInfo.Log(log)
|
||||
logClientOptions(c, log)
|
||||
|
||||
if c.IsSet("proxy-dns") {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
errC <- runDNSProxyServer(c, dnsReadySignal, shutdownC, generalLogger)
|
||||
errC <- runDNSProxyServer(c, dnsReadySignal, shutdownC, log)
|
||||
}()
|
||||
} else {
|
||||
close(dnsReadySignal)
|
||||
|
|
@ -273,12 +272,12 @@ func StartServer(
|
|||
|
||||
go notifySystemd(connectedSignal)
|
||||
if c.IsSet("pidfile") {
|
||||
go writePidFile(connectedSignal, c.String("pidfile"), generalLogger)
|
||||
go writePidFile(connectedSignal, c.String("pidfile"), log)
|
||||
}
|
||||
|
||||
cloudflaredID, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
generalLogger.Errorf("Cannot generate cloudflared ID: %s", err)
|
||||
log.Error().Msgf("Cannot generate cloudflared ID: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -289,12 +288,12 @@ func StartServer(
|
|||
}()
|
||||
|
||||
// update needs to be after DNS proxy is up to resolve equinox server address
|
||||
if updater.IsAutoupdateEnabled(c, generalLogger) {
|
||||
generalLogger.Infof("Autoupdate frequency is set to %v", c.Duration("autoupdate-freq"))
|
||||
if updater.IsAutoupdateEnabled(c, log) {
|
||||
log.Info().Msgf("Autoupdate frequency is set to %v", c.Duration("autoupdate-freq"))
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
autoupdater := updater.NewAutoUpdater(c.Duration("autoupdate-freq"), &listeners, generalLogger)
|
||||
autoupdater := updater.NewAutoUpdater(c.Duration("autoupdate-freq"), &listeners, log)
|
||||
errC <- autoupdater.Run(ctx)
|
||||
}()
|
||||
}
|
||||
|
|
@ -303,21 +302,18 @@ func StartServer(
|
|||
if dnsProxyStandAlone(c) {
|
||||
connectedSignal.Notify()
|
||||
// no grace period, handle SIGINT/SIGTERM immediately
|
||||
return waitToShutdown(&wg, errC, shutdownC, graceShutdownC, 0, generalLogger)
|
||||
return waitToShutdown(&wg, errC, shutdownC, graceShutdownC, 0, log)
|
||||
}
|
||||
|
||||
url := c.String("url")
|
||||
hostname := c.String("hostname")
|
||||
if url == hostname && url != "" && hostname != "" {
|
||||
errText := "hostname and url shouldn't match. See --help for more information"
|
||||
generalLogger.Error(errText)
|
||||
log.Error().Msg(errText)
|
||||
return fmt.Errorf(errText)
|
||||
}
|
||||
|
||||
transportLogger, err := logger.CreateTransportLoggerFromContext(c, isUIEnabled)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error setting up transport logger")
|
||||
}
|
||||
transportLog := logger.CreateTransportLoggerFromContext(c, isUIEnabled)
|
||||
|
||||
readinessCh := make(chan connection.Event, 16)
|
||||
uiCh := make(chan connection.Event, 16)
|
||||
|
|
@ -325,30 +321,30 @@ func StartServer(
|
|||
readinessCh,
|
||||
uiCh,
|
||||
}
|
||||
tunnelConfig, ingressRules, err := prepareTunnelConfig(c, buildInfo, version, generalLogger, transportLogger, namedTunnel, isUIEnabled, eventChannels)
|
||||
tunnelConfig, ingressRules, err := prepareTunnelConfig(c, buildInfo, version, log, transportLog, namedTunnel, isUIEnabled, eventChannels)
|
||||
if err != nil {
|
||||
generalLogger.Errorf("Couldn't start tunnel: %v", err)
|
||||
log.Error().Msgf("Couldn't start tunnel: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
metricsListener, err := listeners.Listen("tcp", c.String("metrics"))
|
||||
if err != nil {
|
||||
generalLogger.Errorf("Error opening metrics server listener: %s", err)
|
||||
log.Error().Msgf("Error opening metrics server listener: %s", err)
|
||||
return errors.Wrap(err, "Error opening metrics server listener")
|
||||
}
|
||||
defer metricsListener.Close()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
errC <- metrics.ServeMetrics(metricsListener, shutdownC, readinessCh, generalLogger)
|
||||
errC <- metrics.ServeMetrics(metricsListener, shutdownC, readinessCh, log)
|
||||
}()
|
||||
|
||||
ingressRules.StartOrigins(&wg, generalLogger, shutdownC, errC)
|
||||
ingressRules.StartOrigins(&wg, log, shutdownC, errC)
|
||||
|
||||
reconnectCh := make(chan origin.ReconnectSignal, 1)
|
||||
if c.IsSet("stdin-control") {
|
||||
generalLogger.Info("Enabling control through stdin")
|
||||
go stdinControl(reconnectCh, generalLogger)
|
||||
log.Info().Msg("Enabling control through stdin")
|
||||
go stdinControl(reconnectCh, log)
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
|
|
@ -365,31 +361,15 @@ func StartServer(
|
|||
&ingressRules,
|
||||
tunnelConfig.HAConnections,
|
||||
)
|
||||
logLevels, err := logger.ParseLevelString(c.String("loglevel"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tunnelInfo.LaunchUI(ctx, generalLogger, transportLogger, logLevels, uiCh)
|
||||
tunnelInfo.LaunchUI(ctx, log, transportLog, uiCh)
|
||||
}
|
||||
|
||||
return waitToShutdown(&wg, errC, shutdownC, graceShutdownC, c.Duration("grace-period"), generalLogger)
|
||||
}
|
||||
|
||||
// forceSetFlag attempts to set the given flag value in the closest context that has it defined
|
||||
func forceSetFlag(c *cli.Context, name, value string) {
|
||||
for _, ctx := range c.Lineage() {
|
||||
if err := ctx.Set(name, value); err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return waitToShutdown(&wg, errC, shutdownC, graceShutdownC, c.Duration("grace-period"), log)
|
||||
}
|
||||
|
||||
func SetFlagsFromConfigFile(c *cli.Context) error {
|
||||
const exitCode = 1
|
||||
log, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return cliutil.PrintLoggerSetupError("error setting up logger", err)
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
inputSource, err := config.ReadConfigFile(c, log)
|
||||
if err != nil {
|
||||
if err == config.ErrNoConfigFile {
|
||||
|
|
@ -411,20 +391,20 @@ func waitToShutdown(wg *sync.WaitGroup,
|
|||
errC chan error,
|
||||
shutdownC, graceShutdownC chan struct{},
|
||||
gracePeriod time.Duration,
|
||||
logger logger.Service,
|
||||
log *zerolog.Logger,
|
||||
) error {
|
||||
var err error
|
||||
if gracePeriod > 0 {
|
||||
err = waitForSignalWithGraceShutdown(errC, shutdownC, graceShutdownC, gracePeriod, logger)
|
||||
err = waitForSignalWithGraceShutdown(errC, shutdownC, graceShutdownC, gracePeriod, log)
|
||||
} else {
|
||||
err = waitForSignal(errC, shutdownC, logger)
|
||||
err = waitForSignal(errC, shutdownC, log)
|
||||
close(graceShutdownC)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("Quitting due to error: %s", err)
|
||||
log.Error().Msgf("Quitting due to error: %s", err)
|
||||
} else {
|
||||
logger.Info("Quitting...")
|
||||
log.Info().Msg("Quitting...")
|
||||
}
|
||||
// Wait for clean exit, discarding all errors
|
||||
go func() {
|
||||
|
|
@ -440,16 +420,16 @@ func notifySystemd(waitForSignal *signal.Signal) {
|
|||
daemon.SdNotify(false, "READY=1")
|
||||
}
|
||||
|
||||
func writePidFile(waitForSignal *signal.Signal, pidFile string, logger logger.Service) {
|
||||
func writePidFile(waitForSignal *signal.Signal, pidFile string, log *zerolog.Logger) {
|
||||
<-waitForSignal.Wait()
|
||||
expandedPath, err := homedir.Expand(pidFile)
|
||||
if err != nil {
|
||||
logger.Errorf("Unable to expand %s, try to use absolute path in --pidfile: %s", pidFile, err)
|
||||
log.Error().Msgf("Unable to expand %s, try to use absolute path in --pidfile: %s", pidFile, err)
|
||||
return
|
||||
}
|
||||
file, err := os.Create(expandedPath)
|
||||
if err != nil {
|
||||
logger.Errorf("Unable to write pid to %s: %s", expandedPath, err)
|
||||
log.Error().Msgf("Unable to write pid to %s: %s", expandedPath, err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
|
@ -1018,7 +998,7 @@ func configureProxyDNSFlags(shouldHide bool) []cli.Flag {
|
|||
}
|
||||
}
|
||||
|
||||
func stdinControl(reconnectCh chan origin.ReconnectSignal, logger logger.Service) {
|
||||
func stdinControl(reconnectCh chan origin.ReconnectSignal, log *zerolog.Logger) {
|
||||
for {
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
|
|
@ -1033,17 +1013,17 @@ func stdinControl(reconnectCh chan origin.ReconnectSignal, logger logger.Service
|
|||
if len(parts) > 1 {
|
||||
var err error
|
||||
if reconnect.Delay, err = time.ParseDuration(parts[1]); err != nil {
|
||||
logger.Error(err.Error())
|
||||
log.Error().Msg(err.Error())
|
||||
continue
|
||||
}
|
||||
}
|
||||
logger.Infof("Sending reconnect signal %+v", reconnect)
|
||||
log.Info().Msgf("Sending reconnect signal %+v", reconnect)
|
||||
reconnectCh <- reconnect
|
||||
default:
|
||||
logger.Infof("Unknown command: %s", command)
|
||||
log.Info().Msgf("Unknown command: %s", command)
|
||||
fallthrough
|
||||
case "help":
|
||||
logger.Info(`Supported command:
|
||||
log.Info().Msg(`Supported command:
|
||||
reconnect [delay]
|
||||
- restarts one randomly chosen connection with optional delay before reconnect`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import (
|
|||
"github.com/cloudflare/cloudflared/edgediscovery"
|
||||
"github.com/cloudflare/cloudflared/h2mux"
|
||||
"github.com/cloudflare/cloudflared/ingress"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/origin"
|
||||
"github.com/cloudflare/cloudflared/tlsconfig"
|
||||
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
||||
|
|
@ -23,6 +22,7 @@ import (
|
|||
"github.com/google/uuid"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
|
@ -46,16 +46,16 @@ func findDefaultOriginCertPath() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func generateRandomClientID(logger logger.Service) (string, error) {
|
||||
func generateRandomClientID(log *zerolog.Logger) (string, error) {
|
||||
u, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
logger.Errorf("couldn't create UUID for client ID %s", err)
|
||||
log.Error().Msgf("couldn't create UUID for client ID %s", err)
|
||||
return "", err
|
||||
}
|
||||
return u.String(), nil
|
||||
}
|
||||
|
||||
func logClientOptions(c *cli.Context, logger logger.Service) {
|
||||
func logClientOptions(c *cli.Context, log *zerolog.Logger) {
|
||||
flags := make(map[string]interface{})
|
||||
for _, flag := range c.LocalFlagNames() {
|
||||
flags[flag] = c.Generic(flag)
|
||||
|
|
@ -69,7 +69,7 @@ func logClientOptions(c *cli.Context, logger logger.Service) {
|
|||
}
|
||||
|
||||
if len(flags) > 0 {
|
||||
logger.Infof("Environment variables %v", flags)
|
||||
log.Info().Msgf("Environment variables %v", flags)
|
||||
}
|
||||
|
||||
envs := make(map[string]string)
|
||||
|
|
@ -84,7 +84,7 @@ func logClientOptions(c *cli.Context, logger logger.Service) {
|
|||
}
|
||||
}
|
||||
if len(envs) > 0 {
|
||||
logger.Infof("Environmental variables %v", envs)
|
||||
log.Info().Msgf("Environmental variables %v", envs)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -92,32 +92,32 @@ func dnsProxyStandAlone(c *cli.Context) bool {
|
|||
return c.IsSet("proxy-dns") && (!c.IsSet("hostname") && !c.IsSet("tag") && !c.IsSet("hello-world"))
|
||||
}
|
||||
|
||||
func findOriginCert(c *cli.Context, logger logger.Service) (string, error) {
|
||||
func findOriginCert(c *cli.Context, log *zerolog.Logger) (string, error) {
|
||||
originCertPath := c.String("origincert")
|
||||
if originCertPath == "" {
|
||||
logger.Infof("Cannot determine default origin certificate path. No file %s in %v", config.DefaultCredentialFile, config.DefaultConfigSearchDirectories())
|
||||
log.Info().Msgf("Cannot determine default origin certificate path. No file %s in %v", config.DefaultCredentialFile, config.DefaultConfigSearchDirectories())
|
||||
if isRunningFromTerminal() {
|
||||
logger.Errorf("You need to specify the origin certificate path with --origincert option, or set TUNNEL_ORIGIN_CERT environment variable. See %s for more information.", argumentsUrl)
|
||||
log.Error().Msgf("You need to specify the origin certificate path with --origincert option, or set TUNNEL_ORIGIN_CERT environment variable. See %s for more information.", argumentsUrl)
|
||||
return "", fmt.Errorf("Client didn't specify origincert path when running from terminal")
|
||||
} else {
|
||||
logger.Errorf("You need to specify the origin certificate path by specifying the origincert option in the configuration file, or set TUNNEL_ORIGIN_CERT environment variable. See %s for more information.", serviceUrl)
|
||||
log.Error().Msgf("You need to specify the origin certificate path by specifying the origincert option in the configuration file, or set TUNNEL_ORIGIN_CERT environment variable. See %s for more information.", serviceUrl)
|
||||
return "", fmt.Errorf("Client didn't specify origincert path")
|
||||
}
|
||||
}
|
||||
var err error
|
||||
originCertPath, err = homedir.Expand(originCertPath)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot resolve path %s: %s", originCertPath, err)
|
||||
log.Error().Msgf("Cannot resolve path %s: %s", originCertPath, err)
|
||||
return "", fmt.Errorf("Cannot resolve path %s", originCertPath)
|
||||
}
|
||||
// Check that the user has acquired a certificate using the login command
|
||||
ok, err := config.FileExists(originCertPath)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot check if origin cert exists at path %s", originCertPath)
|
||||
log.Error().Msgf("Cannot check if origin cert exists at path %s", originCertPath)
|
||||
return "", fmt.Errorf("Cannot check if origin cert exists at path %s", originCertPath)
|
||||
}
|
||||
if !ok {
|
||||
logger.Errorf(`Cannot find a valid certificate for your origin at the path:
|
||||
log.Error().Msgf(`Cannot find a valid certificate for your origin at the path:
|
||||
|
||||
%s
|
||||
|
||||
|
|
@ -132,23 +132,23 @@ If you don't have a certificate signed by Cloudflare, run the command:
|
|||
return originCertPath, nil
|
||||
}
|
||||
|
||||
func readOriginCert(originCertPath string, logger logger.Service) ([]byte, error) {
|
||||
logger.Debugf("Reading origin cert from %s", originCertPath)
|
||||
func readOriginCert(originCertPath string, log *zerolog.Logger) ([]byte, error) {
|
||||
log.Debug().Msgf("Reading origin cert from %s", originCertPath)
|
||||
|
||||
// Easier to send the certificate as []byte via RPC than decoding it at this point
|
||||
originCert, err := ioutil.ReadFile(originCertPath)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot read %s to load origin certificate: %s", originCertPath, err)
|
||||
log.Error().Msgf("Cannot read %s to load origin certificate: %s", originCertPath, err)
|
||||
return nil, fmt.Errorf("Cannot read %s to load origin certificate", originCertPath)
|
||||
}
|
||||
return originCert, nil
|
||||
}
|
||||
|
||||
func getOriginCert(c *cli.Context, logger logger.Service) ([]byte, error) {
|
||||
if originCertPath, err := findOriginCert(c, logger); err != nil {
|
||||
func getOriginCert(c *cli.Context, log *zerolog.Logger) ([]byte, error) {
|
||||
if originCertPath, err := findOriginCert(c, log); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return readOriginCert(originCertPath, logger)
|
||||
return readOriginCert(originCertPath, log)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,8 +156,8 @@ func prepareTunnelConfig(
|
|||
c *cli.Context,
|
||||
buildInfo *buildinfo.BuildInfo,
|
||||
version string,
|
||||
logger logger.Service,
|
||||
transportLogger logger.Service,
|
||||
log *zerolog.Logger,
|
||||
transportLogger *zerolog.Logger,
|
||||
namedTunnel *connection.NamedTunnelConfig,
|
||||
isUIEnabled bool,
|
||||
eventChans []chan connection.Event,
|
||||
|
|
@ -166,13 +166,13 @@ func prepareTunnelConfig(
|
|||
|
||||
hostname, err := validation.ValidateHostname(c.String("hostname"))
|
||||
if err != nil {
|
||||
logger.Errorf("Invalid hostname: %s", err)
|
||||
log.Error().Msgf("Invalid hostname: %s", err)
|
||||
return nil, ingress.Ingress{}, errors.Wrap(err, "Invalid hostname")
|
||||
}
|
||||
isFreeTunnel := hostname == ""
|
||||
clientID := c.String("id")
|
||||
if !c.IsSet("id") {
|
||||
clientID, err = generateRandomClientID(logger)
|
||||
clientID, err = generateRandomClientID(log)
|
||||
if err != nil {
|
||||
return nil, ingress.Ingress{}, err
|
||||
}
|
||||
|
|
@ -180,7 +180,7 @@ func prepareTunnelConfig(
|
|||
|
||||
tags, err := NewTagSliceFromCLI(c.StringSlice("tag"))
|
||||
if err != nil {
|
||||
logger.Errorf("Tag parse failure: %s", err)
|
||||
log.Error().Msgf("Tag parse failure: %s", err)
|
||||
return nil, ingress.Ingress{}, errors.Wrap(err, "Tag parse failure")
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ func prepareTunnelConfig(
|
|||
|
||||
var originCert []byte
|
||||
if !isFreeTunnel {
|
||||
originCert, err = getOriginCert(c, logger)
|
||||
originCert, err = getOriginCert(c, log)
|
||||
if err != nil {
|
||||
return nil, ingress.Ingress{}, errors.Wrap(err, "Error getting origin cert")
|
||||
}
|
||||
|
|
@ -227,17 +227,17 @@ func prepareTunnelConfig(
|
|||
|
||||
// Convert single-origin configuration into multi-origin configuration.
|
||||
if ingressRules.IsEmpty() {
|
||||
ingressRules, err = ingress.NewSingleOrigin(c, !isNamedTunnel, logger)
|
||||
ingressRules, err = ingress.NewSingleOrigin(c, !isNamedTunnel)
|
||||
if err != nil {
|
||||
return nil, ingress.Ingress{}, err
|
||||
}
|
||||
}
|
||||
|
||||
protocolSelector, err := connection.NewProtocolSelector(c.String("protocol"), namedTunnel, edgediscovery.HTTP2Percentage, origin.ResolveTTL, logger)
|
||||
protocolSelector, err := connection.NewProtocolSelector(c.String("protocol"), namedTunnel, edgediscovery.HTTP2Percentage, origin.ResolveTTL, log)
|
||||
if err != nil {
|
||||
return nil, ingress.Ingress{}, err
|
||||
}
|
||||
logger.Infof("Initial protocol %s", protocolSelector.Current())
|
||||
log.Info().Msgf("Initial protocol %s", protocolSelector.Current())
|
||||
|
||||
edgeTLSConfigs := make(map[connection.Protocol]*tls.Config, len(connection.ProtocolList))
|
||||
for _, p := range connection.ProtocolList {
|
||||
|
|
@ -248,7 +248,7 @@ func prepareTunnelConfig(
|
|||
edgeTLSConfigs[p] = edgeTLSConfig
|
||||
}
|
||||
|
||||
originClient := origin.NewClient(ingressRules, tags, logger)
|
||||
originClient := origin.NewClient(ingressRules, tags, log)
|
||||
connectionConfig := &connection.Config{
|
||||
OriginClient: originClient,
|
||||
GracePeriod: c.Duration("grace-period"),
|
||||
|
|
@ -272,7 +272,7 @@ func prepareTunnelConfig(
|
|||
IsFreeTunnel: isFreeTunnel,
|
||||
LBPool: c.String("lb-pool"),
|
||||
Tags: tags,
|
||||
Logger: logger,
|
||||
Log: log,
|
||||
Observer: connection.NewObserver(transportLogger, eventChans, isUIEnabled),
|
||||
ReportedVersion: version,
|
||||
Retries: c.Uint("retries"),
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
|
@ -39,25 +40,25 @@ func (a staticPath) Path() (string, error) {
|
|||
// Implements CredFinder and looks for the credentials file in several directories
|
||||
// searching for a file named <id>.json
|
||||
type searchByID struct {
|
||||
id uuid.UUID
|
||||
c *cli.Context
|
||||
logger logger.Service
|
||||
fs fileSystem
|
||||
id uuid.UUID
|
||||
c *cli.Context
|
||||
log *zerolog.Logger
|
||||
fs fileSystem
|
||||
}
|
||||
|
||||
func newSearchByID(id uuid.UUID, c *cli.Context, logger logger.Service, fs fileSystem) CredFinder {
|
||||
func newSearchByID(id uuid.UUID, c *cli.Context, log *zerolog.Logger, fs fileSystem) CredFinder {
|
||||
return searchByID{
|
||||
id: id,
|
||||
c: c,
|
||||
logger: logger,
|
||||
fs: fs,
|
||||
id: id,
|
||||
c: c,
|
||||
log: log,
|
||||
fs: fs,
|
||||
}
|
||||
}
|
||||
|
||||
func (s searchByID) Path() (string, error) {
|
||||
|
||||
// Fallback to look for tunnel credentials in the origin cert directory
|
||||
if originCertPath, err := findOriginCert(s.c, s.logger); err == nil {
|
||||
if originCertPath, err := findOriginCert(s.c, s.log); err == nil {
|
||||
originCertDir := filepath.Dir(originCertPath)
|
||||
if filePath, err := tunnelFilePath(s.id, originCertDir); err == nil {
|
||||
if s.fs.validFilePath(filePath) {
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ import (
|
|||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/ingress"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func buildIngressSubcommand() *cli.Command {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import (
|
|||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/pkg/errors"
|
||||
cli "github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
|
|
@ -40,10 +40,7 @@ func buildLoginSubcommand(hidden bool) *cli.Command {
|
|||
}
|
||||
|
||||
func login(c *cli.Context) error {
|
||||
logger, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
|
||||
path, ok, err := checkForExistingCert()
|
||||
if ok {
|
||||
|
|
@ -59,7 +56,15 @@ func login(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
resourceData, err := transfer.Run(loginURL, "cert", "callback", callbackStoreURL, false, false, logger)
|
||||
resourceData, err := transfer.Run(
|
||||
loginURL,
|
||||
"cert",
|
||||
"callback",
|
||||
callbackStoreURL,
|
||||
false,
|
||||
false,
|
||||
log,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to write the certificate due to the following error:\n%v\n\nYour browser will download the certificate instead. You will have to manually\ncopy it to the following path:\n\n%s\n", err, path)
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
package tunnel
|
||||
|
||||
import (
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/tunneldns"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func runDNSProxyServer(c *cli.Context, dnsReadySignal, shutdownC chan struct{}, logger logger.Service) error {
|
||||
func runDNSProxyServer(c *cli.Context, dnsReadySignal, shutdownC chan struct{}, log *zerolog.Logger) error {
|
||||
port := c.Int("proxy-dns-port")
|
||||
if port <= 0 || port > 65535 {
|
||||
return errors.New("The 'proxy-dns-port' must be a valid port number in <1, 65535> range.")
|
||||
}
|
||||
listener, err := tunneldns.CreateListener(c.String("proxy-dns-address"), uint16(port), c.StringSlice("proxy-dns-upstream"), c.StringSlice("proxy-dns-bootstrap"), logger)
|
||||
listener, err := tunneldns.CreateListener(c.String("proxy-dns-address"), uint16(port), c.StringSlice("proxy-dns-upstream"), c.StringSlice("proxy-dns-bootstrap"), log)
|
||||
if err != nil {
|
||||
close(dnsReadySignal)
|
||||
listener.Stop()
|
||||
|
|
@ -26,6 +25,6 @@ func runDNSProxyServer(c *cli.Context, dnsReadySignal, shutdownC chan struct{},
|
|||
return errors.Wrap(err, "Cannot start the DNS over HTTPS proxy server")
|
||||
}
|
||||
<-shutdownC
|
||||
listener.Stop()
|
||||
_ = listener.Stop()
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,24 +6,24 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// waitForSignal notifies all routines to shutdownC immediately by closing the
|
||||
// shutdownC when one of the routines in main exits, or when this process receives
|
||||
// SIGTERM/SIGINT
|
||||
func waitForSignal(errC chan error, shutdownC chan struct{}, logger logger.Service) error {
|
||||
func waitForSignal(errC chan error, shutdownC chan struct{}, log *zerolog.Logger) error {
|
||||
signals := make(chan os.Signal, 10)
|
||||
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
|
||||
defer signal.Stop(signals)
|
||||
|
||||
select {
|
||||
case err := <-errC:
|
||||
logger.Infof("terminating due to error: %v", err)
|
||||
log.Info().Msgf("terminating due to error: %v", err)
|
||||
close(shutdownC)
|
||||
return err
|
||||
case s := <-signals:
|
||||
logger.Infof("terminating due to signal %s", s)
|
||||
log.Info().Msgf("terminating due to signal %s", s)
|
||||
close(shutdownC)
|
||||
case <-shutdownC:
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ func waitForSignal(errC chan error, shutdownC chan struct{}, logger logger.Servi
|
|||
func waitForSignalWithGraceShutdown(errC chan error,
|
||||
shutdownC, graceShutdownC chan struct{},
|
||||
gracePeriod time.Duration,
|
||||
logger logger.Service,
|
||||
logger *zerolog.Logger,
|
||||
) error {
|
||||
signals := make(chan os.Signal, 10)
|
||||
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
|
||||
|
|
@ -49,16 +49,16 @@ func waitForSignalWithGraceShutdown(errC chan error,
|
|||
|
||||
select {
|
||||
case err := <-errC:
|
||||
logger.Infof("Initiating graceful shutdown due to %v ...", err)
|
||||
logger.Info().Msgf("Initiating graceful shutdown due to %v ...", err)
|
||||
close(graceShutdownC)
|
||||
close(shutdownC)
|
||||
return err
|
||||
case s := <-signals:
|
||||
logger.Infof("Initiating graceful shutdown due to signal %s ...", s)
|
||||
logger.Info().Msgf("Initiating graceful shutdown due to signal %s ...", s)
|
||||
close(graceShutdownC)
|
||||
waitForGracePeriod(signals, errC, shutdownC, gracePeriod, logger)
|
||||
waitForGracePeriod(signals, errC, shutdownC, gracePeriod)
|
||||
case <-graceShutdownC:
|
||||
waitForGracePeriod(signals, errC, shutdownC, gracePeriod, logger)
|
||||
waitForGracePeriod(signals, errC, shutdownC, gracePeriod)
|
||||
case <-shutdownC:
|
||||
close(graceShutdownC)
|
||||
}
|
||||
|
|
@ -70,7 +70,6 @@ func waitForGracePeriod(signals chan os.Signal,
|
|||
errC chan error,
|
||||
shutdownC chan struct{},
|
||||
gracePeriod time.Duration,
|
||||
logger logger.Service,
|
||||
) {
|
||||
// Unregister signal handler early, so the client can send a second SIGTERM/SIGINT
|
||||
// to force shutdown cloudflared
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ package tunnel
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/rs/zerolog"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ func testChannelClosed(t *testing.T, c chan struct{}) {
|
|||
}
|
||||
|
||||
func TestWaitForSignal(t *testing.T) {
|
||||
logger := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
log := zerolog.Nop()
|
||||
|
||||
// Test handling server error
|
||||
errC := make(chan error)
|
||||
|
|
@ -39,7 +39,7 @@ func TestWaitForSignal(t *testing.T) {
|
|||
}()
|
||||
|
||||
// received error, shutdownC should be closed
|
||||
err := waitForSignal(errC, shutdownC, logger)
|
||||
err := waitForSignal(errC, shutdownC, &log)
|
||||
assert.Equal(t, serverErr, err)
|
||||
testChannelClosed(t, shutdownC)
|
||||
|
||||
|
|
@ -56,10 +56,10 @@ func TestWaitForSignal(t *testing.T) {
|
|||
go func(sig syscall.Signal) {
|
||||
// sleep for a tick to prevent sending signal before calling waitForSignal
|
||||
time.Sleep(tick)
|
||||
syscall.Kill(syscall.Getpid(), sig)
|
||||
_ = syscall.Kill(syscall.Getpid(), sig)
|
||||
}(sig)
|
||||
|
||||
err = waitForSignal(errC, shutdownC, logger)
|
||||
err = waitForSignal(errC, shutdownC, &log)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, shutdownErr, <-errC)
|
||||
testChannelClosed(t, shutdownC)
|
||||
|
|
@ -76,10 +76,10 @@ func TestWaitForSignalWithGraceShutdown(t *testing.T) {
|
|||
errC <- serverErr
|
||||
}()
|
||||
|
||||
logger := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
log := zerolog.Nop()
|
||||
|
||||
// received error, both shutdownC and graceshutdownC should be closed
|
||||
err := waitForSignalWithGraceShutdown(errC, shutdownC, graceshutdownC, tick, logger)
|
||||
err := waitForSignalWithGraceShutdown(errC, shutdownC, graceshutdownC, tick, &log)
|
||||
assert.Equal(t, serverErr, err)
|
||||
testChannelClosed(t, shutdownC)
|
||||
testChannelClosed(t, graceshutdownC)
|
||||
|
|
@ -89,7 +89,7 @@ func TestWaitForSignalWithGraceShutdown(t *testing.T) {
|
|||
shutdownC = make(chan struct{})
|
||||
graceshutdownC = make(chan struct{})
|
||||
close(shutdownC)
|
||||
err = waitForSignalWithGraceShutdown(errC, shutdownC, graceshutdownC, tick, logger)
|
||||
err = waitForSignalWithGraceShutdown(errC, shutdownC, graceshutdownC, tick, &log)
|
||||
assert.NoError(t, err)
|
||||
testChannelClosed(t, shutdownC)
|
||||
testChannelClosed(t, graceshutdownC)
|
||||
|
|
@ -99,7 +99,7 @@ func TestWaitForSignalWithGraceShutdown(t *testing.T) {
|
|||
shutdownC = make(chan struct{})
|
||||
graceshutdownC = make(chan struct{})
|
||||
close(graceshutdownC)
|
||||
err = waitForSignalWithGraceShutdown(errC, shutdownC, graceshutdownC, tick, logger)
|
||||
err = waitForSignalWithGraceShutdown(errC, shutdownC, graceshutdownC, tick, &log)
|
||||
assert.NoError(t, err)
|
||||
testChannelClosed(t, shutdownC)
|
||||
testChannelClosed(t, graceshutdownC)
|
||||
|
|
@ -119,10 +119,10 @@ func TestWaitForSignalWithGraceShutdown(t *testing.T) {
|
|||
go func(sig syscall.Signal) {
|
||||
// sleep for a tick to prevent sending signal before calling waitForSignalWithGraceShutdown
|
||||
time.Sleep(tick)
|
||||
syscall.Kill(syscall.Getpid(), sig)
|
||||
_ = syscall.Kill(syscall.Getpid(), sig)
|
||||
}(sig)
|
||||
|
||||
err = waitForSignalWithGraceShutdown(errC, shutdownC, graceshutdownC, tick, logger)
|
||||
err = waitForSignalWithGraceShutdown(errC, shutdownC, graceshutdownC, tick, &log)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, graceShutdownErr, <-errC)
|
||||
testChannelClosed(t, shutdownC)
|
||||
|
|
@ -145,10 +145,10 @@ func TestWaitForSignalWithGraceShutdown(t *testing.T) {
|
|||
go func(sig syscall.Signal) {
|
||||
// sleep for a tick to prevent sending signal before calling waitForSignalWithGraceShutdown
|
||||
time.Sleep(tick)
|
||||
syscall.Kill(syscall.Getpid(), sig)
|
||||
_ = syscall.Kill(syscall.Getpid(), sig)
|
||||
}(sig)
|
||||
|
||||
err = waitForSignalWithGraceShutdown(errC, shutdownC, graceshutdownC, tick, logger)
|
||||
err = waitForSignalWithGraceShutdown(errC, shutdownC, graceshutdownC, tick, &log)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, shutdownErr, <-errC)
|
||||
testChannelClosed(t, shutdownC)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/cloudflare/cloudflared/certutil"
|
||||
|
|
@ -29,7 +30,7 @@ func (e errInvalidJSONCredential) Error() string {
|
|||
// pass between subcommands, and make sure they are only initialized once
|
||||
type subcommandContext struct {
|
||||
c *cli.Context
|
||||
logger logger.Service
|
||||
log *zerolog.Logger
|
||||
isUIEnabled bool
|
||||
fs fileSystem
|
||||
|
||||
|
|
@ -42,14 +43,11 @@ func newSubcommandContext(c *cli.Context) (*subcommandContext, error) {
|
|||
isUIEnabled := c.IsSet(uiFlag) && c.String("name") != ""
|
||||
|
||||
// If UI is enabled, terminal log output should be disabled -- log should be written into a UI log window instead
|
||||
logger, err := logger.CreateLoggerFromContext(c, isUIEnabled)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, isUIEnabled)
|
||||
|
||||
return &subcommandContext{
|
||||
c: c,
|
||||
logger: logger,
|
||||
log: log,
|
||||
isUIEnabled: isUIEnabled,
|
||||
fs: realFileSystem{},
|
||||
}, nil
|
||||
|
|
@ -60,7 +58,7 @@ func (sc *subcommandContext) credentialFinder(tunnelID uuid.UUID) CredFinder {
|
|||
if path := sc.c.String(CredFileFlag); path != "" {
|
||||
return newStaticPath(path, sc.fs)
|
||||
}
|
||||
return newSearchByID(tunnelID, sc.c, sc.logger, sc.fs)
|
||||
return newSearchByID(tunnelID, sc.c, sc.log, sc.fs)
|
||||
}
|
||||
|
||||
type userCredential struct {
|
||||
|
|
@ -77,7 +75,15 @@ func (sc *subcommandContext) client() (tunnelstore.Client, error) {
|
|||
return nil, err
|
||||
}
|
||||
userAgent := fmt.Sprintf("cloudflared/%s", version)
|
||||
client, err := tunnelstore.NewRESTClient(sc.c.String("api-url"), credential.cert.AccountID, credential.cert.ZoneID, credential.cert.ServiceKey, userAgent, sc.logger)
|
||||
client, err := tunnelstore.NewRESTClient(
|
||||
sc.c.String("api-url"),
|
||||
credential.cert.AccountID,
|
||||
credential.cert.ZoneID,
|
||||
credential.cert.ServiceKey,
|
||||
userAgent,
|
||||
sc.log,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -87,11 +93,11 @@ func (sc *subcommandContext) client() (tunnelstore.Client, error) {
|
|||
|
||||
func (sc *subcommandContext) credential() (*userCredential, error) {
|
||||
if sc.userCredential == nil {
|
||||
originCertPath, err := findOriginCert(sc.c, sc.logger)
|
||||
originCertPath, err := findOriginCert(sc.c, sc.log)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error locating origin cert")
|
||||
}
|
||||
blocks, err := readOriginCert(originCertPath, sc.logger)
|
||||
blocks, err := readOriginCert(originCertPath, sc.log)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Can't read origin cert from %s", originCertPath)
|
||||
}
|
||||
|
|
@ -163,7 +169,7 @@ func (sc *subcommandContext) create(name string) (*tunnelstore.Tunnel, error) {
|
|||
TunnelName: name,
|
||||
}
|
||||
filePath, writeFileErr := writeTunnelCredentials(credential.certPath, &tunnelCredentials)
|
||||
if err != nil {
|
||||
if writeFileErr != nil {
|
||||
var errorLines []string
|
||||
errorLines = append(errorLines, fmt.Sprintf("Your tunnel '%v' was created with ID %v. However, cloudflared couldn't write to the tunnel credentials file at %v.json.", tunnel.Name, tunnel.ID, tunnel.ID))
|
||||
errorLines = append(errorLines, fmt.Sprintf("The file-writing error is: %v", writeFileErr))
|
||||
|
|
@ -176,13 +182,13 @@ func (sc *subcommandContext) create(name string) (*tunnelstore.Tunnel, error) {
|
|||
errorMsg := strings.Join(errorLines, "\n")
|
||||
return nil, errors.New(errorMsg)
|
||||
}
|
||||
sc.logger.Infof("Tunnel credentials written to %v. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel.", filePath)
|
||||
sc.log.Info().Msgf("Tunnel credentials written to %v. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel.", filePath)
|
||||
|
||||
if outputFormat := sc.c.String(outputFormatFlag.Name); outputFormat != "" {
|
||||
return nil, renderOutput(outputFormat, &tunnel)
|
||||
}
|
||||
|
||||
sc.logger.Infof("Created tunnel %s with id %s", tunnel.Name, tunnel.ID)
|
||||
sc.log.Info().Msgf("Created tunnel %s with id %s", tunnel.Name, tunnel.ID)
|
||||
return tunnel, nil
|
||||
}
|
||||
|
||||
|
|
@ -230,7 +236,7 @@ func (sc *subcommandContext) delete(tunnelIDs []uuid.UUID) error {
|
|||
credFinder := sc.credentialFinder(id)
|
||||
if tunnelCredentialsPath, err := credFinder.Path(); err == nil {
|
||||
if err = os.Remove(tunnelCredentialsPath); err != nil {
|
||||
sc.logger.Infof("Tunnel %v was deleted, but we could not remove its credentials file %s: %s. Consider deleting this file manually.", id, tunnelCredentialsPath, err)
|
||||
sc.log.Info().Msgf("Tunnel %v was deleted, but we could not remove its credentials file %s: %s. Consider deleting this file manually.", id, tunnelCredentialsPath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -254,18 +260,19 @@ func (sc *subcommandContext) run(tunnelID uuid.UUID) error {
|
|||
credentials, err := sc.findCredentials(tunnelID)
|
||||
if err != nil {
|
||||
if e, ok := err.(errInvalidJSONCredential); ok {
|
||||
sc.logger.Errorf("The credentials file at %s contained invalid JSON. This is probably caused by passing the wrong filepath. Reminder: the credentials file is a .json file created via `cloudflared tunnel create`.", e.path)
|
||||
sc.logger.Errorf("Invalid JSON when parsing credentials file: %s", e.err.Error())
|
||||
sc.log.Error().Msgf("The credentials file at %s contained invalid JSON. This is probably caused by passing the wrong filepath. Reminder: the credentials file is a .json file created via `cloudflared tunnel create`.", e.path)
|
||||
sc.log.Error().Msgf("Invalid JSON when parsing credentials file: %s", e.err.Error())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return StartServer(
|
||||
sc.c,
|
||||
version,
|
||||
shutdownC,
|
||||
graceShutdownC,
|
||||
&connection.NamedTunnelConfig{Credentials: credentials},
|
||||
sc.logger,
|
||||
sc.log,
|
||||
sc.isUIEnabled,
|
||||
)
|
||||
}
|
||||
|
|
@ -276,9 +283,9 @@ func (sc *subcommandContext) cleanupConnections(tunnelIDs []uuid.UUID) error {
|
|||
return err
|
||||
}
|
||||
for _, tunnelID := range tunnelIDs {
|
||||
sc.logger.Infof("Cleanup connection for tunnel %s", tunnelID)
|
||||
sc.log.Info().Msgf("Cleanup connection for tunnel %s", tunnelID)
|
||||
if err := client.CleanupConnections(tunnelID); err != nil {
|
||||
sc.logger.Errorf("Error cleaning up connections for tunnel %v, error :%v", tunnelID, err)
|
||||
sc.log.Error().Msgf("Error cleaning up connections for tunnel %v, error :%v", tunnelID, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -4,16 +4,15 @@ import (
|
|||
"encoding/base64"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/rs/zerolog"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/connection"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/tunnelstore"
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
|
@ -106,7 +105,7 @@ func (fs mockFileSystem) readFile(filePath string) ([]byte, error) {
|
|||
func Test_subcommandContext_findCredentials(t *testing.T) {
|
||||
type fields struct {
|
||||
c *cli.Context
|
||||
logger logger.Service
|
||||
log *zerolog.Logger
|
||||
isUIEnabled bool
|
||||
fs fileSystem
|
||||
tunnelstoreClient tunnelstore.Client
|
||||
|
|
@ -137,8 +136,7 @@ func Test_subcommandContext_findCredentials(t *testing.T) {
|
|||
},
|
||||
vfp: func(string) bool { return true },
|
||||
}
|
||||
logger, err := logger.New()
|
||||
require.NoError(t, err)
|
||||
log := zerolog.Nop()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
@ -150,13 +148,13 @@ func Test_subcommandContext_findCredentials(t *testing.T) {
|
|||
{
|
||||
name: "Filepath given leads to old credentials file",
|
||||
fields: fields{
|
||||
logger: logger,
|
||||
fs: fs,
|
||||
log: &log,
|
||||
fs: fs,
|
||||
c: func() *cli.Context {
|
||||
flagSet := flag.NewFlagSet("test0", flag.PanicOnError)
|
||||
flagSet.String(CredFileFlag, oldCertPath, "")
|
||||
c := cli.NewContext(cli.NewApp(), flagSet, nil)
|
||||
err = c.Set(CredFileFlag, oldCertPath)
|
||||
_ = c.Set(CredFileFlag, oldCertPath)
|
||||
return c
|
||||
}(),
|
||||
},
|
||||
|
|
@ -172,13 +170,13 @@ func Test_subcommandContext_findCredentials(t *testing.T) {
|
|||
{
|
||||
name: "Filepath given leads to new credentials file",
|
||||
fields: fields{
|
||||
logger: logger,
|
||||
fs: fs,
|
||||
log: &log,
|
||||
fs: fs,
|
||||
c: func() *cli.Context {
|
||||
flagSet := flag.NewFlagSet("test0", flag.PanicOnError)
|
||||
flagSet.String(CredFileFlag, newCertPath, "")
|
||||
c := cli.NewContext(cli.NewApp(), flagSet, nil)
|
||||
err = c.Set(CredFileFlag, newCertPath)
|
||||
_ = c.Set(CredFileFlag, newCertPath)
|
||||
return c
|
||||
}(),
|
||||
},
|
||||
|
|
@ -197,7 +195,7 @@ func Test_subcommandContext_findCredentials(t *testing.T) {
|
|||
t.Run(tt.name, func(t *testing.T) {
|
||||
sc := &subcommandContext{
|
||||
c: tt.fields.c,
|
||||
logger: tt.fields.logger,
|
||||
log: tt.fields.log,
|
||||
isUIEnabled: tt.fields.isUIEnabled,
|
||||
fs: tt.fields.fs,
|
||||
tunnelstoreClient: tt.fields.tunnelstoreClient,
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ func fmtAndPrintTunnelList(tunnels []*tunnelstore.Tunnel, showRecentlyDisconnect
|
|||
defer writer.Flush()
|
||||
|
||||
// Print column headers with tabbed columns
|
||||
fmt.Fprintln(writer, "ID\tNAME\tCREATED\tCONNECTIONS\t")
|
||||
_, _ = fmt.Fprintln(writer, "ID\tNAME\tCREATED\tCONNECTIONS\t")
|
||||
|
||||
// Loop through tunnels, create formatted string for each, and print using tabwriter
|
||||
for _, t := range tunnels {
|
||||
|
|
@ -234,7 +234,7 @@ func fmtAndPrintTunnelList(tunnels []*tunnelstore.Tunnel, showRecentlyDisconnect
|
|||
t.CreatedAt.Format(time.RFC3339),
|
||||
fmtConnections(t.Connections, showRecentlyDisconnected),
|
||||
)
|
||||
fmt.Fprintln(writer, formattedStr)
|
||||
_, _ = fmt.Fprintln(writer, formattedStr)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -360,7 +360,7 @@ func runNamedTunnel(sc *subcommandContext, tunnelRef string) error {
|
|||
return errors.Wrap(err, "error parsing tunnel ID")
|
||||
}
|
||||
|
||||
sc.logger.Infof("Starting tunnel %s", tunnelID.String())
|
||||
sc.log.Info().Msgf("Starting tunnel %s", tunnelID.String())
|
||||
|
||||
return sc.run(tunnelID)
|
||||
}
|
||||
|
|
@ -515,7 +515,7 @@ func routeCommand(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
sc.logger.Infof(res.SuccessSummary())
|
||||
sc.log.Info().Msg(res.SuccessSummary())
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,14 +4,13 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/connection"
|
||||
"github.com/cloudflare/cloudflared/ingress"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
|
||||
"github.com/gdamore/tcell"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type connState struct {
|
||||
|
|
@ -51,16 +50,16 @@ func NewUIModel(version, hostname, metricsURL string, ing *ingress.Ingress, haCo
|
|||
|
||||
func (data *uiModel) LaunchUI(
|
||||
ctx context.Context,
|
||||
generalLogger, transportLogger logger.Service,
|
||||
logLevels []logger.Level,
|
||||
log, transportLog *zerolog.Logger,
|
||||
tunnelEventChan <-chan connection.Event,
|
||||
) {
|
||||
// Configure the logger to stream logs into the textview
|
||||
|
||||
// Add TextView as a group to write output to
|
||||
logTextView := NewDynamicColorTextView()
|
||||
generalLogger.Add(logTextView, logger.NewUIFormatter(time.RFC3339), logLevels...)
|
||||
transportLogger.Add(logTextView, logger.NewUIFormatter(time.RFC3339), logLevels...)
|
||||
// TODO: Format log for UI
|
||||
//log.Add(logTextView, logger.NewUIFormatter(time.RFC3339), logLevels...)
|
||||
//transportLog.Add(logTextView, logger.NewUIFormatter(time.RFC3339), logLevels...)
|
||||
|
||||
// Construct the UI
|
||||
palette := palette{
|
||||
|
|
@ -125,7 +124,7 @@ func (data *uiModel) LaunchUI(
|
|||
case connection.Connected:
|
||||
data.setConnTableCell(event, connTable, palette)
|
||||
case connection.Disconnected, connection.Reconnecting:
|
||||
data.changeConnStatus(event, connTable, generalLogger, palette)
|
||||
data.changeConnStatus(event, connTable, log, palette)
|
||||
case connection.SetURL:
|
||||
tunnelHostText.SetText(event.URL)
|
||||
data.edgeURL = event.URL
|
||||
|
|
@ -141,7 +140,7 @@ func (data *uiModel) LaunchUI(
|
|||
|
||||
go func() {
|
||||
if err := app.SetRoot(frame, true).Run(); err != nil {
|
||||
generalLogger.Errorf("Error launching UI: %s", err)
|
||||
log.Error().Msgf("Error launching UI: %s", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
@ -159,13 +158,13 @@ func handleNewText(app *tview.Application, logTextView *tview.TextView) func() {
|
|||
}
|
||||
}
|
||||
|
||||
func (data *uiModel) changeConnStatus(event connection.Event, table *tview.Table, logger logger.Service, palette palette) {
|
||||
func (data *uiModel) changeConnStatus(event connection.Event, table *tview.Table, log *zerolog.Logger, palette palette) {
|
||||
index := int(event.Index)
|
||||
// Get connection location and state
|
||||
connState := data.getConnState(index)
|
||||
// Check if connection is already displayed in UI
|
||||
if connState == nil {
|
||||
logger.Info("Connection is not in the UI table")
|
||||
log.Info().Msg("Connection is not in the UI table")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package updater
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/rs/zerolog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
|
@ -14,12 +15,10 @@ import (
|
|||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/facebookgo/grace/gracenet"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultCheckUpdateFreq = time.Hour * 24
|
||||
appID = "app_idCzgxYerVD"
|
||||
noUpdateInShellMessage = "cloudflared will not automatically update when run from the shell. To enable auto-updates, run cloudflared as a service: https://developers.cloudflare.com/argo-tunnel/reference/service/"
|
||||
noUpdateOnWindowsMessage = "cloudflared will not automatically update on Windows systems."
|
||||
noUpdateManagedPackageMessage = "cloudflared will not automatically update if installed by a package manager."
|
||||
|
|
@ -114,38 +113,35 @@ func checkForUpdateAndApply(options updateOptions) UpdateOutcome {
|
|||
|
||||
// Update is the handler for the update command from the command line
|
||||
func Update(c *cli.Context) error {
|
||||
logger, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
|
||||
if wasInstalledFromPackageManager() {
|
||||
logger.Error("cloudflared was installed by a package manager. Please update using the same method.")
|
||||
log.Error().Msg("cloudflared was installed by a package manager. Please update using the same method.")
|
||||
return nil
|
||||
}
|
||||
|
||||
isBeta := c.Bool("beta")
|
||||
if isBeta {
|
||||
logger.Info("cloudflared is set to update to the latest beta version")
|
||||
log.Info().Msg("cloudflared is set to update to the latest beta version")
|
||||
}
|
||||
|
||||
isStaging := c.Bool("staging")
|
||||
if isStaging {
|
||||
logger.Info("cloudflared is set to update from staging")
|
||||
log.Info().Msg("cloudflared is set to update from staging")
|
||||
}
|
||||
|
||||
isForced := c.Bool("force")
|
||||
if isForced {
|
||||
logger.Info("cloudflared is set to upgrade to the latest publish version regardless of the current version")
|
||||
log.Info().Msg("cloudflared is set to upgrade to the latest publish version regardless of the current version")
|
||||
}
|
||||
|
||||
updateOutcome := loggedUpdate(logger, updateOptions{isBeta: isBeta, isStaging: isStaging, isForced: isForced, version: c.String("version")})
|
||||
updateOutcome := loggedUpdate(log, updateOptions{isBeta: isBeta, isStaging: isStaging, isForced: isForced, version: c.String("version")})
|
||||
if updateOutcome.Error != nil {
|
||||
return &statusErr{updateOutcome.Error}
|
||||
}
|
||||
|
||||
if updateOutcome.noUpdate() {
|
||||
logger.Infof("cloudflared is up to date (%s)", updateOutcome.Version)
|
||||
log.Info().Msgf("cloudflared is up to date (%s)", updateOutcome.Version)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -153,13 +149,13 @@ func Update(c *cli.Context) error {
|
|||
}
|
||||
|
||||
// Checks for an update and applies it if one is available
|
||||
func loggedUpdate(logger logger.Service, options updateOptions) UpdateOutcome {
|
||||
func loggedUpdate(log *zerolog.Logger, options updateOptions) UpdateOutcome {
|
||||
updateOutcome := checkForUpdateAndApply(options)
|
||||
if updateOutcome.Updated {
|
||||
logger.Infof("cloudflared has been updated to version %s", updateOutcome.Version)
|
||||
log.Info().Msgf("cloudflared has been updated to version %s", updateOutcome.Version)
|
||||
}
|
||||
if updateOutcome.Error != nil {
|
||||
logger.Errorf("update check failed: %s", updateOutcome.Error)
|
||||
log.Error().Msgf("update check failed: %s", updateOutcome.Error)
|
||||
}
|
||||
|
||||
return updateOutcome
|
||||
|
|
@ -170,7 +166,7 @@ type AutoUpdater struct {
|
|||
configurable *configurable
|
||||
listeners *gracenet.Net
|
||||
updateConfigChan chan *configurable
|
||||
logger logger.Service
|
||||
log *zerolog.Logger
|
||||
}
|
||||
|
||||
// AutoUpdaterConfigurable is the attributes of AutoUpdater that can be reconfigured during runtime
|
||||
|
|
@ -179,7 +175,7 @@ type configurable struct {
|
|||
freq time.Duration
|
||||
}
|
||||
|
||||
func NewAutoUpdater(freq time.Duration, listeners *gracenet.Net, logger logger.Service) *AutoUpdater {
|
||||
func NewAutoUpdater(freq time.Duration, listeners *gracenet.Net, log *zerolog.Logger) *AutoUpdater {
|
||||
updaterConfigurable := &configurable{
|
||||
enabled: true,
|
||||
freq: freq,
|
||||
|
|
@ -192,7 +188,7 @@ func NewAutoUpdater(freq time.Duration, listeners *gracenet.Net, logger logger.S
|
|||
configurable: updaterConfigurable,
|
||||
listeners: listeners,
|
||||
updateConfigChan: make(chan *configurable),
|
||||
logger: logger,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -200,19 +196,19 @@ func (a *AutoUpdater) Run(ctx context.Context) error {
|
|||
ticker := time.NewTicker(a.configurable.freq)
|
||||
for {
|
||||
if a.configurable.enabled {
|
||||
updateOutcome := loggedUpdate(a.logger, updateOptions{})
|
||||
updateOutcome := loggedUpdate(a.log, updateOptions{})
|
||||
if updateOutcome.Updated {
|
||||
if IsSysV() {
|
||||
// SysV doesn't have a mechanism to keep service alive, we have to restart the process
|
||||
a.logger.Info("Restarting service managed by SysV...")
|
||||
a.log.Info().Msg("Restarting service managed by SysV...")
|
||||
pid, err := a.listeners.StartProcess()
|
||||
if err != nil {
|
||||
a.logger.Errorf("Unable to restart server automatically: %s", err)
|
||||
a.log.Error().Msgf("Unable to restart server automatically: %s", err)
|
||||
return &statusErr{err: err}
|
||||
}
|
||||
// stop old process after autoupdate. Otherwise we create a new process
|
||||
// after each update
|
||||
a.logger.Infof("PID of the new process is %d", pid)
|
||||
a.log.Info().Msgf("PID of the new process is %d", pid)
|
||||
}
|
||||
return &statusSuccess{newVersion: updateOutcome.Version}
|
||||
}
|
||||
|
|
@ -244,26 +240,26 @@ func (a *AutoUpdater) Update(newFreq time.Duration) {
|
|||
a.updateConfigChan <- newConfigurable
|
||||
}
|
||||
|
||||
func IsAutoupdateEnabled(c *cli.Context, l logger.Service) bool {
|
||||
if !SupportAutoUpdate(l) {
|
||||
func IsAutoupdateEnabled(c *cli.Context, log *zerolog.Logger) bool {
|
||||
if !SupportAutoUpdate(log) {
|
||||
return false
|
||||
}
|
||||
return !c.Bool("no-autoupdate") && c.Duration("autoupdate-freq") != 0
|
||||
}
|
||||
|
||||
func SupportAutoUpdate(logger logger.Service) bool {
|
||||
func SupportAutoUpdate(log *zerolog.Logger) bool {
|
||||
if runtime.GOOS == "windows" {
|
||||
logger.Info(noUpdateOnWindowsMessage)
|
||||
log.Info().Msg(noUpdateOnWindowsMessage)
|
||||
return false
|
||||
}
|
||||
|
||||
if wasInstalledFromPackageManager() {
|
||||
logger.Info(noUpdateManagedPackageMessage)
|
||||
log.Info().Msg(noUpdateManagedPackageMessage)
|
||||
return false
|
||||
}
|
||||
|
||||
if isRunningFromTerminal() {
|
||||
logger.Info(noUpdateInShellMessage)
|
||||
log.Info().Msg(noUpdateInShellMessage)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -4,15 +4,15 @@ import (
|
|||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/facebookgo/grace/gracenet"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDisabledAutoUpdater(t *testing.T) {
|
||||
listeners := &gracenet.Net{}
|
||||
logger := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
autoupdater := NewAutoUpdater(0, listeners, logger)
|
||||
log := zerolog.Nop()
|
||||
autoupdater := NewAutoUpdater(0, listeners, &log)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
errC := make(chan error)
|
||||
go func() {
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@ import (
|
|||
"unsafe"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/pkg/errors"
|
||||
cli "github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc"
|
||||
"golang.org/x/sys/windows/svc/eventlog"
|
||||
|
|
@ -67,15 +66,11 @@ func runApp(app *cli.App, shutdownC, graceShutdownC chan struct{}) {
|
|||
// 2. get ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
|
||||
// This involves actually trying to start the service.
|
||||
|
||||
logger, err := logger.New()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
log := logger.Create(nil)
|
||||
|
||||
isIntSess, err := svc.IsAnInteractiveSession()
|
||||
if err != nil {
|
||||
logger.Fatalf("failed to determine if we are running in an interactive session: %v", err)
|
||||
log.Fatal().Msgf("failed to determine if we are running in an interactive session: %v", err)
|
||||
}
|
||||
if isIntSess {
|
||||
app.Run(os.Args)
|
||||
|
|
@ -93,7 +88,7 @@ func runApp(app *cli.App, shutdownC, graceShutdownC chan struct{}) {
|
|||
app.Run(os.Args)
|
||||
return
|
||||
}
|
||||
logger.Fatalf("%s service failed: %v", windowsServiceName, err)
|
||||
log.Fatal().Msgf("%s service failed: %v", windowsServiceName, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,15 +100,10 @@ type windowsService struct {
|
|||
|
||||
// called by the package code at the start of the service
|
||||
func (s *windowsService) Execute(serviceArgs []string, r <-chan svc.ChangeRequest, statusChan chan<- svc.Status) (ssec bool, errno uint32) {
|
||||
logger, err := logger.New()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
log := logger.Create(nil)
|
||||
elog, err := eventlog.Open(windowsServiceName)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot open event log for %s with error: %s", windowsServiceName, err)
|
||||
log.Error().Msgf("Cannot open event log for %s with error: %s", windowsServiceName, err)
|
||||
return
|
||||
}
|
||||
defer elog.Close()
|
||||
|
|
@ -173,79 +163,73 @@ func (s *windowsService) Execute(serviceArgs []string, r <-chan svc.ChangeReques
|
|||
}
|
||||
|
||||
func installWindowsService(c *cli.Context) error {
|
||||
logger, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
|
||||
logger.Infof("Installing Argo Tunnel Windows service")
|
||||
log.Info().Msgf("Installing Argo Tunnel Windows service")
|
||||
exepath, err := os.Executable()
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot find path name that start the process")
|
||||
log.Error().Msgf("Cannot find path name that start the process")
|
||||
return err
|
||||
}
|
||||
m, err := mgr.Connect()
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot establish a connection to the service control manager: %s", err)
|
||||
log.Error().Msgf("Cannot establish a connection to the service control manager: %s", err)
|
||||
return err
|
||||
}
|
||||
defer m.Disconnect()
|
||||
s, err := m.OpenService(windowsServiceName)
|
||||
if err == nil {
|
||||
s.Close()
|
||||
logger.Errorf("service %s already exists", windowsServiceName)
|
||||
log.Error().Msgf("service %s already exists", windowsServiceName)
|
||||
return fmt.Errorf("service %s already exists", windowsServiceName)
|
||||
}
|
||||
config := mgr.Config{StartType: mgr.StartAutomatic, DisplayName: windowsServiceDescription}
|
||||
s, err = m.CreateService(windowsServiceName, exepath, config)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot install service %s", windowsServiceName)
|
||||
log.Error().Msgf("Cannot install service %s", windowsServiceName)
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
logger.Infof("Argo Tunnel agent service is installed")
|
||||
log.Info().Msgf("Argo Tunnel agent service is installed")
|
||||
err = eventlog.InstallAsEventCreate(windowsServiceName, eventlog.Error|eventlog.Warning|eventlog.Info)
|
||||
if err != nil {
|
||||
s.Delete()
|
||||
logger.Errorf("Cannot install event logger: %s", err)
|
||||
log.Error().Msgf("Cannot install event logger: %s", err)
|
||||
return fmt.Errorf("SetupEventLogSource() failed: %s", err)
|
||||
}
|
||||
err = configRecoveryOption(s.Handle)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot set service recovery actions: %s", err)
|
||||
logger.Infof("See %s to manually configure service recovery actions", windowsServiceUrl)
|
||||
log.Error().Msgf("Cannot set service recovery actions: %s", err)
|
||||
log.Info().Msgf("See %s to manually configure service recovery actions", windowsServiceUrl)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func uninstallWindowsService(c *cli.Context) error {
|
||||
logger, err := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
||||
|
||||
logger.Infof("Uninstalling Argo Tunnel Windows Service")
|
||||
log.Info().Msgf("Uninstalling Argo Tunnel Windows Service")
|
||||
m, err := mgr.Connect()
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot establish a connection to the service control manager")
|
||||
log.Error().Msgf("Cannot establish a connection to the service control manager")
|
||||
return err
|
||||
}
|
||||
defer m.Disconnect()
|
||||
s, err := m.OpenService(windowsServiceName)
|
||||
if err != nil {
|
||||
logger.Errorf("service %s is not installed", windowsServiceName)
|
||||
log.Error().Msgf("service %s is not installed", windowsServiceName)
|
||||
return fmt.Errorf("service %s is not installed", windowsServiceName)
|
||||
}
|
||||
defer s.Close()
|
||||
err = s.Delete()
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot delete service %s", windowsServiceName)
|
||||
log.Error().Msgf("Cannot delete service %s", windowsServiceName)
|
||||
return err
|
||||
}
|
||||
logger.Infof("Argo Tunnel agent service is uninstalled")
|
||||
log.Info().Msgf("Argo Tunnel agent service is uninstalled")
|
||||
err = eventlog.Remove(windowsServiceName)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot remove event logger")
|
||||
log.Error().Msgf("Cannot remove event logger")
|
||||
return fmt.Errorf("RemoveEventLogSource() failed: %s", err)
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/gobwas/ws/wsutil"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -22,14 +22,14 @@ var (
|
|||
OriginClient: &mockOriginClient{},
|
||||
GracePeriod: time.Millisecond * 100,
|
||||
}
|
||||
testLogger, _ = logger.New()
|
||||
log = zerolog.Nop()
|
||||
testOriginURL = &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "connectiontest.argotunnel.com",
|
||||
}
|
||||
testTunnelEventChan = make(chan Event)
|
||||
testObserver = &Observer{
|
||||
testLogger,
|
||||
&log,
|
||||
m,
|
||||
[]chan Event{testTunnelEventChan},
|
||||
false,
|
||||
|
|
@ -81,7 +81,7 @@ func wsEndpoint(w ResponseWriter, r *http.Request) error {
|
|||
resp := &http.Response{
|
||||
StatusCode: http.StatusSwitchingProtocols,
|
||||
}
|
||||
w.WriteRespHeaders(resp)
|
||||
_ = w.WriteRespHeaders(resp)
|
||||
clientReader := nowriter{r.Body}
|
||||
go func() {
|
||||
for {
|
||||
|
|
@ -102,8 +102,8 @@ func originRespEndpoint(w ResponseWriter, status int, data []byte) {
|
|||
resp := &http.Response{
|
||||
StatusCode: status,
|
||||
}
|
||||
w.WriteRespHeaders(resp)
|
||||
w.Write(data)
|
||||
_ = w.WriteRespHeaders(resp)
|
||||
_, _ = w.Write(data)
|
||||
}
|
||||
|
||||
type mockConnectedFuse struct{}
|
||||
|
|
|
|||
|
|
@ -65,11 +65,11 @@ func (e muxerShutdownError) Error() string {
|
|||
func isHandshakeErrRecoverable(err error, connIndex uint8, observer *Observer) bool {
|
||||
switch err.(type) {
|
||||
case edgediscovery.DialError:
|
||||
observer.Errorf("Connection %d unable to dial edge: %s", connIndex, err)
|
||||
observer.log.Error().Msgf("Connection %d unable to dial edge: %s", connIndex, err)
|
||||
case h2mux.MuxerHandshakeError:
|
||||
observer.Errorf("Connection %d handshake with edge server failed: %s", connIndex, err)
|
||||
observer.log.Error().Msgf("Connection %d handshake with edge server failed: %s", connIndex, err)
|
||||
default:
|
||||
observer.Errorf("Connection %d failed: %s", connIndex, err)
|
||||
observer.log.Error().Msgf("Connection %d failed: %s", connIndex, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -7,10 +7,11 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/h2mux"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
||||
"github.com/cloudflare/cloudflared/websocket"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
|
|
@ -37,14 +38,14 @@ type MuxerConfig struct {
|
|||
MetricsUpdateFreq time.Duration
|
||||
}
|
||||
|
||||
func (mc *MuxerConfig) H2MuxerConfig(h h2mux.MuxedStreamHandler, logger logger.Service) *h2mux.MuxerConfig {
|
||||
func (mc *MuxerConfig) H2MuxerConfig(h h2mux.MuxedStreamHandler, log *zerolog.Logger) *h2mux.MuxerConfig {
|
||||
return &h2mux.MuxerConfig{
|
||||
Timeout: muxerTimeout,
|
||||
Handler: h,
|
||||
IsClient: true,
|
||||
HeartbeatInterval: mc.HeartbeatInterval,
|
||||
MaxHeartbeats: mc.MaxHeartbeats,
|
||||
Logger: logger,
|
||||
Log: log,
|
||||
CompressionQuality: mc.CompressionSetting,
|
||||
}
|
||||
}
|
||||
|
|
@ -67,7 +68,7 @@ func NewH2muxConnection(ctx context.Context,
|
|||
|
||||
// Establish a muxed connection with the edge
|
||||
// Client mux handshake with agent server
|
||||
muxer, err := h2mux.Handshake(edgeConn, edgeConn, *muxerConfig.H2MuxerConfig(h, observer), h2mux.ActiveStreams)
|
||||
muxer, err := h2mux.Handshake(edgeConn, edgeConn, *muxerConfig.H2MuxerConfig(h, observer.log), h2mux.ActiveStreams)
|
||||
if err != nil {
|
||||
recoverable := isHandshakeErrRecoverable(err, connIndex, observer)
|
||||
return nil, err, recoverable
|
||||
|
|
@ -87,7 +88,7 @@ func (h *h2muxConnection) ServeNamedTunnel(ctx context.Context, namedTunnel *Nam
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rpcClient := newRegistrationRPCClient(ctx, stream, h.observer)
|
||||
rpcClient := newRegistrationRPCClient(ctx, stream, h.observer.log)
|
||||
defer rpcClient.Close()
|
||||
|
||||
if err = rpcClient.RegisterConnection(serveCtx, namedTunnel, connOptions, h.connIndex, h.observer); err != nil {
|
||||
|
|
@ -122,7 +123,7 @@ func (h *h2muxConnection) ServeClassicTunnel(ctx context.Context, classicTunnel
|
|||
return nil
|
||||
}
|
||||
// log errors and proceed to RegisterTunnel
|
||||
h.observer.Errorf("Couldn't reconnect connection %d. Reregistering it instead. Error was: %v", h.connIndex, err)
|
||||
h.observer.log.Error().Msgf("Couldn't reconnect connection %d. Reregistering it instead. Error was: %v", h.connIndex, err)
|
||||
}
|
||||
return h.registerTunnel(ctx, credentialManager, classicTunnel, registrationOptions)
|
||||
})
|
||||
|
|
@ -212,9 +213,9 @@ func (rp *h2muxRespWriter) WriteRespHeaders(resp *http.Response) error {
|
|||
}
|
||||
|
||||
func (rp *h2muxRespWriter) WriteErrorResponse() {
|
||||
rp.WriteHeaders([]h2mux.Header{
|
||||
_ = rp.WriteHeaders([]h2mux.Header{
|
||||
{Name: ":status", Value: "502"},
|
||||
{Name: ResponseMetaHeaderField, Value: responseMetaHeaderCfd},
|
||||
})
|
||||
rp.Write([]byte("502 Bad Gateway"))
|
||||
_, _ = rp.Write([]byte("502 Bad Gateway"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ func newH2MuxConnection(ctx context.Context, t require.TestingT) (*h2muxConnecti
|
|||
edgeMuxChan := make(chan *h2mux.Muxer)
|
||||
go func() {
|
||||
edgeMuxConfig := h2mux.MuxerConfig{
|
||||
Logger: testObserver,
|
||||
Log: testObserver.log,
|
||||
}
|
||||
edgeMux, err := h2mux.Handshake(edgeConn, edgeConn, edgeMuxConfig, h2mux.ActiveStreams)
|
||||
require.NoError(t, err)
|
||||
|
|
@ -85,7 +85,7 @@ func TestServeStreamHTTP(t *testing.T) {
|
|||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
edgeMux.Serve(ctx)
|
||||
_ = edgeMux.Serve(ctx)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/cloudflare/cloudflared/h2mux"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ type http2Connection struct {
|
|||
connIndex uint8
|
||||
wg *sync.WaitGroup
|
||||
// newRPCClientFunc allows us to mock RPCs during testing
|
||||
newRPCClientFunc func(context.Context, io.ReadWriteCloser, logger.Service) NamedTunnelRPCClient
|
||||
newRPCClientFunc func(context.Context, io.ReadWriteCloser, *zerolog.Logger) NamedTunnelRPCClient
|
||||
connectedFuse ConnectedFuse
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ func (c *http2Connection) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
flusher, isFlusher := w.(http.Flusher)
|
||||
if !isFlusher {
|
||||
c.observer.Errorf("%T doesn't implement http.Flusher", w)
|
||||
c.observer.log.Error().Msgf("%T doesn't implement http.Flusher", w)
|
||||
respWriter.WriteErrorResponse()
|
||||
return
|
||||
}
|
||||
|
|
@ -112,7 +112,7 @@ func (c *http2Connection) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func (c *http2Connection) serveControlStream(ctx context.Context, respWriter *http2RespWriter) error {
|
||||
rpcClient := c.newRPCClientFunc(ctx, respWriter, c.observer)
|
||||
rpcClient := c.newRPCClientFunc(ctx, respWriter, c.observer.log)
|
||||
defer rpcClient.Close()
|
||||
|
||||
if err := rpcClient.RegisterConnection(ctx, c.namedTunnel, c.connOptions, c.connIndex, c.observer); err != nil {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
||||
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
||||
|
||||
"github.com/gobwas/ws/wsutil"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
|
@ -136,7 +137,7 @@ type mockRPCClientFactory struct {
|
|||
unregistered chan struct{}
|
||||
}
|
||||
|
||||
func (mf *mockRPCClientFactory) newMockRPCClient(context.Context, io.ReadWriteCloser, logger.Service) NamedTunnelRPCClient {
|
||||
func (mf *mockRPCClientFactory) newMockRPCClient(context.Context, io.ReadWriteCloser, *zerolog.Logger) NamedTunnelRPCClient {
|
||||
return mockNamedTunnelRPCClient{
|
||||
registered: mf.registered,
|
||||
unregistered: mf.unregistered,
|
||||
|
|
|
|||
|
|
@ -5,20 +5,21 @@ import (
|
|||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type Observer struct {
|
||||
logger.Service
|
||||
log *zerolog.Logger
|
||||
metrics *tunnelMetrics
|
||||
tunnelEventChans []chan Event
|
||||
uiEnabled bool
|
||||
}
|
||||
|
||||
func NewObserver(logger logger.Service, tunnelEventChans []chan Event, uiEnabled bool) *Observer {
|
||||
func NewObserver(log *zerolog.Logger, tunnelEventChans []chan Event, uiEnabled bool) *Observer {
|
||||
return &Observer{
|
||||
logger,
|
||||
log,
|
||||
newTunnelMetrics(),
|
||||
tunnelEventChans,
|
||||
uiEnabled,
|
||||
|
|
@ -27,7 +28,7 @@ func NewObserver(logger logger.Service, tunnelEventChans []chan Event, uiEnabled
|
|||
|
||||
func (o *Observer) logServerInfo(connIndex uint8, location, msg string) {
|
||||
o.sendEvent(Event{Index: connIndex, EventType: Connected, Location: location})
|
||||
o.Infof(msg)
|
||||
o.log.Info().Msgf(msg)
|
||||
o.metrics.registerServerLocation(uint8ToString(connIndex), location)
|
||||
}
|
||||
|
||||
|
|
@ -36,10 +37,10 @@ func (o *Observer) logTrialHostname(registration *tunnelpogs.TunnelRegistration)
|
|||
if !o.uiEnabled {
|
||||
if registrationURL, err := url.Parse(registration.Url); err == nil {
|
||||
for _, line := range asciiBox(trialZoneMsg(registrationURL.String()), 2) {
|
||||
o.Info(line)
|
||||
o.log.Info().Msg(line)
|
||||
}
|
||||
} else {
|
||||
o.Error("Failed to connect tunnel, please try again.")
|
||||
o.log.Error().Msg("Failed to connect tunnel, please try again.")
|
||||
return fmt.Errorf("empty URL in response from Cloudflare edge")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -89,7 +89,7 @@ type autoProtocolSelector struct {
|
|||
fetchFunc PercentageFetcher
|
||||
refreshAfter time.Time
|
||||
ttl time.Duration
|
||||
logger logger.Service
|
||||
log *zerolog.Logger
|
||||
}
|
||||
|
||||
func newAutoProtocolSelector(
|
||||
|
|
@ -97,7 +97,7 @@ func newAutoProtocolSelector(
|
|||
switchThrehold int32,
|
||||
fetchFunc PercentageFetcher,
|
||||
ttl time.Duration,
|
||||
logger logger.Service,
|
||||
log *zerolog.Logger,
|
||||
) *autoProtocolSelector {
|
||||
return &autoProtocolSelector{
|
||||
current: current,
|
||||
|
|
@ -105,7 +105,7 @@ func newAutoProtocolSelector(
|
|||
fetchFunc: fetchFunc,
|
||||
refreshAfter: time.Now().Add(ttl),
|
||||
ttl: ttl,
|
||||
logger: logger,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ func (s *autoProtocolSelector) Current() Protocol {
|
|||
|
||||
percentage, err := s.fetchFunc()
|
||||
if err != nil {
|
||||
s.logger.Errorf("Failed to refresh protocol, err: %v", err)
|
||||
s.log.Error().Msgf("Failed to refresh protocol, err: %v", err)
|
||||
return s.current
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +139,13 @@ func (s *autoProtocolSelector) Fallback() (Protocol, bool) {
|
|||
|
||||
type PercentageFetcher func() (int32, error)
|
||||
|
||||
func NewProtocolSelector(protocolFlag string, namedTunnel *NamedTunnelConfig, fetchFunc PercentageFetcher, ttl time.Duration, logger logger.Service) (ProtocolSelector, error) {
|
||||
func NewProtocolSelector(
|
||||
protocolFlag string,
|
||||
namedTunnel *NamedTunnelConfig,
|
||||
fetchFunc PercentageFetcher,
|
||||
ttl time.Duration,
|
||||
log *zerolog.Logger,
|
||||
) (ProtocolSelector, error) {
|
||||
if namedTunnel == nil {
|
||||
return &staticProtocolSelector{
|
||||
current: H2mux,
|
||||
|
|
@ -157,9 +163,9 @@ func NewProtocolSelector(protocolFlag string, namedTunnel *NamedTunnelConfig, fe
|
|||
}
|
||||
if protocolFlag == HTTP2.String() {
|
||||
if http2Percentage < 0 {
|
||||
return newAutoProtocolSelector(H2mux, explicitHTTP2FallbackThreshold, fetchFunc, ttl, logger), nil
|
||||
return newAutoProtocolSelector(H2mux, explicitHTTP2FallbackThreshold, fetchFunc, ttl, log), nil
|
||||
}
|
||||
return newAutoProtocolSelector(HTTP2, explicitHTTP2FallbackThreshold, fetchFunc, ttl, logger), nil
|
||||
return newAutoProtocolSelector(HTTP2, explicitHTTP2FallbackThreshold, fetchFunc, ttl, log), nil
|
||||
}
|
||||
|
||||
if protocolFlag != autoSelectFlag {
|
||||
|
|
@ -167,13 +173,13 @@ func NewProtocolSelector(protocolFlag string, namedTunnel *NamedTunnelConfig, fe
|
|||
}
|
||||
threshold := switchThreshold(namedTunnel.Credentials.AccountTag)
|
||||
if threshold < http2Percentage {
|
||||
return newAutoProtocolSelector(HTTP2, threshold, fetchFunc, ttl, logger), nil
|
||||
return newAutoProtocolSelector(HTTP2, threshold, fetchFunc, ttl, log), nil
|
||||
}
|
||||
return newAutoProtocolSelector(H2mux, threshold, fetchFunc, ttl, logger), nil
|
||||
return newAutoProtocolSelector(H2mux, threshold, fetchFunc, ttl, log), nil
|
||||
}
|
||||
|
||||
func switchThreshold(accountTag string) int32 {
|
||||
h := fnv.New32a()
|
||||
h.Write([]byte(accountTag))
|
||||
_, _ = h.Write([]byte(accountTag))
|
||||
return int32(h.Sum32() % 100)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -130,9 +129,9 @@ func TestNewProtocolSelector(t *testing.T) {
|
|||
wantErr: true,
|
||||
},
|
||||
}
|
||||
logger, _ := logger.New()
|
||||
|
||||
for _, test := range tests {
|
||||
selector, err := NewProtocolSelector(test.protocol, test.namedTunnelConfig, test.fetchFunc, testNoTTL, logger)
|
||||
selector, err := NewProtocolSelector(test.protocol, test.namedTunnelConfig, test.fetchFunc, testNoTTL, &log)
|
||||
if test.wantErr {
|
||||
assert.Error(t, err, fmt.Sprintf("test %s failed", test.name))
|
||||
} else {
|
||||
|
|
@ -148,9 +147,8 @@ func TestNewProtocolSelector(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAutoProtocolSelectorRefresh(t *testing.T) {
|
||||
logger, _ := logger.New()
|
||||
fetcher := dynamicMockFetcher{}
|
||||
selector, err := NewProtocolSelector("auto", testNamedTunnelConfig, fetcher.fetch(), testNoTTL, logger)
|
||||
selector, err := NewProtocolSelector("auto", testNamedTunnelConfig, fetcher.fetch(), testNoTTL, &log)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, H2mux, selector.Current())
|
||||
|
||||
|
|
@ -178,9 +176,8 @@ func TestAutoProtocolSelectorRefresh(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestHTTP2ProtocolSelectorRefresh(t *testing.T) {
|
||||
logger, _ := logger.New()
|
||||
fetcher := dynamicMockFetcher{}
|
||||
selector, err := NewProtocolSelector("http2", testNamedTunnelConfig, fetcher.fetch(), testNoTTL, logger)
|
||||
selector, err := NewProtocolSelector("http2", testNamedTunnelConfig, fetcher.fetch(), testNoTTL, &log)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, HTTP2, selector.Current())
|
||||
|
||||
|
|
@ -208,9 +205,8 @@ func TestHTTP2ProtocolSelectorRefresh(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestProtocolSelectorRefreshTTL(t *testing.T) {
|
||||
logger, _ := logger.New()
|
||||
fetcher := dynamicMockFetcher{percentage: 100}
|
||||
selector, err := NewProtocolSelector("auto", testNamedTunnelConfig, fetcher.fetch(), time.Hour, logger)
|
||||
selector, err := NewProtocolSelector("auto", testNamedTunnelConfig, fetcher.fetch(), time.Hour, &log)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, HTTP2, selector.Current())
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@ import (
|
|||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/tunnelrpc"
|
||||
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"zombiezen.com/go/capnproto2/rpc"
|
||||
)
|
||||
|
||||
|
|
@ -22,12 +23,12 @@ type tunnelServerClient struct {
|
|||
func NewTunnelServerClient(
|
||||
ctx context.Context,
|
||||
stream io.ReadWriteCloser,
|
||||
logger logger.Service,
|
||||
log *zerolog.Logger,
|
||||
) *tunnelServerClient {
|
||||
transport := tunnelrpc.NewTransportLogger(logger, rpc.StreamTransport(stream))
|
||||
transport := tunnelrpc.NewTransportLogger(log, rpc.StreamTransport(stream))
|
||||
conn := rpc.NewConn(
|
||||
transport,
|
||||
tunnelrpc.ConnLog(logger),
|
||||
tunnelrpc.ConnLog(log),
|
||||
)
|
||||
registrationClient := tunnelpogs.RegistrationServer_PogsClient{Client: conn.Bootstrap(ctx), Conn: conn}
|
||||
return &tunnelServerClient{
|
||||
|
|
@ -46,8 +47,8 @@ func (tsc *tunnelServerClient) Authenticate(ctx context.Context, classicTunnel *
|
|||
|
||||
func (tsc *tunnelServerClient) Close() {
|
||||
// Closing the client will also close the connection
|
||||
tsc.client.Close()
|
||||
tsc.transport.Close()
|
||||
_ = tsc.client.Close()
|
||||
_ = tsc.transport.Close()
|
||||
}
|
||||
|
||||
type NamedTunnelRPCClient interface {
|
||||
|
|
@ -70,12 +71,12 @@ type registrationServerClient struct {
|
|||
func newRegistrationRPCClient(
|
||||
ctx context.Context,
|
||||
stream io.ReadWriteCloser,
|
||||
logger logger.Service,
|
||||
log *zerolog.Logger,
|
||||
) NamedTunnelRPCClient {
|
||||
transport := tunnelrpc.NewTransportLogger(logger, rpc.StreamTransport(stream))
|
||||
transport := tunnelrpc.NewTransportLogger(log, rpc.StreamTransport(stream))
|
||||
conn := rpc.NewConn(
|
||||
transport,
|
||||
tunnelrpc.ConnLog(logger),
|
||||
tunnelrpc.ConnLog(log),
|
||||
)
|
||||
return ®istrationServerClient{
|
||||
client: tunnelpogs.RegistrationServer_PogsClient{Client: conn.Bootstrap(ctx), Conn: conn},
|
||||
|
|
@ -117,14 +118,14 @@ func (rsc *registrationServerClient) RegisterConnection(
|
|||
func (rsc *registrationServerClient) GracefulShutdown(ctx context.Context, gracePeriod time.Duration) {
|
||||
ctx, cancel := context.WithTimeout(ctx, gracePeriod)
|
||||
defer cancel()
|
||||
rsc.client.UnregisterConnection(ctx)
|
||||
_ = rsc.client.UnregisterConnection(ctx)
|
||||
}
|
||||
|
||||
func (rsc *registrationServerClient) Close() {
|
||||
// Closing the client will also close the connection
|
||||
rsc.client.Close()
|
||||
_ = rsc.client.Close()
|
||||
// Closing the transport also closes the stream
|
||||
rsc.transport.Close()
|
||||
_ = rsc.transport.Close()
|
||||
}
|
||||
|
||||
type rpcName string
|
||||
|
|
@ -143,10 +144,10 @@ func (h *h2muxConnection) registerTunnel(ctx context.Context, credentialSetter C
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rpcClient := NewTunnelServerClient(ctx, stream, h.observer)
|
||||
rpcClient := NewTunnelServerClient(ctx, stream, h.observer.log)
|
||||
defer rpcClient.Close()
|
||||
|
||||
h.logServerInfo(ctx, rpcClient)
|
||||
_ = h.logServerInfo(ctx, rpcClient)
|
||||
registration := rpcClient.client.RegisterTunnel(
|
||||
ctx,
|
||||
classicTunnel.OriginCert,
|
||||
|
|
@ -178,12 +179,12 @@ func (h *h2muxConnection) processRegistrationSuccess(
|
|||
credentialManager CredentialManager, classicTunnel *ClassicTunnelConfig,
|
||||
) error {
|
||||
for _, logLine := range registration.LogLines {
|
||||
h.observer.Info(logLine)
|
||||
h.observer.log.Info().Msg(logLine)
|
||||
}
|
||||
|
||||
if registration.TunnelID != "" {
|
||||
h.observer.metrics.tunnelsHA.AddTunnelID(h.connIndex, registration.TunnelID)
|
||||
h.observer.Infof("Each HA connection's tunnel IDs: %v", h.observer.metrics.tunnelsHA.String())
|
||||
h.observer.log.Info().Msgf("Each HA connection's tunnel IDs: %v", h.observer.metrics.tunnelsHA.String())
|
||||
}
|
||||
|
||||
// Print out the user's trial zone URL in a nice box (if they requested and got one and UI flag is not set)
|
||||
|
|
@ -197,7 +198,7 @@ func (h *h2muxConnection) processRegistrationSuccess(
|
|||
credentialManager.SetConnDigest(h.connIndex, registration.ConnDigest)
|
||||
h.observer.metrics.userHostnamesCounts.WithLabelValues(registration.Url).Inc()
|
||||
|
||||
h.observer.Infof("Route propagating, it may take up to 1 minute for your new route to become functional")
|
||||
h.observer.log.Info().Msgf("Route propagating, it may take up to 1 minute for your new route to become functional")
|
||||
h.observer.metrics.regSuccess.WithLabelValues(string(name)).Inc()
|
||||
return nil
|
||||
}
|
||||
|
|
@ -228,15 +229,15 @@ func (h *h2muxConnection) reconnectTunnel(ctx context.Context, credentialManager
|
|||
return err
|
||||
}
|
||||
|
||||
h.observer.Debug("initiating RPC stream to reconnect")
|
||||
h.observer.log.Debug().Msg("initiating RPC stream to reconnect")
|
||||
stream, err := h.newRPCStream(ctx, register)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rpcClient := NewTunnelServerClient(ctx, stream, h.observer)
|
||||
rpcClient := NewTunnelServerClient(ctx, stream, h.observer.log)
|
||||
defer rpcClient.Close()
|
||||
|
||||
h.logServerInfo(ctx, rpcClient)
|
||||
_ = h.logServerInfo(ctx, rpcClient)
|
||||
registration := rpcClient.client.ReconnectTunnel(
|
||||
ctx,
|
||||
token,
|
||||
|
|
@ -259,15 +260,15 @@ func (h *h2muxConnection) logServerInfo(ctx context.Context, rpcClient *tunnelSe
|
|||
})
|
||||
serverInfoMessage, err := serverInfoPromise.Result().Struct()
|
||||
if err != nil {
|
||||
h.observer.Errorf("Failed to retrieve server information: %s", err)
|
||||
h.observer.log.Error().Msgf("Failed to retrieve server information: %s", err)
|
||||
return err
|
||||
}
|
||||
serverInfo, err := tunnelpogs.UnmarshalServerInfo(serverInfoMessage)
|
||||
if err != nil {
|
||||
h.observer.Errorf("Failed to retrieve server information: %s", err)
|
||||
h.observer.log.Error().Msgf("Failed to retrieve server information: %s", err)
|
||||
return err
|
||||
}
|
||||
h.observer.logServerInfo(h.connIndex, serverInfo.LocationName, fmt.Sprintf("Connnection %d connected to %s", h.connIndex, serverInfo.LocationName))
|
||||
h.observer.logServerInfo(h.connIndex, serverInfo.LocationName, fmt.Sprintf("Connection %d connected to %s", h.connIndex, serverInfo.LocationName))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -281,15 +282,15 @@ func (h *h2muxConnection) unregister(isNamedTunnel bool) {
|
|||
}
|
||||
|
||||
if isNamedTunnel {
|
||||
rpcClient := newRegistrationRPCClient(unregisterCtx, stream, h.observer)
|
||||
rpcClient := newRegistrationRPCClient(unregisterCtx, stream, h.observer.log)
|
||||
defer rpcClient.Close()
|
||||
|
||||
rpcClient.GracefulShutdown(unregisterCtx, h.config.GracePeriod)
|
||||
} else {
|
||||
rpcClient := NewTunnelServerClient(unregisterCtx, stream, h.observer)
|
||||
rpcClient := NewTunnelServerClient(unregisterCtx, stream, h.observer.log)
|
||||
defer rpcClient.Close()
|
||||
|
||||
// gracePeriod is encoded in int64 using capnproto
|
||||
rpcClient.client.UnregisterTunnel(unregisterCtx, h.config.GracePeriod.Nanoseconds())
|
||||
_ = rpcClient.client.UnregisterTunnel(unregisterCtx, h.config.GracePeriod.Nanoseconds())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,20 +8,21 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/hello"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/validation"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// Proxy is an HTTP server that proxies requests to a Client.
|
||||
type Proxy struct {
|
||||
client Client
|
||||
accessValidator *validation.Access
|
||||
logger logger.Service
|
||||
log *zerolog.Logger
|
||||
}
|
||||
|
||||
// NewInsecureProxy creates a Proxy that talks to a Client at an origin.
|
||||
|
|
@ -43,12 +44,9 @@ func NewInsecureProxy(ctx context.Context, origin string) (*Proxy, error) {
|
|||
return nil, errors.Wrap(err, "could not connect to the database")
|
||||
}
|
||||
|
||||
logger, err := logger.New() // TODO: Does not obey log configuration
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error setting up logger")
|
||||
}
|
||||
log := zerolog.New(os.Stderr).With().Logger() // TODO: Does not obey log configuration
|
||||
|
||||
return &Proxy{client, nil, logger}, nil
|
||||
return &Proxy{client, nil, &log}, nil
|
||||
}
|
||||
|
||||
// NewSecureProxy creates a Proxy that talks to a Client at an origin.
|
||||
|
|
@ -96,7 +94,7 @@ func (proxy *Proxy) IsAllowed(r *http.Request, verbose ...bool) bool {
|
|||
// of either a misconfiguration of the CLI or a massive failure of upstream systems.
|
||||
if len(verbose) > 0 {
|
||||
cfRay := proxy.getRayHeader(r)
|
||||
proxy.logger.Infof("dbproxy: Failed JWT authentication: cf-ray: %s %s", cfRay, err)
|
||||
proxy.log.Info().Msgf("dbproxy: Failed JWT authentication: cf-ray: %s %s", cfRay, err)
|
||||
}
|
||||
|
||||
return false
|
||||
|
|
@ -151,8 +149,8 @@ func (proxy *Proxy) httpListen(ctx context.Context, listener net.Listener) error
|
|||
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
httpServer.Close()
|
||||
listener.Close()
|
||||
_ = httpServer.Close()
|
||||
_ = listener.Close()
|
||||
}()
|
||||
|
||||
return httpServer.Serve(listener)
|
||||
|
|
@ -241,7 +239,7 @@ func (proxy *Proxy) httpRespondErr(w http.ResponseWriter, r *http.Request, defau
|
|||
proxy.httpRespond(w, r, status, err.Error())
|
||||
if len(err.Error()) > 0 {
|
||||
cfRay := proxy.getRayHeader(r)
|
||||
proxy.logger.Infof("dbproxy: Database proxy error: cf-ray: %s %s", cfRay, err)
|
||||
proxy.log.Info().Msgf("dbproxy: Database proxy error: cf-ray: %s %s", cfRay, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ func NewSQLClient(ctx context.Context, originURL *url.URL) (Client, error) {
|
|||
// Closes the driver, will occur when the context finishes.
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
driver.Close()
|
||||
_ = driver.Close()
|
||||
}()
|
||||
|
||||
return &SQLClient{driver.DriverName(), driver}, nil
|
||||
|
|
@ -260,7 +260,7 @@ func sqlRows(rows *sql.Rows) ([]map[string]interface{}, error) {
|
|||
for i := range columns {
|
||||
pointers[i] = &values[i]
|
||||
}
|
||||
rows.Scan(pointers...)
|
||||
_ = rows.Scan(pointers...)
|
||||
|
||||
// Convert a row, an array of values, into an object where
|
||||
// each key is the name of its respective column.
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import (
|
|||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -58,15 +58,15 @@ var friendlyDNSErrorLines = []string{
|
|||
}
|
||||
|
||||
// EdgeDiscovery implements HA service discovery lookup.
|
||||
func edgeDiscovery(logger logger.Service) ([][]*net.TCPAddr, error) {
|
||||
func edgeDiscovery(log *zerolog.Logger) ([][]*net.TCPAddr, error) {
|
||||
_, addrs, err := netLookupSRV(srvService, srvProto, srvName)
|
||||
if err != nil {
|
||||
_, fallbackAddrs, fallbackErr := fallbackLookupSRV(srvService, srvProto, srvName)
|
||||
if fallbackErr != nil || len(fallbackAddrs) == 0 {
|
||||
// use the original DNS error `err` in messages, not `fallbackErr`
|
||||
logger.Errorf("Error looking up Cloudflare edge IPs: the DNS query failed: %s", err)
|
||||
log.Error().Msgf("Error looking up Cloudflare edge IPs: the DNS query failed: %s", err)
|
||||
for _, s := range friendlyDNSErrorLines {
|
||||
logger.Error(s)
|
||||
log.Error().Msg(s)
|
||||
}
|
||||
return nil, errors.Wrapf(err, "Could not lookup srv records on _%v._%v.%v", srvService, srvProto, srvName)
|
||||
}
|
||||
|
|
@ -122,11 +122,11 @@ func resolveSRVToTCP(srv *net.SRV) ([]*net.TCPAddr, error) {
|
|||
|
||||
// ResolveAddrs resolves TCP address given a list of addresses. Address can be a hostname, however, it will return at most one
|
||||
// of the hostname's IP addresses.
|
||||
func ResolveAddrs(addrs []string, logger logger.Service) (resolved []*net.TCPAddr) {
|
||||
func ResolveAddrs(addrs []string, log *zerolog.Logger) (resolved []*net.TCPAddr) {
|
||||
for _, addr := range addrs {
|
||||
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to resolve %s, err: %v", addr, err)
|
||||
log.Error().Msgf("Failed to resolve %s, err: %v", addr, err)
|
||||
} else {
|
||||
resolved = append(resolved, tcpAddr)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package allregions
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -19,8 +19,8 @@ func TestEdgeDiscovery(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
addrLists, err := edgeDiscovery(l)
|
||||
l := zerolog.Nop()
|
||||
addrLists, err := edgeDiscovery(&l)
|
||||
assert.NoError(t, err)
|
||||
actualAddrSet := map[string]bool{}
|
||||
for _, addrs := range addrLists {
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ func (r Region) GetUnusedIP(excluding *net.TCPAddr) *net.TCPAddr {
|
|||
// Use the address, assigning it to a proxy connection.
|
||||
func (r Region) Use(addr *net.TCPAddr, connID int) {
|
||||
if addr == nil {
|
||||
//logrus.Errorf("Attempted to use nil address for connection %d", connID)
|
||||
return
|
||||
}
|
||||
r.connFor[addr] = InUse(connID)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// Regions stores Cloudflare edge network IPs, partitioned into two regions.
|
||||
|
|
@ -19,8 +19,8 @@ type Regions struct {
|
|||
// ------------------------------------
|
||||
|
||||
// ResolveEdge resolves the Cloudflare edge, returning all regions discovered.
|
||||
func ResolveEdge(logger logger.Service) (*Regions, error) {
|
||||
addrLists, err := edgeDiscovery(logger)
|
||||
func ResolveEdge(log *zerolog.Logger) (*Regions, error) {
|
||||
addrLists, err := edgeDiscovery(log)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -35,8 +35,8 @@ func ResolveEdge(logger logger.Service) (*Regions, error) {
|
|||
|
||||
// StaticEdge creates a list of edge addresses from the list of hostnames.
|
||||
// Mainly used for testing connectivity.
|
||||
func StaticEdge(hostnames []string, logger logger.Service) (*Regions, error) {
|
||||
resolved := ResolveAddrs(hostnames, logger)
|
||||
func StaticEdge(hostnames []string, log *zerolog.Logger) (*Regions, error) {
|
||||
resolved := ResolveAddrs(hostnames, log)
|
||||
if len(resolved) == 0 {
|
||||
return nil, fmt.Errorf("failed to resolve any edge address")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/cloudflare/cloudflared/edgediscovery/allregions"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -19,7 +19,7 @@ var errNoAddressesLeft = fmt.Errorf("There are no free edge addresses left")
|
|||
type Edge struct {
|
||||
regions *allregions.Regions
|
||||
sync.Mutex
|
||||
logger logger.Service
|
||||
log *zerolog.Logger
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
|
|
@ -28,34 +28,34 @@ type Edge struct {
|
|||
|
||||
// ResolveEdge runs the initial discovery of the Cloudflare edge, finding Addrs that can be allocated
|
||||
// to connections.
|
||||
func ResolveEdge(l logger.Service) (*Edge, error) {
|
||||
regions, err := allregions.ResolveEdge(l)
|
||||
func ResolveEdge(log *zerolog.Logger) (*Edge, error) {
|
||||
regions, err := allregions.ResolveEdge(log)
|
||||
if err != nil {
|
||||
return new(Edge), err
|
||||
}
|
||||
return &Edge{
|
||||
logger: l,
|
||||
log: log,
|
||||
regions: regions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// StaticEdge creates a list of edge addresses from the list of hostnames. Mainly used for testing connectivity.
|
||||
func StaticEdge(l logger.Service, hostnames []string) (*Edge, error) {
|
||||
regions, err := allregions.StaticEdge(hostnames, l)
|
||||
func StaticEdge(log *zerolog.Logger, hostnames []string) (*Edge, error) {
|
||||
regions, err := allregions.StaticEdge(hostnames, log)
|
||||
if err != nil {
|
||||
return new(Edge), err
|
||||
}
|
||||
return &Edge{
|
||||
logger: l,
|
||||
log: log,
|
||||
regions: regions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MockEdge creates a Cloudflare Edge from arbitrary TCP addresses. Used for testing.
|
||||
func MockEdge(l logger.Service, addrs []*net.TCPAddr) *Edge {
|
||||
func MockEdge(log *zerolog.Logger, addrs []*net.TCPAddr) *Edge {
|
||||
regions := allregions.NewNoResolve(addrs)
|
||||
return &Edge{
|
||||
logger: l,
|
||||
log: log,
|
||||
regions: regions,
|
||||
}
|
||||
}
|
||||
|
|
@ -82,17 +82,17 @@ func (ed *Edge) GetAddr(connID int) (*net.TCPAddr, error) {
|
|||
|
||||
// If this connection has already used an edge addr, return it.
|
||||
if addr := ed.regions.AddrUsedBy(connID); addr != nil {
|
||||
ed.logger.Debugf("edgediscovery - GetAddr: Returning same address back to proxy connection: connID: %d", connID)
|
||||
ed.log.Debug().Msgf("edgediscovery - GetAddr: Returning same address back to proxy connection: connID: %d", connID)
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
// Otherwise, give it an unused one
|
||||
addr := ed.regions.GetUnusedAddr(nil, connID)
|
||||
if addr == nil {
|
||||
ed.logger.Debugf("edgediscovery - GetAddr: No addresses left to give proxy connection: connID: %d", connID)
|
||||
ed.log.Debug().Msgf("edgediscovery - GetAddr: No addresses left to give proxy connection: connID: %d", connID)
|
||||
return nil, errNoAddressesLeft
|
||||
}
|
||||
ed.logger.Debugf("edgediscovery - GetAddr: Giving connection its new address %s: connID: %d", addr, connID)
|
||||
ed.log.Debug().Msgf("edgediscovery - GetAddr: Giving connection its new address %s: connID: %d", addr, connID)
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
|
|
@ -107,11 +107,11 @@ func (ed *Edge) GetDifferentAddr(connID int) (*net.TCPAddr, error) {
|
|||
}
|
||||
addr := ed.regions.GetUnusedAddr(oldAddr, connID)
|
||||
if addr == nil {
|
||||
ed.logger.Debugf("edgediscovery - GetDifferentAddr: No addresses left to give proxy connection: connID: %d", connID)
|
||||
ed.log.Debug().Msgf("edgediscovery - GetDifferentAddr: No addresses left to give proxy connection: connID: %d", connID)
|
||||
// note: if oldAddr were not nil, it will become available on the next iteration
|
||||
return nil, errNoAddressesLeft
|
||||
}
|
||||
ed.logger.Debugf("edgediscovery - GetDifferentAddr: Giving connection its new address %s: connID: %d", addr, connID)
|
||||
ed.log.Debug().Msgf("edgediscovery - GetDifferentAddr: Giving connection its new address %s: connID: %d", addr, connID)
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +127,6 @@ func (ed *Edge) AvailableAddrs() int {
|
|||
func (ed *Edge) GiveBack(addr *net.TCPAddr) bool {
|
||||
ed.Lock()
|
||||
defer ed.Unlock()
|
||||
ed.logger.Debug("edgediscovery - GiveBack: Address now unused")
|
||||
ed.log.Debug().Msg("edgediscovery - GiveBack: Address now unused")
|
||||
return ed.regions.GiveBack(addr)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -29,11 +29,12 @@ var (
|
|||
Port: 8000,
|
||||
Zone: "",
|
||||
}
|
||||
|
||||
log = zerolog.Nop()
|
||||
)
|
||||
|
||||
func TestGiveBack(t *testing.T) {
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
edge := MockEdge(l, []*net.TCPAddr{&addr0, &addr1, &addr2, &addr3})
|
||||
edge := MockEdge(&log, []*net.TCPAddr{&addr0, &addr1, &addr2, &addr3})
|
||||
|
||||
// Give this connection an address
|
||||
assert.Equal(t, 4, edge.AvailableAddrs())
|
||||
|
|
@ -49,10 +50,8 @@ func TestGiveBack(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRPCAndProxyShareSingleEdgeIP(t *testing.T) {
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
|
||||
// Make an edge with a single IP
|
||||
edge := MockEdge(l, []*net.TCPAddr{&addr0})
|
||||
edge := MockEdge(&log, []*net.TCPAddr{&addr0})
|
||||
tunnelConnID := 0
|
||||
|
||||
// Use the IP for a tunnel
|
||||
|
|
@ -66,8 +65,7 @@ func TestRPCAndProxyShareSingleEdgeIP(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetAddrForRPC(t *testing.T) {
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
edge := MockEdge(l, []*net.TCPAddr{&addr0, &addr1, &addr2, &addr3})
|
||||
edge := MockEdge(&log, []*net.TCPAddr{&addr0, &addr1, &addr2, &addr3})
|
||||
|
||||
// Get a connection
|
||||
assert.Equal(t, 4, edge.AvailableAddrs())
|
||||
|
|
@ -84,10 +82,8 @@ func TestGetAddrForRPC(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestOnePerRegion(t *testing.T) {
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
|
||||
// Make an edge with only one address
|
||||
edge := MockEdge(l, []*net.TCPAddr{&addr0, &addr1})
|
||||
edge := MockEdge(&log, []*net.TCPAddr{&addr0, &addr1})
|
||||
|
||||
// Use the only address
|
||||
const connID = 0
|
||||
|
|
@ -108,10 +104,8 @@ func TestOnePerRegion(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestOnlyOneAddrLeft(t *testing.T) {
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
|
||||
// Make an edge with only one address
|
||||
edge := MockEdge(l, []*net.TCPAddr{&addr0})
|
||||
edge := MockEdge(&log, []*net.TCPAddr{&addr0})
|
||||
|
||||
// Use the only address
|
||||
const connID = 0
|
||||
|
|
@ -130,10 +124,8 @@ func TestOnlyOneAddrLeft(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNoAddrsLeft(t *testing.T) {
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
|
||||
// Make an edge with no addresses
|
||||
edge := MockEdge(l, []*net.TCPAddr{})
|
||||
edge := MockEdge(&log, []*net.TCPAddr{})
|
||||
|
||||
_, err := edge.GetAddr(2)
|
||||
assert.Error(t, err)
|
||||
|
|
@ -142,8 +134,7 @@ func TestNoAddrsLeft(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetAddr(t *testing.T) {
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
edge := MockEdge(l, []*net.TCPAddr{&addr0, &addr1, &addr2, &addr3})
|
||||
edge := MockEdge(&log, []*net.TCPAddr{&addr0, &addr1, &addr2, &addr3})
|
||||
|
||||
// Give this connection an address
|
||||
const connID = 0
|
||||
|
|
@ -158,8 +149,7 @@ func TestGetAddr(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetDifferentAddr(t *testing.T) {
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
edge := MockEdge(l, []*net.TCPAddr{&addr0, &addr1, &addr2, &addr3})
|
||||
edge := MockEdge(&log, []*net.TCPAddr{&addr0, &addr1, &addr2, &addr3})
|
||||
|
||||
// Give this connection an address
|
||||
assert.Equal(t, 4, edge.AvailableAddrs())
|
||||
|
|
|
|||
1
go.mod
1
go.mod
|
|
@ -50,6 +50,7 @@ require (
|
|||
github.com/prometheus/client_golang v1.7.1
|
||||
github.com/prometheus/common v0.13.0 // indirect
|
||||
github.com/rivo/tview v0.0.0-20200712113419-c65badfc3d92
|
||||
github.com/rs/zerolog v1.20.0
|
||||
github.com/stretchr/testify v1.6.0
|
||||
github.com/urfave/cli/v2 v2.2.0
|
||||
github.com/xo/dburl v0.0.0-20191005012637-293c3298d6c0
|
||||
|
|
|
|||
5
go.sum
5
go.sum
|
|
@ -143,6 +143,7 @@ github.com/coreos/go-oidc v0.0.0-20171002155002-a93f71fdfe73 h1:7CNPV0LWRCa1FNmq
|
|||
github.com/coreos/go-oidc v0.0.0-20171002155002-a93f71fdfe73/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||
|
|
@ -565,6 +566,9 @@ github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
|
|||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs=
|
||||
github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
|
||||
github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4 h1:S9YlS71UNJIyS61OqGAmLXv3w5zclSidN+qwr80XxKs=
|
||||
github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
|
|
@ -837,6 +841,7 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw
|
|||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
|
|
|
|||
|
|
@ -8,11 +8,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/rs/zerolog"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -50,7 +49,7 @@ type MuxerConfig struct {
|
|||
// The minimum number of heartbeats to send before terminating the connection.
|
||||
MaxHeartbeats uint64
|
||||
// Logger to use
|
||||
Logger logger.Service
|
||||
Log *zerolog.Logger
|
||||
CompressionQuality CompressionSetting
|
||||
// Initial size for HTTP2 flow control windows
|
||||
DefaultWindowSize uint32
|
||||
|
|
@ -138,10 +137,10 @@ func Handshake(
|
|||
handshakeSetting := http2.Setting{ID: SettingMuxerMagic, Val: MuxerMagicEdge}
|
||||
compressionSetting := http2.Setting{ID: SettingCompression, Val: config.CompressionQuality.toH2Setting()}
|
||||
if CompressionIsSupported() {
|
||||
config.Logger.Debug("muxer: Compression is supported")
|
||||
config.Log.Debug().Msg("muxer: Compression is supported")
|
||||
m.compressionQuality = config.CompressionQuality.getPreset()
|
||||
} else {
|
||||
config.Logger.Debug("muxer: Compression is not supported")
|
||||
config.Log.Debug().Msg("muxer: Compression is not supported")
|
||||
compressionSetting = http2.Setting{ID: SettingCompression, Val: 0}
|
||||
}
|
||||
|
||||
|
|
@ -178,12 +177,12 @@ func Handshake(
|
|||
// Sanity check to enusre idelDuration is sane
|
||||
if idleDuration == 0 || idleDuration < defaultTimeout {
|
||||
idleDuration = defaultTimeout
|
||||
config.Logger.Infof("muxer: Minimum idle time has been adjusted to %d", defaultTimeout)
|
||||
config.Log.Info().Msgf("muxer: Minimum idle time has been adjusted to %d", defaultTimeout)
|
||||
}
|
||||
maxRetries := config.MaxHeartbeats
|
||||
if maxRetries == 0 {
|
||||
maxRetries = defaultRetries
|
||||
config.Logger.Infof("muxer: Minimum number of unacked heartbeats to send before closing the connection has been adjusted to %d", maxRetries)
|
||||
config.Log.Info().Msgf("muxer: Minimum number of unacked heartbeats to send before closing the connection has been adjusted to %d", maxRetries)
|
||||
}
|
||||
|
||||
compBytesBefore, compBytesAfter := NewAtomicCounter(0), NewAtomicCounter(0)
|
||||
|
|
@ -325,7 +324,7 @@ func (m *Muxer) Serve(ctx context.Context) error {
|
|||
errGroup.Go(func() error {
|
||||
ch := make(chan error)
|
||||
go func() {
|
||||
err := m.muxReader.run(m.config.Logger)
|
||||
err := m.muxReader.run(m.config.Log)
|
||||
m.explicitShutdown.Fuse(false)
|
||||
m.r.Close()
|
||||
m.abort()
|
||||
|
|
@ -346,7 +345,7 @@ func (m *Muxer) Serve(ctx context.Context) error {
|
|||
errGroup.Go(func() error {
|
||||
ch := make(chan error)
|
||||
go func() {
|
||||
err := m.muxWriter.run(m.config.Logger)
|
||||
err := m.muxWriter.run(m.config.Log)
|
||||
m.explicitShutdown.Fuse(false)
|
||||
m.w.Close()
|
||||
m.abort()
|
||||
|
|
@ -367,7 +366,7 @@ func (m *Muxer) Serve(ctx context.Context) error {
|
|||
errGroup.Go(func() error {
|
||||
ch := make(chan error)
|
||||
go func() {
|
||||
err := m.muxMetricsUpdater.run(m.config.Logger)
|
||||
err := m.muxMetricsUpdater.run(m.config.Log)
|
||||
// don't block if parent goroutine quit early
|
||||
select {
|
||||
case ch <- err:
|
||||
|
|
|
|||
|
|
@ -16,10 +16,9 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -27,6 +26,8 @@ const (
|
|||
testHandshakeTimeout = time.Millisecond * 1000
|
||||
)
|
||||
|
||||
var log = zerolog.Nop()
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
if os.Getenv("VERBOSE") == "1" {
|
||||
//TODO: set log level
|
||||
|
|
@ -52,7 +53,7 @@ func NewDefaultMuxerPair(t assert.TestingT, testName string, f MuxedStreamFunc)
|
|||
Handler: f,
|
||||
IsClient: true,
|
||||
Name: "origin",
|
||||
Logger: logger.NewOutputWriter(logger.NewMockWriteManager()),
|
||||
Log: &log,
|
||||
DefaultWindowSize: (1 << 8) - 1,
|
||||
MaxWindowSize: (1 << 15) - 1,
|
||||
StreamWriteBufferMaxLen: 1024,
|
||||
|
|
@ -64,7 +65,7 @@ func NewDefaultMuxerPair(t assert.TestingT, testName string, f MuxedStreamFunc)
|
|||
Timeout: testHandshakeTimeout,
|
||||
IsClient: false,
|
||||
Name: "edge",
|
||||
Logger: logger.NewOutputWriter(logger.NewMockWriteManager()),
|
||||
Log: &log,
|
||||
DefaultWindowSize: (1 << 8) - 1,
|
||||
MaxWindowSize: (1 << 15) - 1,
|
||||
StreamWriteBufferMaxLen: 1024,
|
||||
|
|
@ -87,7 +88,7 @@ func NewCompressedMuxerPair(t assert.TestingT, testName string, quality Compress
|
|||
IsClient: true,
|
||||
Name: "origin",
|
||||
CompressionQuality: quality,
|
||||
Logger: logger.NewOutputWriter(logger.NewMockWriteManager()),
|
||||
Log: &log,
|
||||
HeartbeatInterval: defaultTimeout,
|
||||
MaxHeartbeats: defaultRetries,
|
||||
},
|
||||
|
|
@ -97,7 +98,7 @@ func NewCompressedMuxerPair(t assert.TestingT, testName string, quality Compress
|
|||
IsClient: false,
|
||||
Name: "edge",
|
||||
CompressionQuality: quality,
|
||||
Logger: logger.NewOutputWriter(logger.NewMockWriteManager()),
|
||||
Log: &log,
|
||||
HeartbeatInterval: defaultTimeout,
|
||||
MaxHeartbeats: defaultRetries,
|
||||
},
|
||||
|
|
@ -186,11 +187,11 @@ func TestSingleStream(t *testing.T) {
|
|||
if stream.Headers[0].Value != "headerValue" {
|
||||
t.Fatalf("expected header value %s, got %s", "headerValue", stream.Headers[0].Value)
|
||||
}
|
||||
stream.WriteHeaders([]Header{
|
||||
_ = stream.WriteHeaders([]Header{
|
||||
{Name: "response-header", Value: "responseValue"},
|
||||
})
|
||||
buf := []byte("Hello world")
|
||||
stream.Write(buf)
|
||||
_, _ = stream.Write(buf)
|
||||
n, err := io.ReadFull(stream, buf)
|
||||
if n > 0 {
|
||||
t.Fatalf("read %d bytes after EOF", n)
|
||||
|
|
@ -230,7 +231,7 @@ func TestSingleStream(t *testing.T) {
|
|||
if string(responseBody) != "Hello world" {
|
||||
t.Fatalf("expected response body %s, got %s", "Hello world", responseBody)
|
||||
}
|
||||
stream.Close()
|
||||
_ = stream.Close()
|
||||
n, err = stream.Write([]byte("aaaaa"))
|
||||
if n > 0 {
|
||||
t.Fatalf("wrote %d bytes after EOF", n)
|
||||
|
|
@ -252,7 +253,7 @@ func TestSingleStreamLargeResponseBody(t *testing.T) {
|
|||
if stream.Headers[0].Value != "headerValue" {
|
||||
t.Fatalf("expected header value %s, got %s", "headerValue", stream.Headers[0].Value)
|
||||
}
|
||||
stream.WriteHeaders([]Header{
|
||||
_ = stream.WriteHeaders([]Header{
|
||||
{Name: "response-header", Value: "responseValue"},
|
||||
})
|
||||
payload := make([]byte, bodySize)
|
||||
|
|
@ -302,7 +303,6 @@ func TestSingleStreamLargeResponseBody(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMultipleStreams(t *testing.T) {
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
f := MuxedStreamFunc(func(stream *MuxedStream) error {
|
||||
if len(stream.Headers) != 1 {
|
||||
t.Fatalf("expected %d headers, got %d", 1, len(stream.Headers))
|
||||
|
|
@ -310,13 +310,13 @@ func TestMultipleStreams(t *testing.T) {
|
|||
if stream.Headers[0].Name != "client-token" {
|
||||
t.Fatalf("expected header name %s, got %s", "client-token", stream.Headers[0].Name)
|
||||
}
|
||||
l.Debugf("Got request for stream %s", stream.Headers[0].Value)
|
||||
stream.WriteHeaders([]Header{
|
||||
log.Debug().Msgf("Got request for stream %s", stream.Headers[0].Value)
|
||||
_ = stream.WriteHeaders([]Header{
|
||||
{Name: "response-token", Value: stream.Headers[0].Value},
|
||||
})
|
||||
l.Debugf("Wrote headers for stream %s", stream.Headers[0].Value)
|
||||
stream.Write([]byte("OK"))
|
||||
l.Debugf("Wrote body for stream %s", stream.Headers[0].Value)
|
||||
log.Debug().Msgf("Wrote headers for stream %s", stream.Headers[0].Value)
|
||||
_, _ = stream.Write([]byte("OK"))
|
||||
log.Debug().Msgf("Wrote body for stream %s", stream.Headers[0].Value)
|
||||
return nil
|
||||
})
|
||||
muxPair := NewDefaultMuxerPair(t, t.Name(), f)
|
||||
|
|
@ -334,7 +334,7 @@ func TestMultipleStreams(t *testing.T) {
|
|||
[]Header{{Name: "client-token", Value: tokenString}},
|
||||
nil,
|
||||
)
|
||||
l.Debugf("Got headers for stream %d", tokenId)
|
||||
log.Debug().Msgf("Got headers for stream %d", tokenId)
|
||||
if err != nil {
|
||||
errorsC <- err
|
||||
return
|
||||
|
|
@ -372,7 +372,7 @@ func TestMultipleStreams(t *testing.T) {
|
|||
testFail := false
|
||||
for err := range errorsC {
|
||||
testFail = true
|
||||
l.Errorf("%s", err)
|
||||
log.Error().Msgf("%s", err)
|
||||
}
|
||||
if testFail {
|
||||
t.Fatalf("TestMultipleStreams failed")
|
||||
|
|
@ -396,7 +396,7 @@ func TestMultipleStreamsFlowControl(t *testing.T) {
|
|||
if stream.Headers[0].Value != "headerValue" {
|
||||
t.Fatalf("expected header value %s, got %s", "headerValue", stream.Headers[0].Value)
|
||||
}
|
||||
stream.WriteHeaders([]Header{
|
||||
_ = stream.WriteHeaders([]Header{
|
||||
{Name: "response-header", Value: "responseValue"},
|
||||
})
|
||||
payload := make([]byte, responseSizes[(stream.streamID-2)/2])
|
||||
|
|
@ -450,27 +450,25 @@ func TestMultipleStreamsFlowControl(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGracefulShutdown(t *testing.T) {
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
|
||||
sendC := make(chan struct{})
|
||||
responseBuf := bytes.Repeat([]byte("Hello world"), 65536)
|
||||
|
||||
f := MuxedStreamFunc(func(stream *MuxedStream) error {
|
||||
stream.WriteHeaders([]Header{
|
||||
_ = stream.WriteHeaders([]Header{
|
||||
{Name: "response-header", Value: "responseValue"},
|
||||
})
|
||||
<-sendC
|
||||
l.Debugf("Writing %d bytes", len(responseBuf))
|
||||
stream.Write(responseBuf)
|
||||
stream.CloseWrite()
|
||||
l.Debugf("Wrote %d bytes", len(responseBuf))
|
||||
log.Debug().Msgf("Writing %d bytes", len(responseBuf))
|
||||
_, _ = stream.Write(responseBuf)
|
||||
_ = stream.CloseWrite()
|
||||
log.Debug().Msgf("Wrote %d bytes", len(responseBuf))
|
||||
// Reading from the stream will block until the edge closes its end of the stream.
|
||||
// Otherwise, we'll close the whole connection before receiving the 'stream closed'
|
||||
// message from the edge.
|
||||
// Graceful shutdown works if you omit this, it just gives spurious errors for now -
|
||||
// TODO ignore errors when writing 'stream closed' and we're shutting down.
|
||||
stream.Read([]byte{0})
|
||||
l.Debugf("Handler ends")
|
||||
_, _ = stream.Read([]byte{0})
|
||||
log.Debug().Msgf("Handler ends")
|
||||
return nil
|
||||
})
|
||||
muxPair := NewDefaultMuxerPair(t, t.Name(), f)
|
||||
|
|
@ -487,7 +485,7 @@ func TestGracefulShutdown(t *testing.T) {
|
|||
muxPair.EdgeMux.Shutdown()
|
||||
close(sendC)
|
||||
responseBody := make([]byte, len(responseBuf))
|
||||
l.Debugf("Waiting for %d bytes", len(responseBuf))
|
||||
log.Debug().Msgf("Waiting for %d bytes", len(responseBuf))
|
||||
n, err := io.ReadFull(stream, responseBody)
|
||||
if err != nil {
|
||||
t.Fatalf("error from (*MuxedStream).Read with %d bytes read: %s", n, err)
|
||||
|
|
@ -498,7 +496,7 @@ func TestGracefulShutdown(t *testing.T) {
|
|||
if !bytes.Equal(responseBuf, responseBody) {
|
||||
t.Fatalf("response body mismatch")
|
||||
}
|
||||
stream.Close()
|
||||
_ = stream.Close()
|
||||
muxPair.Wait(t)
|
||||
}
|
||||
|
||||
|
|
@ -509,7 +507,7 @@ func TestUnexpectedShutdown(t *testing.T) {
|
|||
|
||||
f := MuxedStreamFunc(func(stream *MuxedStream) error {
|
||||
defer close(handlerFinishC)
|
||||
stream.WriteHeaders([]Header{
|
||||
_ = stream.WriteHeaders([]Header{
|
||||
{Name: "response-header", Value: "responseValue"},
|
||||
})
|
||||
<-sendC
|
||||
|
|
@ -536,7 +534,7 @@ func TestUnexpectedShutdown(t *testing.T) {
|
|||
nil,
|
||||
)
|
||||
// Close the underlying connection before telling the origin to write.
|
||||
muxPair.EdgeConn.Close()
|
||||
_ = muxPair.EdgeConn.Close()
|
||||
close(sendC)
|
||||
if err != nil {
|
||||
t.Fatalf("error in OpenStream: %s", err)
|
||||
|
|
@ -559,18 +557,18 @@ func TestUnexpectedShutdown(t *testing.T) {
|
|||
|
||||
func EchoHandler(stream *MuxedStream) error {
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "Hello, world!\n\n# REQUEST HEADERS:\n\n")
|
||||
_, _ = fmt.Fprintf(&buf, "Hello, world!\n\n# REQUEST HEADERS:\n\n")
|
||||
for _, header := range stream.Headers {
|
||||
fmt.Fprintf(&buf, "[%s] = %s\n", header.Name, header.Value)
|
||||
_, _ = fmt.Fprintf(&buf, "[%s] = %s\n", header.Name, header.Value)
|
||||
}
|
||||
stream.WriteHeaders([]Header{
|
||||
_ = stream.WriteHeaders([]Header{
|
||||
{Name: ":status", Value: "200"},
|
||||
{Name: "server", Value: "Echo-server/1.0"},
|
||||
{Name: "date", Value: time.Now().Format(time.RFC850)},
|
||||
{Name: "content-type", Value: "text/html; charset=utf-8"},
|
||||
{Name: "content-length", Value: strconv.Itoa(buf.Len())},
|
||||
})
|
||||
buf.WriteTo(stream)
|
||||
_, _ = buf.WriteTo(stream)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -582,14 +580,14 @@ func TestOpenAfterDisconnect(t *testing.T) {
|
|||
switch i {
|
||||
case 0:
|
||||
// Close both directions of the connection to cause EOF on both peers.
|
||||
muxPair.OriginConn.Close()
|
||||
muxPair.EdgeConn.Close()
|
||||
_ = muxPair.OriginConn.Close()
|
||||
_ = muxPair.EdgeConn.Close()
|
||||
case 1:
|
||||
// Close origin conn to cause EOF on origin first.
|
||||
muxPair.OriginConn.Close()
|
||||
_ = muxPair.OriginConn.Close()
|
||||
case 2:
|
||||
// Close edge conn to cause EOF on edge first.
|
||||
muxPair.EdgeConn.Close()
|
||||
_ = muxPair.EdgeConn.Close()
|
||||
}
|
||||
|
||||
_, err := muxPair.OpenEdgeMuxStream(
|
||||
|
|
@ -617,7 +615,7 @@ func TestHPACK(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("error in OpenStream: %s", err)
|
||||
}
|
||||
stream.Close()
|
||||
_ = stream.Close()
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
stream, err := muxPair.OpenEdgeMuxStream(
|
||||
|
|
@ -654,8 +652,8 @@ func TestHPACK(t *testing.T) {
|
|||
if stream.Headers[0].Value != "200" {
|
||||
t.Fatalf("expected status 200, got %s", stream.Headers[0].Value)
|
||||
}
|
||||
ioutil.ReadAll(stream)
|
||||
stream.Close()
|
||||
_, _ = ioutil.ReadAll(stream)
|
||||
_ = stream.Close()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -680,7 +678,7 @@ func AssertIfPipeReadable(t *testing.T, pipe io.ReadCloser) {
|
|||
}
|
||||
|
||||
func TestMultipleStreamsWithDictionaries(t *testing.T) {
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
l := zerolog.Nop()
|
||||
|
||||
for q := CompressionNone; q <= CompressionMax; q++ {
|
||||
htmlBody := `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"` +
|
||||
|
|
@ -730,10 +728,10 @@ func TestMultipleStreamsWithDictionaries(t *testing.T) {
|
|||
contentType = "img/gif"
|
||||
}
|
||||
|
||||
stream.WriteHeaders([]Header{
|
||||
Header{Name: "content-type", Value: contentType},
|
||||
_ = stream.WriteHeaders([]Header{
|
||||
{Name: "content-type", Value: contentType},
|
||||
})
|
||||
stream.Write([]byte(strings.Replace(htmlBody, "paragraph", pathHeader.Value, 1) + stream.Headers[5].Value))
|
||||
_, _ = stream.Write([]byte(strings.Replace(htmlBody, "paragraph", pathHeader.Value, 1) + stream.Headers[5].Value))
|
||||
|
||||
return nil
|
||||
})
|
||||
|
|
@ -817,7 +815,7 @@ func TestMultipleStreamsWithDictionaries(t *testing.T) {
|
|||
testFail := false
|
||||
for err := range errorsC {
|
||||
testFail = true
|
||||
l.Errorf("%s", err)
|
||||
l.Error().Msgf("%s", err)
|
||||
}
|
||||
if testFail {
|
||||
t.Fatalf("TestMultipleStreams failed")
|
||||
|
|
@ -831,8 +829,6 @@ func TestMultipleStreamsWithDictionaries(t *testing.T) {
|
|||
}
|
||||
|
||||
func sampleSiteHandler(files map[string][]byte) MuxedStreamFunc {
|
||||
l := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
|
||||
return func(stream *MuxedStream) error {
|
||||
var contentType string
|
||||
var pathHeader Header
|
||||
|
|
@ -857,16 +853,16 @@ func sampleSiteHandler(files map[string][]byte) MuxedStreamFunc {
|
|||
} else {
|
||||
contentType = "img/gif"
|
||||
}
|
||||
stream.WriteHeaders([]Header{
|
||||
Header{Name: "content-type", Value: contentType},
|
||||
_ = stream.WriteHeaders([]Header{
|
||||
{Name: "content-type", Value: contentType},
|
||||
})
|
||||
l.Debugf("Wrote headers for stream %s", pathHeader.Value)
|
||||
log.Debug().Msgf("Wrote headers for stream %s", pathHeader.Value)
|
||||
file, ok := files[pathHeader.Value]
|
||||
if !ok {
|
||||
return fmt.Errorf("%s content is not preloaded", pathHeader.Value)
|
||||
}
|
||||
stream.Write(file)
|
||||
l.Debugf("Wrote body for stream %s", pathHeader.Value)
|
||||
_, _ = stream.Write(file)
|
||||
log.Debug().Msgf("Wrote body for stream %s", pathHeader.Value)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
@ -1008,7 +1004,7 @@ func BenchmarkOpenStream(b *testing.B) {
|
|||
if stream.Headers[0].Value != "headerValue" {
|
||||
b.Fatalf("expected header value %s, got %s", "headerValue", stream.Headers[0].Value)
|
||||
}
|
||||
stream.WriteHeaders([]Header{
|
||||
_ = stream.WriteHeaders([]Header{
|
||||
{Name: "response-header", Value: "responseValue"},
|
||||
})
|
||||
return nil
|
||||
|
|
@ -1058,7 +1054,7 @@ func BenchmarkSingleStreamLargeResponseBody(b *testing.B) {
|
|||
if stream.Headers[0].Value != "headerValue" {
|
||||
b.Fatalf("expected header value %s, got %s", "headerValue", stream.Headers[0].Value)
|
||||
}
|
||||
stream.WriteHeaders([]Header{
|
||||
_ = stream.WriteHeaders([]Header{
|
||||
{Name: "response-header", Value: "responseValue"},
|
||||
})
|
||||
for i := 0; i < writeN; i++ {
|
||||
|
|
@ -1083,7 +1079,7 @@ func BenchmarkSingleStreamLargeResponseBody(b *testing.B) {
|
|||
Handler: f,
|
||||
IsClient: true,
|
||||
Name: "origin",
|
||||
Logger: logger.NewOutputWriter(logger.NewMockWriteManager()),
|
||||
Log: &log,
|
||||
DefaultWindowSize: defaultWindowSize,
|
||||
MaxWindowSize: maxWindowSize,
|
||||
StreamWriteBufferMaxLen: defaultWriteBufferMaxLen,
|
||||
|
|
@ -1095,7 +1091,7 @@ func BenchmarkSingleStreamLargeResponseBody(b *testing.B) {
|
|||
Timeout: testHandshakeTimeout,
|
||||
IsClient: false,
|
||||
Name: "edge",
|
||||
Logger: logger.NewOutputWriter(logger.NewMockWriteManager()),
|
||||
Log: &log,
|
||||
DefaultWindowSize: defaultWindowSize,
|
||||
MaxWindowSize: maxWindowSize,
|
||||
StreamWriteBufferMaxLen: defaultWriteBufferMaxLen,
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/golang-collections/collections/queue"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// data points used to compute average receive window and send window size
|
||||
|
|
@ -20,7 +20,7 @@ type muxMetricsUpdater interface {
|
|||
// metrics returns the latest metrics
|
||||
metrics() *MuxerMetrics
|
||||
// run is a blocking call to start the event loop
|
||||
run(logger logger.Service) error
|
||||
run(log *zerolog.Logger) error
|
||||
// updateRTTChan is called by muxReader to report new RTT measurements
|
||||
updateRTT(rtt *roundTripMeasurement)
|
||||
//updateReceiveWindowChan is called by muxReader and muxWriter when receiveWindow size is updated
|
||||
|
|
@ -137,30 +137,30 @@ func (updater *muxMetricsUpdaterImpl) metrics() *MuxerMetrics {
|
|||
return m
|
||||
}
|
||||
|
||||
func (updater *muxMetricsUpdaterImpl) run(logger logger.Service) error {
|
||||
defer logger.Debug("mux - metrics: event loop finished")
|
||||
func (updater *muxMetricsUpdaterImpl) run(log *zerolog.Logger) error {
|
||||
defer log.Debug().Msg("mux - metrics: event loop finished")
|
||||
for {
|
||||
select {
|
||||
case <-updater.abortChan:
|
||||
logger.Infof("mux - metrics: Stopping mux metrics updater")
|
||||
log.Info().Msgf("mux - metrics: Stopping mux metrics updater")
|
||||
return nil
|
||||
case roundTripMeasurement := <-updater.updateRTTChan:
|
||||
go updater.rttData.update(roundTripMeasurement)
|
||||
logger.Debug("mux - metrics: Update rtt")
|
||||
log.Debug().Msg("mux - metrics: Update rtt")
|
||||
case receiveWindow := <-updater.updateReceiveWindowChan:
|
||||
go updater.receiveWindowData.update(receiveWindow)
|
||||
logger.Debug("mux - metrics: Update receive window")
|
||||
log.Debug().Msg("mux - metrics: Update receive window")
|
||||
case sendWindow := <-updater.updateSendWindowChan:
|
||||
go updater.sendWindowData.update(sendWindow)
|
||||
logger.Debug("mux - metrics: Update send window")
|
||||
log.Debug().Msg("mux - metrics: Update send window")
|
||||
case inBoundBytes := <-updater.updateInBoundBytesChan:
|
||||
// inBoundBytes is bytes/sec because the update interval is 1 sec
|
||||
go updater.inBoundRate.update(inBoundBytes)
|
||||
logger.Debugf("mux - metrics: Inbound bytes %d", inBoundBytes)
|
||||
log.Debug().Msgf("mux - metrics: Inbound bytes %d", inBoundBytes)
|
||||
case outBoundBytes := <-updater.updateOutBoundBytesChan:
|
||||
// outBoundBytes is bytes/sec because the update interval is 1 sec
|
||||
go updater.outBoundRate.update(outBoundBytes)
|
||||
logger.Debugf("mux - metrics: Outbound bytes %d", outBoundBytes)
|
||||
log.Debug().Msgf("mux - metrics: Outbound bytes %d", outBoundBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -91,10 +91,10 @@ func TestMuxMetricsUpdater(t *testing.T) {
|
|||
abortChan := make(chan struct{})
|
||||
compBefore, compAfter := NewAtomicCounter(0), NewAtomicCounter(0)
|
||||
m := newMuxMetricsUpdater(abortChan, compBefore, compAfter)
|
||||
logger := logger.NewOutputWriter(logger.NewMockWriteManager())
|
||||
log := zerolog.Nop()
|
||||
|
||||
go func() {
|
||||
errChan <- m.run(logger)
|
||||
errChan <- m.run(&log)
|
||||
}()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/rs/zerolog"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
|
|
@ -68,8 +68,8 @@ func (r *MuxReader) Shutdown() <-chan struct{} {
|
|||
return done
|
||||
}
|
||||
|
||||
func (r *MuxReader) run(logger logger.Service) error {
|
||||
defer logger.Debug("mux - read: event loop finished")
|
||||
func (r *MuxReader) run(log *zerolog.Logger) error {
|
||||
defer log.Debug().Msg("mux - read: event loop finished")
|
||||
|
||||
// routine to periodically update bytesRead
|
||||
go func() {
|
||||
|
|
@ -93,7 +93,7 @@ func (r *MuxReader) run(logger logger.Service) error {
|
|||
}
|
||||
switch e := err.(type) {
|
||||
case http2.StreamError:
|
||||
logger.Infof("%s: stream error", errorString)
|
||||
log.Info().Msgf("%s: stream error", errorString)
|
||||
// Ideally we wouldn't return here, since that aborts the muxer.
|
||||
// We should communicate the error to the relevant MuxedStream
|
||||
// data structure, so that callers of MuxedStream.Read() and
|
||||
|
|
@ -101,28 +101,28 @@ func (r *MuxReader) run(logger logger.Service) error {
|
|||
// and keep the muxer going.
|
||||
return r.streamError(e.StreamID, e.Code)
|
||||
case http2.ConnectionError:
|
||||
logger.Infof("%s: stream error", errorString)
|
||||
log.Info().Msgf("%s: stream error", errorString)
|
||||
return r.connectionError(err)
|
||||
default:
|
||||
if isConnectionClosedError(err) {
|
||||
if r.streams.Len() == 0 {
|
||||
// don't log the error here -- that would just be extra noise
|
||||
logger.Debug("mux - read: shutting down")
|
||||
log.Debug().Msg("mux - read: shutting down")
|
||||
return nil
|
||||
}
|
||||
logger.Infof("%s: connection closed unexpectedly", errorString)
|
||||
log.Info().Msgf("%s: connection closed unexpectedly", errorString)
|
||||
return err
|
||||
} else {
|
||||
logger.Infof("%s: frame read error", errorString)
|
||||
log.Info().Msgf("%s: frame read error", errorString)
|
||||
return r.connectionError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
r.connActive.Signal()
|
||||
logger.Debugf("mux - read: read frame: data %v", frame)
|
||||
log.Debug().Msgf("mux - read: read frame: data %v", frame)
|
||||
switch f := frame.(type) {
|
||||
case *http2.DataFrame:
|
||||
err = r.receiveFrameData(f, logger)
|
||||
err = r.receiveFrameData(f, log)
|
||||
case *http2.MetaHeadersFrame:
|
||||
err = r.receiveHeaderData(f)
|
||||
case *http2.RSTStreamFrame:
|
||||
|
|
@ -155,7 +155,7 @@ func (r *MuxReader) run(logger logger.Service) error {
|
|||
err = ErrUnexpectedFrameType
|
||||
}
|
||||
if err != nil {
|
||||
logger.Debugf("mux - read: read error: data %v", frame)
|
||||
log.Debug().Msgf("mux - read: read error: data %v", frame)
|
||||
return r.connectionError(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -276,7 +276,7 @@ func (r *MuxReader) handleStream(stream *MuxedStream) {
|
|||
}
|
||||
|
||||
// Receives a data frame from a stream. A non-nil error is a connection error.
|
||||
func (r *MuxReader) receiveFrameData(frame *http2.DataFrame, logger logger.Service) error {
|
||||
func (r *MuxReader) receiveFrameData(frame *http2.DataFrame, log *zerolog.Logger) error {
|
||||
stream, err := r.getStreamForFrame(frame)
|
||||
if err != nil {
|
||||
return r.defaultStreamErrorHandler(err, frame.Header())
|
||||
|
|
@ -292,9 +292,9 @@ func (r *MuxReader) receiveFrameData(frame *http2.DataFrame, logger logger.Servi
|
|||
if frame.Header().Flags.Has(http2.FlagDataEndStream) {
|
||||
if stream.receiveEOF() {
|
||||
r.streams.Delete(stream.streamID)
|
||||
logger.Debugf("mux - read: stream closed: streamID: %d", frame.Header().StreamID)
|
||||
log.Debug().Msgf("mux - read: stream closed: streamID: %d", frame.Header().StreamID)
|
||||
} else {
|
||||
logger.Debugf("mux - read: shutdown receive side: streamID: %d", frame.Header().StreamID)
|
||||
log.Debug().Msgf("mux - read: shutdown receive side: streamID: %d", frame.Header().StreamID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ package h2mux
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"github.com/rs/zerolog"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
)
|
||||
|
|
@ -72,8 +72,8 @@ func tsToPingData(ts int64) [8]byte {
|
|||
return pingData
|
||||
}
|
||||
|
||||
func (w *MuxWriter) run(logger logger.Service) error {
|
||||
defer logger.Debug("mux - write: event loop finished")
|
||||
func (w *MuxWriter) run(log *zerolog.Logger) error {
|
||||
defer log.Debug().Msg("mux - write: event loop finished")
|
||||
|
||||
// routine to periodically communicate bytesWrote
|
||||
go func() {
|
||||
|
|
@ -91,17 +91,17 @@ func (w *MuxWriter) run(logger logger.Service) error {
|
|||
for {
|
||||
select {
|
||||
case <-w.abortChan:
|
||||
logger.Debug("mux - write: aborting writer thread")
|
||||
log.Debug().Msg("mux - write: aborting writer thread")
|
||||
return nil
|
||||
case errCode := <-w.goAwayChan:
|
||||
logger.Debugf("mux - write: sending GOAWAY code %v", errCode)
|
||||
log.Debug().Msgf("mux - write: sending GOAWAY code %v", errCode)
|
||||
err := w.f.WriteGoAway(w.streams.LastPeerStreamID(), errCode, []byte{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.idleTimer.MarkActive()
|
||||
case <-w.pingTimestamp.GetUpdateChan():
|
||||
logger.Debug("mux - write: sending PING ACK")
|
||||
log.Debug().Msg("mux - write: sending PING ACK")
|
||||
err := w.f.WritePing(true, tsToPingData(w.pingTimestamp.Get()))
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -111,7 +111,7 @@ func (w *MuxWriter) run(logger logger.Service) error {
|
|||
if !w.idleTimer.Retry() {
|
||||
return ErrConnectionDropped
|
||||
}
|
||||
logger.Debug("mux - write: sending PING")
|
||||
log.Debug().Msg("mux - write: sending PING")
|
||||
err := w.f.WritePing(false, tsToPingData(time.Now().UnixNano()))
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -121,7 +121,7 @@ func (w *MuxWriter) run(logger logger.Service) error {
|
|||
w.idleTimer.MarkActive()
|
||||
case <-w.streamErrors.GetSignalChan():
|
||||
for streamID, errCode := range w.streamErrors.GetErrors() {
|
||||
logger.Debugf("mux - write: resetting stream with code: %v streamID: %d", errCode, streamID)
|
||||
log.Debug().Msgf("mux - write: resetting stream with code: %v streamID: %d", errCode, streamID)
|
||||
err := w.f.WriteRSTStream(streamID, errCode)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -141,7 +141,7 @@ func (w *MuxWriter) run(logger logger.Service) error {
|
|||
if streamRequest.body != nil {
|
||||
go streamRequest.flushBody()
|
||||
}
|
||||
err := w.writeStreamData(streamRequest.stream, logger)
|
||||
err := w.writeStreamData(streamRequest.stream, log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -151,7 +151,7 @@ func (w *MuxWriter) run(logger logger.Service) error {
|
|||
if !ok {
|
||||
continue
|
||||
}
|
||||
err := w.writeStreamData(stream, logger)
|
||||
err := w.writeStreamData(stream, log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -159,7 +159,7 @@ func (w *MuxWriter) run(logger logger.Service) error {
|
|||
case useDict := <-w.useDictChan:
|
||||
err := w.writeUseDictionary(useDict)
|
||||
if err != nil {
|
||||
logger.Errorf("mux - write: error writing use dictionary: %s", err)
|
||||
log.Error().Msgf("mux - write: error writing use dictionary: %s", err)
|
||||
return err
|
||||
}
|
||||
w.idleTimer.MarkActive()
|
||||
|
|
@ -167,18 +167,18 @@ func (w *MuxWriter) run(logger logger.Service) error {
|
|||
}
|
||||
}
|
||||
|
||||
func (w *MuxWriter) writeStreamData(stream *MuxedStream, logger logger.Service) error {
|
||||
logger.Debugf("mux - write: writable: streamID: %d", stream.streamID)
|
||||
func (w *MuxWriter) writeStreamData(stream *MuxedStream, log *zerolog.Logger) error {
|
||||
log.Debug().Msgf("mux - write: writable: streamID: %d", stream.streamID)
|
||||
chunk := stream.getChunk()
|
||||
w.metricsUpdater.updateReceiveWindow(stream.getReceiveWindow())
|
||||
w.metricsUpdater.updateSendWindow(stream.getSendWindow())
|
||||
if chunk.sendHeadersFrame() {
|
||||
err := w.writeHeaders(chunk.streamID, chunk.headers)
|
||||
if err != nil {
|
||||
logger.Errorf("mux - write: error writing headers: %s: streamID: %d", err, stream.streamID)
|
||||
log.Error().Msgf("mux - write: error writing headers: %s: streamID: %d", err, stream.streamID)
|
||||
return err
|
||||
}
|
||||
logger.Debugf("mux - write: output headers: streamID: %d", stream.streamID)
|
||||
log.Debug().Msgf("mux - write: output headers: streamID: %d", stream.streamID)
|
||||
}
|
||||
|
||||
if chunk.sendWindowUpdateFrame() {
|
||||
|
|
@ -189,22 +189,22 @@ func (w *MuxWriter) writeStreamData(stream *MuxedStream, logger logger.Service)
|
|||
// window, unless the receiver treats this as a connection error"
|
||||
err := w.f.WriteWindowUpdate(chunk.streamID, chunk.windowUpdate)
|
||||
if err != nil {
|
||||
logger.Errorf("mux - write: error writing window update: %s: streamID: %d", err, stream.streamID)
|
||||
log.Error().Msgf("mux - write: error writing window update: %s: streamID: %d", err, stream.streamID)
|
||||
return err
|
||||
}
|
||||
logger.Debugf("mux - write: increment receive window by %d streamID: %d", chunk.windowUpdate, stream.streamID)
|
||||
log.Debug().Msgf("mux - write: increment receive window by %d streamID: %d", chunk.windowUpdate, stream.streamID)
|
||||
}
|
||||
|
||||
for chunk.sendDataFrame() {
|
||||
payload, sentEOF := chunk.nextDataFrame(int(w.maxFrameSize))
|
||||
err := w.f.WriteData(chunk.streamID, sentEOF, payload)
|
||||
if err != nil {
|
||||
logger.Errorf("mux - write: error writing data: %s: streamID: %d", err, stream.streamID)
|
||||
log.Error().Msgf("mux - write: error writing data: %s: streamID: %d", err, stream.streamID)
|
||||
return err
|
||||
}
|
||||
// update the amount of data wrote
|
||||
w.bytesWrote.IncrementBy(uint64(len(payload)))
|
||||
logger.Debugf("mux - write: output data: %d: streamID: %d", len(payload), stream.streamID)
|
||||
log.Debug().Msgf("mux - write: output data: %d: streamID: %d", len(payload), stream.streamID)
|
||||
|
||||
if sentEOF {
|
||||
if stream.readBuffer.Closed() {
|
||||
|
|
@ -212,15 +212,15 @@ func (w *MuxWriter) writeStreamData(stream *MuxedStream, logger logger.Service)
|
|||
if !stream.gotReceiveEOF() {
|
||||
// the peer may send data that we no longer want to receive. Force them into the
|
||||
// closed state.
|
||||
logger.Debugf("mux - write: resetting stream: streamID: %d", stream.streamID)
|
||||
log.Debug().Msgf("mux - write: resetting stream: streamID: %d", stream.streamID)
|
||||
w.f.WriteRSTStream(chunk.streamID, http2.ErrCodeNo)
|
||||
} else {
|
||||
// Half-open stream transitioned into closed
|
||||
logger.Debugf("mux - write: closing stream: streamID: %d", stream.streamID)
|
||||
log.Debug().Msgf("mux - write: closing stream: streamID: %d", stream.streamID)
|
||||
}
|
||||
w.streams.Delete(chunk.streamID)
|
||||
} else {
|
||||
logger.Debugf("mux - write: closing stream write side: streamID: %d", stream.streamID)
|
||||
log.Debug().Msgf("mux - write: closing stream write side: streamID: %d", stream.streamID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
"github.com/cloudflare/cloudflared/tlsconfig"
|
||||
)
|
||||
|
|
@ -99,8 +99,8 @@ const indexTemplate = `
|
|||
</html>
|
||||
`
|
||||
|
||||
func StartHelloWorldServer(logger logger.Service, listener net.Listener, shutdownC <-chan struct{}) error {
|
||||
logger.Infof("Starting Hello World server at %s", listener.Addr())
|
||||
func StartHelloWorldServer(log *zerolog.Logger, listener net.Listener, shutdownC <-chan struct{}) error {
|
||||
log.Info().Msgf("Starting Hello World server at %s", listener.Addr())
|
||||
serverName := defaultServerName
|
||||
if hostname, err := os.Hostname(); err == nil {
|
||||
serverName = hostname
|
||||
|
|
@ -113,14 +113,14 @@ func StartHelloWorldServer(logger logger.Service, listener net.Listener, shutdow
|
|||
|
||||
muxer := http.NewServeMux()
|
||||
muxer.HandleFunc(UptimeRoute, uptimeHandler(time.Now()))
|
||||
muxer.HandleFunc(WSRoute, websocketHandler(logger, upgrader))
|
||||
muxer.HandleFunc(SSERoute, sseHandler(logger))
|
||||
muxer.HandleFunc(WSRoute, websocketHandler(log, upgrader))
|
||||
muxer.HandleFunc(SSERoute, sseHandler(log))
|
||||
muxer.HandleFunc(HealthRoute, healthHandler())
|
||||
muxer.HandleFunc("/", rootHandler(serverName))
|
||||
httpServer := &http.Server{Addr: listener.Addr().String(), Handler: muxer}
|
||||
go func() {
|
||||
<-shutdownC
|
||||
httpServer.Close()
|
||||
_ = httpServer.Close()
|
||||
}()
|
||||
|
||||
err := httpServer.Serve(listener)
|
||||
|
|
@ -152,13 +152,13 @@ func uptimeHandler(startTime time.Time) http.HandlerFunc {
|
|||
w.WriteHeader(http.StatusInternalServerError)
|
||||
} else {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(respJson)
|
||||
_, _ = w.Write(respJson)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This handler will echo message
|
||||
func websocketHandler(logger logger.Service, upgrader websocket.Upgrader) http.HandlerFunc {
|
||||
func websocketHandler(log *zerolog.Logger, upgrader websocket.Upgrader) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// This addresses the issue of r.Host includes port but origin header doesn't
|
||||
host, _, err := net.SplitHostPort(r.Host)
|
||||
|
|
@ -168,32 +168,32 @@ func websocketHandler(logger logger.Service, upgrader websocket.Upgrader) http.H
|
|||
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
logger.Errorf("failed to upgrade to websocket connection, error: %s", err)
|
||||
log.Error().Msgf("failed to upgrade to websocket connection, error: %s", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
for {
|
||||
mt, message, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
logger.Errorf("websocket read message error: %s", err)
|
||||
log.Error().Msgf("websocket read message error: %s", err)
|
||||
break
|
||||
}
|
||||
|
||||
if err := conn.WriteMessage(mt, message); err != nil {
|
||||
logger.Errorf("websocket write message error: %s", err)
|
||||
log.Error().Msgf("websocket write message error: %s", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sseHandler(logger logger.Service) http.HandlerFunc {
|
||||
func sseHandler(log *zerolog.Logger) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/event-stream; charset=utf-8")
|
||||
flusher, ok := w.(http.Flusher)
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
logger.Errorf("Can't support SSE. ResponseWriter %T doesn't implement http.Flusher interface", w)
|
||||
log.Error().Msgf("Can't support SSE. ResponseWriter %T doesn't implement http.Flusher interface", w)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -204,7 +204,7 @@ func sseHandler(logger logger.Service) http.HandlerFunc {
|
|||
freq = parsedFreq
|
||||
}
|
||||
}
|
||||
logger.Infof("Server Sent Events every %s", freq)
|
||||
log.Info().Msgf("Server Sent Events every %s", freq)
|
||||
ticker := time.NewTicker(freq)
|
||||
counter := 0
|
||||
for {
|
||||
|
|
@ -247,9 +247,9 @@ func rootHandler(serverName string) http.HandlerFunc {
|
|||
})
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintf(w, "error: %v", err)
|
||||
_, _ = fmt.Fprintf(w, "error: %v", err)
|
||||
} else {
|
||||
buffer.WriteTo(w)
|
||||
_, _ = buffer.WriteTo(w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -63,7 +63,7 @@ type Ingress struct {
|
|||
|
||||
// NewSingleOrigin constructs an Ingress set with only one rule, constructed from
|
||||
// legacy CLI parameters like --url or --no-chunked-encoding.
|
||||
func NewSingleOrigin(c *cli.Context, allowURLFromArgs bool, logger logger.Service) (Ingress, error) {
|
||||
func NewSingleOrigin(c *cli.Context, allowURLFromArgs bool) (Ingress, error) {
|
||||
|
||||
service, err := parseSingleOriginService(c, allowURLFromArgs)
|
||||
if err != nil {
|
||||
|
|
@ -113,10 +113,10 @@ func (ing Ingress) IsEmpty() bool {
|
|||
}
|
||||
|
||||
// StartOrigins will start any origin services managed by cloudflared, e.g. proxy servers or Hello World.
|
||||
func (ing Ingress) StartOrigins(wg *sync.WaitGroup, log logger.Service, shutdownC <-chan struct{}, errC chan error) {
|
||||
func (ing Ingress) StartOrigins(wg *sync.WaitGroup, log *zerolog.Logger, shutdownC <-chan struct{}, errC chan error) {
|
||||
for _, rule := range ing.Rules {
|
||||
if err := rule.Service.start(wg, log, shutdownC, errC, rule.Config); err != nil {
|
||||
log.Errorf("Error starting local service %s: %s", rule.Service, err)
|
||||
log.Error().Msgf("Error starting local service %s: %s", rule.Service, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import (
|
|||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/tlsconfig"
|
||||
)
|
||||
|
||||
|
|
@ -329,9 +328,8 @@ func TestSingleOriginSetsConfig(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
allowURLFromArgs := false
|
||||
logger, err := logger.New()
|
||||
require.NoError(t, err)
|
||||
ingress, err := NewSingleOrigin(cliCtx, allowURLFromArgs, logger)
|
||||
ingress, err := NewSingleOrigin(cliCtx, allowURLFromArgs)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, time.Second, ingress.Rules[0].Config.ConnectTimeout)
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/hello"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"github.com/cloudflare/cloudflared/socks"
|
||||
"github.com/cloudflare/cloudflared/tlsconfig"
|
||||
"github.com/cloudflare/cloudflared/websocket"
|
||||
gws "github.com/gorilla/websocket"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// OriginService is something a tunnel can proxy traffic to.
|
||||
|
|
@ -29,7 +29,7 @@ type OriginService interface {
|
|||
// Start the origin service if it's managed by cloudflared, e.g. proxy servers or Hello World.
|
||||
// If it's not managed by cloudflared, this is a no-op because the user is responsible for
|
||||
// starting the origin service.
|
||||
start(wg *sync.WaitGroup, log logger.Service, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error
|
||||
start(wg *sync.WaitGroup, log *zerolog.Logger, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error
|
||||
}
|
||||
|
||||
// unixSocketPath is an OriginService representing a unix socket (which accepts HTTP)
|
||||
|
|
@ -42,7 +42,7 @@ func (o *unixSocketPath) String() string {
|
|||
return "unix socket: " + o.path
|
||||
}
|
||||
|
||||
func (o *unixSocketPath) start(wg *sync.WaitGroup, log logger.Service, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error {
|
||||
func (o *unixSocketPath) start(wg *sync.WaitGroup, log *zerolog.Logger, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error {
|
||||
transport, err := newHTTPTransport(o, cfg, log)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -84,7 +84,7 @@ func (o *localService) Dial(reqURL *url.URL, headers http.Header) (*gws.Conn, *h
|
|||
return d.Dial(reqURL.String(), headers)
|
||||
}
|
||||
|
||||
func (o *localService) start(wg *sync.WaitGroup, log logger.Service, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error {
|
||||
func (o *localService) start(wg *sync.WaitGroup, log *zerolog.Logger, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error {
|
||||
transport, err := newHTTPTransport(o, cfg, log)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -101,13 +101,13 @@ func (o *localService) start(wg *sync.WaitGroup, log logger.Service, shutdownC <
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o *localService) startProxy(staticHost string, wg *sync.WaitGroup, log logger.Service, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error {
|
||||
func (o *localService) startProxy(staticHost string, wg *sync.WaitGroup, log *zerolog.Logger, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error {
|
||||
|
||||
// Start a listener for the proxy
|
||||
proxyAddress := net.JoinHostPort(cfg.ProxyAddress, strconv.Itoa(int(cfg.ProxyPort)))
|
||||
listener, err := net.Listen("tcp", proxyAddress)
|
||||
if err != nil {
|
||||
log.Errorf("Cannot start Websocket Proxy Server: %s", err)
|
||||
log.Error().Msgf("Cannot start Websocket Proxy Server: %s", err)
|
||||
return errors.Wrap(err, "Cannot start Websocket Proxy Server")
|
||||
}
|
||||
|
||||
|
|
@ -119,18 +119,18 @@ func (o *localService) startProxy(staticHost string, wg *sync.WaitGroup, log log
|
|||
// This origin's config specifies what type of proxy to start.
|
||||
switch cfg.ProxyType {
|
||||
case socksProxy:
|
||||
log.Info("SOCKS5 server started")
|
||||
log.Info().Msg("SOCKS5 server started")
|
||||
streamHandler = func(wsConn *websocket.Conn, remoteConn net.Conn, _ http.Header) {
|
||||
dialer := socks.NewConnDialer(remoteConn)
|
||||
requestHandler := socks.NewRequestHandler(dialer)
|
||||
socksServer := socks.NewConnectionHandler(requestHandler)
|
||||
|
||||
socksServer.Serve(wsConn)
|
||||
_ = socksServer.Serve(wsConn)
|
||||
}
|
||||
case "":
|
||||
log.Debug("Not starting any websocket proxy")
|
||||
log.Debug().Msg("Not starting any websocket proxy")
|
||||
default:
|
||||
log.Errorf("%s isn't a valid proxy (valid options are {%s})", cfg.ProxyType, socksProxy)
|
||||
log.Error().Msgf("%s isn't a valid proxy (valid options are {%s})", cfg.ProxyType, socksProxy)
|
||||
}
|
||||
|
||||
errC <- websocket.StartProxyServer(log, listener, staticHost, shutdownC, streamHandler)
|
||||
|
|
@ -203,7 +203,13 @@ func (o *helloWorld) String() string {
|
|||
}
|
||||
|
||||
// Start starts a HelloWorld server and stores its address in the Service receiver.
|
||||
func (o *helloWorld) start(wg *sync.WaitGroup, log logger.Service, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error {
|
||||
func (o *helloWorld) start(
|
||||
wg *sync.WaitGroup,
|
||||
log *zerolog.Logger,
|
||||
shutdownC <-chan struct{},
|
||||
errC chan error,
|
||||
cfg OriginRequestConfig,
|
||||
) error {
|
||||
transport, err := newHTTPTransport(o, cfg, log)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -261,7 +267,13 @@ func (o *statusCode) String() string {
|
|||
return fmt.Sprintf("HTTP %d", o.resp.StatusCode)
|
||||
}
|
||||
|
||||
func (o *statusCode) start(wg *sync.WaitGroup, log logger.Service, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error {
|
||||
func (o *statusCode) start(
|
||||
wg *sync.WaitGroup,
|
||||
log *zerolog.Logger,
|
||||
shutdownC <-chan struct{},
|
||||
errC chan error,
|
||||
cfg OriginRequestConfig,
|
||||
) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -280,7 +292,7 @@ func (nrc *NopReadCloser) Close() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func newHTTPTransport(service OriginService, cfg OriginRequestConfig, log logger.Service) (*http.Transport, error) {
|
||||
func newHTTPTransport(service OriginService, cfg OriginRequestConfig, log *zerolog.Logger) (*http.Transport, error) {
|
||||
originCertPool, err := tlsconfig.LoadOriginCA(cfg.CAPool, log)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error loading cert pool")
|
||||
|
|
@ -338,6 +350,6 @@ func (mos MockOriginService) String() string {
|
|||
return "MockOriginService"
|
||||
}
|
||||
|
||||
func (mos MockOriginService) start(wg *sync.WaitGroup, log logger.Service, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error {
|
||||
func (mos MockOriginService) start(wg *sync.WaitGroup, log *zerolog.Logger, shutdownC <-chan struct{}, errC chan error, cfg OriginRequestConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ type RollingConfig struct {
|
|||
}
|
||||
|
||||
func createDefaultConfig() Config {
|
||||
const minLevel = "fatal"
|
||||
const minLevel = "info"
|
||||
|
||||
const RollingMaxSize = 1 // Mb
|
||||
const RollingMaxBackups = 5 // files
|
||||
|
|
@ -57,7 +57,7 @@ func createDefaultConfig() Config {
|
|||
func CreateConfig(
|
||||
minLevel string,
|
||||
disableTerminal bool,
|
||||
rollingLogPath, nonRollingLogFilePath string,
|
||||
rollingLogPath, rollingLogFilename, nonRollingLogFilePath string,
|
||||
) *Config {
|
||||
var console *ConsoleConfig
|
||||
if !disableTerminal {
|
||||
|
|
@ -71,7 +71,7 @@ func CreateConfig(
|
|||
|
||||
var rolling *RollingConfig
|
||||
if rollingLogPath != "" {
|
||||
rolling = createRollingConfig(rollingLogPath)
|
||||
rolling = createRollingConfig(rollingLogPath, rollingLogFilename)
|
||||
}
|
||||
|
||||
if minLevel == "" {
|
||||
|
|
@ -103,14 +103,14 @@ func createFileConfig(filepath string) *FileConfig {
|
|||
}
|
||||
}
|
||||
|
||||
func createRollingConfig(directory string) *RollingConfig {
|
||||
func createRollingConfig(directory, filename string) *RollingConfig {
|
||||
if directory == "" {
|
||||
directory = defaultConfig.RollingConfig.Directory
|
||||
}
|
||||
|
||||
return &RollingConfig{
|
||||
Directory: directory,
|
||||
Filename: defaultConfig.RollingConfig.Filename,
|
||||
Filename: filename,
|
||||
maxSize: defaultConfig.RollingConfig.maxSize,
|
||||
maxBackups: defaultConfig.RollingConfig.maxBackups,
|
||||
maxAge: defaultConfig.RollingConfig.maxAge,
|
||||
|
|
|
|||
203
logger/create.go
203
logger/create.go
|
|
@ -1,13 +1,11 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/alecthomas/units"
|
||||
"github.com/rs/zerolog"
|
||||
fallbacklog "github.com/rs/zerolog/log"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
|
@ -24,162 +22,40 @@ const (
|
|||
LogSSHLevelFlag = "log-level"
|
||||
)
|
||||
|
||||
// Option is to encaspulate actions that will be called by Parse and run later to build an Options struct
|
||||
type Option func(*Options) error
|
||||
func newZerolog(loggerConfig *Config) *zerolog.Logger {
|
||||
var writers []io.Writer
|
||||
|
||||
// Options is use to set logging configuration data
|
||||
type Options struct {
|
||||
logFileDirectory string
|
||||
maxFileSize units.Base2Bytes
|
||||
maxFileCount uint
|
||||
terminalOutputDisabled bool
|
||||
supportedFileLevels []Level
|
||||
supportedTerminalLevels []Level
|
||||
}
|
||||
|
||||
// DisableTerminal stops terminal output for the logger
|
||||
func DisableTerminal(disable bool) Option {
|
||||
return func(c *Options) error {
|
||||
c.terminalOutputDisabled = disable
|
||||
return nil
|
||||
if loggerConfig.ConsoleConfig != nil {
|
||||
writers = append(writers, zerolog.ConsoleWriter{
|
||||
Out: os.Stderr,
|
||||
NoColor: loggerConfig.ConsoleConfig.noColor,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// File sets a custom file to log events
|
||||
func File(path string, size units.Base2Bytes, count uint) Option {
|
||||
return func(c *Options) error {
|
||||
c.logFileDirectory = path
|
||||
c.maxFileSize = size
|
||||
c.maxFileCount = count
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// TODO TUN-3472: Support file writer and log rotation
|
||||
|
||||
// DefaultFile configures the log options will the defaults
|
||||
func DefaultFile(directoryPath string) Option {
|
||||
return func(c *Options) error {
|
||||
size, err := units.ParseBase2Bytes("1MB")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.logFileDirectory = directoryPath
|
||||
c.maxFileSize = size
|
||||
c.maxFileCount = 5
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// SupportedFileLevels sets the supported logging levels for the log file
|
||||
func SupportedFileLevels(supported []Level) Option {
|
||||
return func(c *Options) error {
|
||||
c.supportedFileLevels = supported
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// SupportedTerminalevels sets the supported logging levels for the terminal output
|
||||
func SupportedTerminalevels(supported []Level) Option {
|
||||
return func(c *Options) error {
|
||||
c.supportedTerminalLevels = supported
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// LogLevelString sets the supported logging levels from a command line flag
|
||||
func LogLevelString(level string) Option {
|
||||
return func(c *Options) error {
|
||||
supported, err := ParseLevelString(level)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.supportedFileLevels = supported
|
||||
c.supportedTerminalLevels = supported
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Parse builds the Options struct so the caller knows what actions should be run
|
||||
func Parse(opts ...Option) (*Options, error) {
|
||||
options := &Options{}
|
||||
for _, opt := range opts {
|
||||
if err := opt(options); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return options, nil
|
||||
}
|
||||
|
||||
// New setups a new logger based on the options.
|
||||
// The default behavior is to write to standard out
|
||||
func New(opts ...Option) (*OutputWriter, error) {
|
||||
options, err := Parse(opts...)
|
||||
multi := zerolog.MultiLevelWriter(writers...)
|
||||
|
||||
level, err := zerolog.ParseLevel(loggerConfig.MinLevel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
failLog := fallbacklog.With().Logger()
|
||||
fallbacklog.Error().Msgf("Falling back to a default logger due to logger setup failure: %s", err)
|
||||
return &failLog
|
||||
}
|
||||
log := zerolog.New(multi).With().Timestamp().Logger().Level(level)
|
||||
|
||||
l := NewOutputWriter(SharedWriteManager)
|
||||
if options.logFileDirectory != "" {
|
||||
l.Add(NewFileRollingWriter(SanitizeLogPath(options.logFileDirectory),
|
||||
"cloudflared",
|
||||
int64(options.maxFileSize),
|
||||
options.maxFileCount),
|
||||
NewDefaultFormatter(time.RFC3339Nano), options.supportedFileLevels...)
|
||||
}
|
||||
|
||||
if !options.terminalOutputDisabled {
|
||||
terminalFormatter := NewTerminalFormatter(time.RFC3339)
|
||||
|
||||
if len(options.supportedTerminalLevels) == 0 {
|
||||
l.Add(os.Stderr, terminalFormatter, InfoLevel, ErrorLevel, FatalLevel)
|
||||
} else {
|
||||
l.Add(os.Stderr, terminalFormatter, options.supportedTerminalLevels...)
|
||||
}
|
||||
}
|
||||
|
||||
return l, nil
|
||||
return &log
|
||||
}
|
||||
|
||||
func NewInHouse(loggerConfig *Config) (*OutputWriter, error) {
|
||||
var loggerOpts []Option
|
||||
|
||||
var logPath string
|
||||
if loggerConfig.FileConfig != nil {
|
||||
logPath = loggerConfig.FileConfig.Filepath
|
||||
}
|
||||
if logPath == "" && loggerConfig.RollingConfig != nil {
|
||||
logPath = loggerConfig.RollingConfig.Directory
|
||||
}
|
||||
|
||||
if logPath != "" {
|
||||
loggerOpts = append(loggerOpts, DefaultFile(logPath))
|
||||
}
|
||||
|
||||
loggerOpts = append(loggerOpts, LogLevelString(loggerConfig.MinLevel))
|
||||
|
||||
if loggerConfig.ConsoleConfig == nil {
|
||||
disableOption := DisableTerminal(true)
|
||||
loggerOpts = append(loggerOpts, disableOption)
|
||||
}
|
||||
|
||||
l, err := New(loggerOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func CreateTransportLoggerFromContext(c *cli.Context, disableTerminal bool) (*OutputWriter, error) {
|
||||
func CreateTransportLoggerFromContext(c *cli.Context, disableTerminal bool) *zerolog.Logger {
|
||||
return createFromContext(c, LogTransportLevelFlag, LogDirectoryFlag, disableTerminal)
|
||||
}
|
||||
|
||||
func CreateLoggerFromContext(c *cli.Context, disableTerminal bool) (*OutputWriter, error) {
|
||||
func CreateLoggerFromContext(c *cli.Context, disableTerminal bool) *zerolog.Logger {
|
||||
return createFromContext(c, LogLevelFlag, LogDirectoryFlag, disableTerminal)
|
||||
}
|
||||
|
||||
func CreateSSHLoggerFromContext(c *cli.Context, disableTerminal bool) (*OutputWriter, error) {
|
||||
func CreateSSHLoggerFromContext(c *cli.Context, disableTerminal bool) *zerolog.Logger {
|
||||
return createFromContext(c, LogSSHLevelFlag, LogSSHDirectoryFlag, disableTerminal)
|
||||
}
|
||||
|
||||
|
|
@ -188,37 +64,26 @@ func createFromContext(
|
|||
logLevelFlagName,
|
||||
logDirectoryFlagName string,
|
||||
disableTerminal bool,
|
||||
) (*OutputWriter, error) {
|
||||
) *zerolog.Logger {
|
||||
logLevel := c.String(logLevelFlagName)
|
||||
logFile := c.String(LogFileFlag)
|
||||
logDirectory := c.String(logDirectoryFlagName)
|
||||
|
||||
loggerConfig := CreateConfig(logLevel, disableTerminal, logDirectory, logFile)
|
||||
loggerConfig := CreateConfig(
|
||||
logLevel,
|
||||
disableTerminal,
|
||||
logDirectory,
|
||||
defaultConfig.RollingConfig.Filename,
|
||||
logFile,
|
||||
)
|
||||
|
||||
return NewInHouse(loggerConfig)
|
||||
return newZerolog(loggerConfig)
|
||||
}
|
||||
|
||||
// ParseLevelString returns the expected log levels based on the cmd flag
|
||||
func ParseLevelString(lvl string) ([]Level, error) {
|
||||
switch strings.ToLower(lvl) {
|
||||
case "fatal":
|
||||
return []Level{FatalLevel}, nil
|
||||
case "error":
|
||||
return []Level{FatalLevel, ErrorLevel}, nil
|
||||
case "info", "warn":
|
||||
return []Level{FatalLevel, ErrorLevel, InfoLevel}, nil
|
||||
case "debug":
|
||||
return []Level{FatalLevel, ErrorLevel, InfoLevel, DebugLevel}, nil
|
||||
func Create(loggerConfig *Config) *zerolog.Logger {
|
||||
if loggerConfig == nil {
|
||||
loggerConfig = &defaultConfig
|
||||
}
|
||||
return []Level{}, fmt.Errorf("not a valid log level: %q", lvl)
|
||||
}
|
||||
|
||||
// SanitizeLogPath checks that the logger log path
|
||||
func SanitizeLogPath(path string) string {
|
||||
newPath := strings.TrimSpace(path)
|
||||
// make sure it has a log file extension and is not a directory
|
||||
if filepath.Ext(newPath) != ".log" && !(isDirectory(newPath) || strings.HasSuffix(newPath, "/")) {
|
||||
newPath = newPath + ".log"
|
||||
}
|
||||
return newPath
|
||||
return newZerolog(loggerConfig)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLogLevelParse(t *testing.T) {
|
||||
lvls, err := ParseLevelString("fatal")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []Level{FatalLevel}, lvls)
|
||||
|
||||
lvls, err = ParseLevelString("error")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []Level{FatalLevel, ErrorLevel}, lvls)
|
||||
|
||||
lvls, err = ParseLevelString("info")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []Level{FatalLevel, ErrorLevel, InfoLevel}, lvls)
|
||||
|
||||
lvls, err = ParseLevelString("info")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []Level{FatalLevel, ErrorLevel, InfoLevel}, lvls)
|
||||
|
||||
lvls, err = ParseLevelString("warn")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []Level{FatalLevel, ErrorLevel, InfoLevel}, lvls)
|
||||
|
||||
lvls, err = ParseLevelString("debug")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []Level{FatalLevel, ErrorLevel, InfoLevel, DebugLevel}, lvls)
|
||||
|
||||
_, err = ParseLevelString("blah")
|
||||
assert.Error(t, err)
|
||||
|
||||
_, err = ParseLevelString("")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestPathSanitizer(t *testing.T) {
|
||||
assert.Equal(t, "somebad/path/log.bat.log", SanitizeLogPath("\t somebad/path/log.bat\n\n"))
|
||||
assert.Equal(t, "proper/path/cloudflared.log", SanitizeLogPath("proper/path/cloudflared.log"))
|
||||
assert.Equal(t, "proper/path/", SanitizeLogPath("proper/path/"))
|
||||
assert.Equal(t, "proper/path/cloudflared.log", SanitizeLogPath("\tproper/path/cloudflared\n\n"))
|
||||
}
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// FileRollingWriter maintains a set of log files numbered in order
|
||||
// to keep a subset of log data to ensure it doesn't grow pass defined limits
|
||||
type FileRollingWriter struct {
|
||||
baseFileName string
|
||||
directory string
|
||||
maxFileSize int64
|
||||
maxFileCount uint
|
||||
fileHandle *os.File
|
||||
}
|
||||
|
||||
// NewFileRollingWriter creates a new rolling file writer.
|
||||
// directory is the working directory for the files
|
||||
// baseFileName is the log file name. This writer appends .log to the name for the file name
|
||||
// maxFileSize is the size in bytes of how large each file can be. Not a hard limit, general limit based after each write
|
||||
// maxFileCount is the number of rolled files to keep.
|
||||
func NewFileRollingWriter(directory, baseFileName string, maxFileSize int64, maxFileCount uint) *FileRollingWriter {
|
||||
return &FileRollingWriter{
|
||||
directory: directory,
|
||||
baseFileName: baseFileName,
|
||||
maxFileSize: maxFileSize,
|
||||
maxFileCount: maxFileCount,
|
||||
}
|
||||
}
|
||||
|
||||
// Write is an implementation of io.writer the rolls the file once it reaches its max size
|
||||
// It is expected the caller to Write is doing so in a thread safe manner (as WriteManager does).
|
||||
func (w *FileRollingWriter) Write(p []byte) (n int, err error) {
|
||||
logFile, isSingleFile := buildPath(w.directory, w.baseFileName)
|
||||
if w.fileHandle == nil {
|
||||
h, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
w.fileHandle = h
|
||||
}
|
||||
|
||||
// get size for rolling check
|
||||
info, err := w.fileHandle.Stat()
|
||||
if err != nil {
|
||||
// failed to stat the file. Close the file handle and attempt to open a new handle on the next write
|
||||
w.Close()
|
||||
w.fileHandle = nil
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// write to the file
|
||||
written, err := w.fileHandle.Write(p)
|
||||
|
||||
// check if the file needs to be rolled
|
||||
if err == nil && info.Size()+int64(written) > w.maxFileSize && !isSingleFile {
|
||||
// close the file handle than do the renaming. A new one will be opened on the next write
|
||||
w.Close()
|
||||
w.rename(logFile, 1)
|
||||
}
|
||||
|
||||
return written, err
|
||||
}
|
||||
|
||||
// Close closes the file handle if it is open
|
||||
func (w *FileRollingWriter) Close() {
|
||||
if w.fileHandle != nil {
|
||||
w.fileHandle.Close()
|
||||
w.fileHandle = nil
|
||||
}
|
||||
}
|
||||
|
||||
// rename is how the files are rolled. It works recursively to move the base log file to the rolled ones
|
||||
// e.g. cloudflared.log -> cloudflared-1.log,
|
||||
// but if cloudflared-1.log already exists, it is renamed to cloudflared-2.log,
|
||||
// then the other files move in to their postion
|
||||
func (w *FileRollingWriter) rename(sourcePath string, index uint) {
|
||||
destinationPath, isSingleFile := buildPath(w.directory, fmt.Sprintf("%s-%d", w.baseFileName, index))
|
||||
if isSingleFile {
|
||||
return //don't need to rename anything, it is a single file
|
||||
}
|
||||
|
||||
// rolled to the max amount of files allowed on disk
|
||||
if index >= w.maxFileCount {
|
||||
os.Remove(destinationPath)
|
||||
}
|
||||
|
||||
// if the rolled path already exist, rename it to cloudflared-2.log, then do this one.
|
||||
// recursive call since the oldest one needs to be renamed, before the newer ones can be moved
|
||||
if exists(destinationPath) {
|
||||
w.rename(destinationPath, index+1)
|
||||
}
|
||||
|
||||
os.Rename(sourcePath, destinationPath)
|
||||
}
|
||||
|
||||
// return the path to the log file and if it is a single file or not.
|
||||
// true means a single file. false means a rolled file
|
||||
func buildPath(directory, fileName string) (string, bool) {
|
||||
if !isDirectory(directory) { // not a directory, so try and treat it as a single file for backwards compatibility sake
|
||||
return directory, true
|
||||
}
|
||||
return filepath.Join(directory, fileName+".log"), false
|
||||
}
|
||||
|
||||
func exists(filePath string) bool {
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isDirectory(path string) bool {
|
||||
if path == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
fileInfo, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return fileInfo.IsDir()
|
||||
}
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFileWrite(t *testing.T) {
|
||||
fileName := "test_file"
|
||||
fileLog := fileName + ".log"
|
||||
testData := []byte(string("hello Dalton, how are you doing?"))
|
||||
defer func() {
|
||||
os.Remove(fileLog)
|
||||
}()
|
||||
|
||||
w := NewFileRollingWriter("", fileName, 1000, 2)
|
||||
defer w.Close()
|
||||
|
||||
l, err := w.Write(testData)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, l, len(testData), "expected write length and data length to match")
|
||||
|
||||
d, err := ioutil.ReadFile(fileLog)
|
||||
assert.FileExists(t, fileLog, "file doesn't exist at expected path")
|
||||
assert.Equal(t, d, testData, "expected data in file to match test data")
|
||||
}
|
||||
|
||||
func TestRolling(t *testing.T) {
|
||||
dirName := "testdir"
|
||||
err := os.Mkdir(dirName, 0755)
|
||||
assert.NoError(t, err)
|
||||
|
||||
fileName := "test_file"
|
||||
firstFile := filepath.Join(dirName, fileName+".log")
|
||||
secondFile := filepath.Join(dirName, fileName+"-1.log")
|
||||
thirdFile := filepath.Join(dirName, fileName+"-2.log")
|
||||
|
||||
defer func() {
|
||||
os.RemoveAll(dirName)
|
||||
os.Remove(firstFile)
|
||||
os.Remove(secondFile)
|
||||
os.Remove(thirdFile)
|
||||
}()
|
||||
|
||||
w := NewFileRollingWriter(dirName, fileName, 1000, 2)
|
||||
defer w.Close()
|
||||
|
||||
for i := 99; i >= 1; i-- {
|
||||
testData := []byte(fmt.Sprintf("%d bottles of beer on the wall...", i))
|
||||
w.Write(testData)
|
||||
}
|
||||
assert.FileExists(t, firstFile, "first file doesn't exist as expected")
|
||||
assert.FileExists(t, secondFile, "second file doesn't exist as expected")
|
||||
assert.FileExists(t, thirdFile, "third file doesn't exist as expected")
|
||||
assert.False(t, exists(filepath.Join(dirName, fileName+"-3.log")), "limited to two files and there is more")
|
||||
}
|
||||
|
||||
func TestSingleFile(t *testing.T) {
|
||||
fileName := "test_file"
|
||||
testData := []byte(string("hello Dalton, how are you doing?"))
|
||||
defer func() {
|
||||
os.Remove(fileName)
|
||||
}()
|
||||
|
||||
w := NewFileRollingWriter(fileName, fileName, 1000, 2)
|
||||
defer w.Close()
|
||||
|
||||
l, err := w.Write(testData)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, l, len(testData), "expected write length and data length to match")
|
||||
|
||||
d, err := ioutil.ReadFile(fileName)
|
||||
assert.FileExists(t, fileName, "file doesn't exist at expected path")
|
||||
assert.Equal(t, d, testData, "expected data in file to match test data")
|
||||
}
|
||||
|
||||
func TestSingleFileInDirectory(t *testing.T) {
|
||||
dirName := "testdir"
|
||||
err := os.Mkdir(dirName, 0755)
|
||||
assert.NoError(t, err)
|
||||
|
||||
fileName := "test_file"
|
||||
fullPath := filepath.Join(dirName, fileName+".log")
|
||||
testData := []byte(string("hello Dalton, how are you doing?"))
|
||||
defer func() {
|
||||
os.Remove(fullPath)
|
||||
os.RemoveAll(dirName)
|
||||
}()
|
||||
|
||||
w := NewFileRollingWriter(fullPath, fileName, 1000, 2)
|
||||
defer w.Close()
|
||||
|
||||
l, err := w.Write(testData)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, l, len(testData), "expected write length and data length to match")
|
||||
|
||||
d, err := ioutil.ReadFile(fullPath)
|
||||
assert.FileExists(t, fullPath, "file doesn't exist at expected path")
|
||||
assert.Equal(t, d, testData, "expected data in file to match test data")
|
||||
}
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/acmacalister/skittles"
|
||||
)
|
||||
|
||||
// Level of logging, lower number means more verbose logging, higher more terse
|
||||
type Level int
|
||||
|
||||
const (
|
||||
// DebugLevel is for messages that are intended for purposes debugging only
|
||||
DebugLevel Level = iota
|
||||
|
||||
// InfoLevel is for standard log messages
|
||||
InfoLevel
|
||||
|
||||
// ErrorLevel is for error message to indicate something has gone wrong
|
||||
ErrorLevel
|
||||
|
||||
// FatalLevel is for error message that log and kill the program with an os.exit(1)
|
||||
FatalLevel
|
||||
)
|
||||
|
||||
// Formatter is the base interface for formatting logging messages before writing them out
|
||||
type Formatter interface {
|
||||
Timestamp(Level, time.Time) string // format the timestamp string
|
||||
Content(Level, string) string // format content string (color for terminal, etc)
|
||||
}
|
||||
|
||||
// DefaultFormatter writes a simple structure timestamp and the message per log line
|
||||
type DefaultFormatter struct {
|
||||
format string
|
||||
}
|
||||
|
||||
// NewDefaultFormatter creates the standard log formatter
|
||||
// format is the time format to use for timestamp formatting
|
||||
func NewDefaultFormatter(format string) Formatter {
|
||||
return &DefaultFormatter{
|
||||
format: format,
|
||||
}
|
||||
}
|
||||
|
||||
// Timestamp formats a log line timestamp with a brackets around them
|
||||
func (f *DefaultFormatter) Timestamp(l Level, d time.Time) string {
|
||||
if f.format == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("[%s]: ", d.Format(f.format))
|
||||
}
|
||||
|
||||
// Content just writes the log line straight to the sources
|
||||
func (f *DefaultFormatter) Content(l Level, c string) string {
|
||||
return c
|
||||
}
|
||||
|
||||
// TerminalFormatter is setup for colored output
|
||||
type TerminalFormatter struct {
|
||||
format string
|
||||
supportsColor bool
|
||||
}
|
||||
|
||||
// UIFormatter is used for streaming logs to UI
|
||||
type UIFormatter struct {
|
||||
format string
|
||||
supportsColor bool
|
||||
}
|
||||
|
||||
// NewTerminalFormatter creates a Terminal formatter for colored output
|
||||
// format is the time format to use for timestamp formatting
|
||||
func NewTerminalFormatter(format string) Formatter {
|
||||
supportsColor := (runtime.GOOS != "windows")
|
||||
return &TerminalFormatter{
|
||||
format: format,
|
||||
supportsColor: supportsColor,
|
||||
}
|
||||
}
|
||||
|
||||
func NewUIFormatter(format string) Formatter {
|
||||
supportsColor := (runtime.GOOS != "windows")
|
||||
return &UIFormatter{
|
||||
format: format,
|
||||
supportsColor: supportsColor,
|
||||
}
|
||||
}
|
||||
|
||||
// Timestamp uses formatting that is tview-specific for UI
|
||||
func (f *UIFormatter) Timestamp(l Level, d time.Time) string {
|
||||
t := ""
|
||||
dateStr := "[" + d.Format(f.format) + "] "
|
||||
switch l {
|
||||
case InfoLevel:
|
||||
t = "[#00ffff]INFO[white]"
|
||||
case ErrorLevel:
|
||||
t = "[red]ERROR[white]"
|
||||
case DebugLevel:
|
||||
t = "[yellow]DEBUG[white]"
|
||||
case FatalLevel:
|
||||
t = "[red]FATAL[white]"
|
||||
}
|
||||
return t + dateStr
|
||||
}
|
||||
|
||||
func (f *UIFormatter) Content(l Level, c string) string {
|
||||
return c
|
||||
}
|
||||
|
||||
// Timestamp returns the log level with a matching color to the log type
|
||||
func (f *TerminalFormatter) Timestamp(l Level, d time.Time) string {
|
||||
t := ""
|
||||
dateStr := "[" + d.Format(f.format) + "] "
|
||||
switch l {
|
||||
case InfoLevel:
|
||||
t = f.output("INFO", skittles.Cyan)
|
||||
case ErrorLevel:
|
||||
t = f.output("ERROR", skittles.Red)
|
||||
case DebugLevel:
|
||||
t = f.output("DEBUG", skittles.Yellow)
|
||||
case FatalLevel:
|
||||
t = f.output("FATAL", skittles.Red)
|
||||
}
|
||||
return t + dateStr
|
||||
}
|
||||
|
||||
// Content just writes the log line straight to the sources
|
||||
func (f *TerminalFormatter) Content(l Level, c string) string {
|
||||
return c
|
||||
}
|
||||
|
||||
func (f *TerminalFormatter) output(msg string, colorFunc func(interface{}) string) string {
|
||||
if f.supportsColor {
|
||||
return colorFunc(msg)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
package logger
|
||||
|
||||
import "sync"
|
||||
|
||||
// SharedWriteManager is a package level variable to allows multiple loggers to use the same write manager.
|
||||
// This is useful when multiple loggers will write to the same file to ensure they don't clobber each other.
|
||||
var SharedWriteManager = NewWriteManager()
|
||||
|
||||
type writeData struct {
|
||||
target LogOutput
|
||||
data []byte
|
||||
}
|
||||
|
||||
// WriteManager is a logging service that handles managing multiple writing streams
|
||||
type WriteManager struct {
|
||||
shutdown chan struct{}
|
||||
writeChan chan writeData
|
||||
writers map[string]Service
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// NewWriteManager creates a write manager that implements OutputManager
|
||||
func NewWriteManager() OutputManager {
|
||||
m := &WriteManager{
|
||||
shutdown: make(chan struct{}),
|
||||
writeChan: make(chan writeData, 1000),
|
||||
}
|
||||
|
||||
go m.run()
|
||||
return m
|
||||
}
|
||||
|
||||
// Append adds a message to the writer runloop
|
||||
func (m *WriteManager) Append(data []byte, target LogOutput) {
|
||||
m.wg.Add(1)
|
||||
m.writeChan <- writeData{data: data, target: target}
|
||||
}
|
||||
|
||||
// Shutdown stops the sync manager service
|
||||
func (m *WriteManager) Shutdown() {
|
||||
m.wg.Wait()
|
||||
close(m.shutdown)
|
||||
close(m.writeChan)
|
||||
}
|
||||
|
||||
// run is the main runloop that schedules log messages
|
||||
func (m *WriteManager) run() {
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-m.writeChan:
|
||||
if ok {
|
||||
event.target.WriteLogLine(event.data)
|
||||
m.wg.Done()
|
||||
}
|
||||
case <-m.shutdown:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type outputFunc func(b []byte)
|
||||
|
||||
func (f outputFunc) WriteLogLine(data []byte) {
|
||||
f(data)
|
||||
}
|
||||
|
||||
func TestWriteManger(t *testing.T) {
|
||||
testData := []byte(string("hello Austin, how are you doing?"))
|
||||
waitChan := make(chan []byte)
|
||||
m := NewWriteManager()
|
||||
m.Append(testData, outputFunc(func(b []byte) {
|
||||
waitChan <- b
|
||||
}))
|
||||
resp := <-waitChan
|
||||
assert.Equal(t, testData, resp)
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package logger
|
||||
|
||||
// MockWriteManager does nothing and is provided for testing purposes
|
||||
type MockWriteManager struct {
|
||||
}
|
||||
|
||||
// NewMockWriteManager creates an OutputManager that does nothing for testing purposes
|
||||
func NewMockWriteManager() OutputManager {
|
||||
return &MockWriteManager{}
|
||||
}
|
||||
|
||||
// Append is a mock stub
|
||||
func (m *MockWriteManager) Append(data []byte, target LogOutput) {
|
||||
}
|
||||
|
||||
// Shutdown is a mock stub
|
||||
func (m *MockWriteManager) Shutdown() {
|
||||
}
|
||||
157
logger/output.go
157
logger/output.go
|
|
@ -1,157 +0,0 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// provided for testing
|
||||
var osExit = os.Exit
|
||||
|
||||
type LogOutput interface {
|
||||
WriteLogLine([]byte)
|
||||
}
|
||||
|
||||
// OutputManager is used to sync data of Output
|
||||
type OutputManager interface {
|
||||
Append([]byte, LogOutput)
|
||||
Shutdown()
|
||||
}
|
||||
|
||||
// Service is the logging service that is either a group or single log writer
|
||||
type Service interface {
|
||||
Error(message string)
|
||||
Info(message string)
|
||||
Debug(message string)
|
||||
Fatal(message string)
|
||||
|
||||
Errorf(format string, args ...interface{})
|
||||
Infof(format string, args ...interface{})
|
||||
Debugf(format string, args ...interface{})
|
||||
Fatalf(format string, args ...interface{})
|
||||
|
||||
Add(writer io.Writer, formatter Formatter, levels ...Level)
|
||||
}
|
||||
|
||||
type sourceGroup struct {
|
||||
writer io.Writer
|
||||
formatter Formatter
|
||||
levelsSupported []Level
|
||||
}
|
||||
|
||||
func (s *sourceGroup) WriteLogLine(data []byte) {
|
||||
_, _ = s.writer.Write(data)
|
||||
}
|
||||
|
||||
func (s *sourceGroup) supportsLevel(l Level) bool {
|
||||
for _, level := range s.levelsSupported {
|
||||
if l == level {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// OutputWriter is the standard logging implementation
|
||||
type OutputWriter struct {
|
||||
groups []*sourceGroup
|
||||
syncWriter OutputManager
|
||||
minLevel Level
|
||||
}
|
||||
|
||||
// NewOutputWriter creates a new logger
|
||||
func NewOutputWriter(syncWriter OutputManager) *OutputWriter {
|
||||
return &OutputWriter{
|
||||
syncWriter: syncWriter,
|
||||
groups: nil,
|
||||
minLevel: FatalLevel,
|
||||
}
|
||||
}
|
||||
|
||||
// Add a writer and formatter to output to
|
||||
func (s *OutputWriter) Add(writer io.Writer, formatter Formatter, levels ...Level) {
|
||||
s.groups = append(s.groups, &sourceGroup{writer: writer, formatter: formatter, levelsSupported: levels})
|
||||
|
||||
// track most verbose (lowest) level we need to output
|
||||
for _, level := range levels {
|
||||
if level < s.minLevel {
|
||||
s.minLevel = level
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error writes an error to the logging sources
|
||||
func (s *OutputWriter) Error(message string) {
|
||||
if s.minLevel <= ErrorLevel {
|
||||
s.output(ErrorLevel, message)
|
||||
}
|
||||
}
|
||||
|
||||
// Info writes an info string to the logging sources
|
||||
func (s *OutputWriter) Info(message string) {
|
||||
if s.minLevel <= InfoLevel {
|
||||
s.output(InfoLevel, message)
|
||||
}
|
||||
}
|
||||
|
||||
// Debug writes a debug string to the logging sources
|
||||
func (s *OutputWriter) Debug(message string) {
|
||||
if s.minLevel <= DebugLevel {
|
||||
s.output(DebugLevel, message)
|
||||
}
|
||||
}
|
||||
|
||||
// Fatal writes a error string to the logging sources and runs does an os.exit()
|
||||
func (s *OutputWriter) Fatal(message string) {
|
||||
s.output(FatalLevel, message)
|
||||
s.syncWriter.Shutdown() // waits for the pending logging to finish
|
||||
osExit(1)
|
||||
}
|
||||
|
||||
// Errorf writes a formatted error to the logging sources
|
||||
func (s *OutputWriter) Errorf(format string, args ...interface{}) {
|
||||
if s.minLevel <= ErrorLevel {
|
||||
s.output(ErrorLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
}
|
||||
|
||||
// Infof writes a formatted info statement to the logging sources
|
||||
func (s *OutputWriter) Infof(format string, args ...interface{}) {
|
||||
if s.minLevel <= InfoLevel {
|
||||
s.output(InfoLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
}
|
||||
|
||||
// Debugf writes a formatted debug statement to the logging sources
|
||||
func (s *OutputWriter) Debugf(format string, args ...interface{}) {
|
||||
if s.minLevel <= DebugLevel {
|
||||
s.output(DebugLevel, fmt.Sprintf(format, args...))
|
||||
}
|
||||
}
|
||||
|
||||
// Fatalf writes a writes a formatted error statement and runs does an os.exit()
|
||||
func (s *OutputWriter) Fatalf(format string, args ...interface{}) {
|
||||
s.output(FatalLevel, fmt.Sprintf(format, args...))
|
||||
s.syncWriter.Shutdown() // waits for the pending logging to finish
|
||||
osExit(1)
|
||||
}
|
||||
|
||||
// output does the actual write to the sync manager
|
||||
func (s *OutputWriter) output(l Level, content string) {
|
||||
now := time.Now()
|
||||
for _, group := range s.groups {
|
||||
if group.supportsLevel(l) {
|
||||
logLine := fmt.Sprintf("%s%s\n", group.formatter.Timestamp(l, now),
|
||||
group.formatter.Content(l, content))
|
||||
s.syncWriter.Append([]byte(logLine), group)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write implements io.Writer to support SetOutput of the log package
|
||||
func (s *OutputWriter) Write(p []byte) (n int, err error) {
|
||||
s.Info(string(p))
|
||||
return len(p), nil
|
||||
}
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLogLevel(t *testing.T) {
|
||||
timeFormat := "2006-01-02"
|
||||
f := NewDefaultFormatter(timeFormat)
|
||||
m := NewWriteManager()
|
||||
|
||||
var testBuffer bytes.Buffer
|
||||
logger := NewOutputWriter(m)
|
||||
logger.Add(&testBuffer, f, InfoLevel, DebugLevel)
|
||||
|
||||
testTime := f.Timestamp(InfoLevel, time.Now())
|
||||
|
||||
testInfo := "hello Dalton, how are you doing?"
|
||||
logger.Info(testInfo)
|
||||
|
||||
tesErr := "hello Austin, how did it break today?"
|
||||
logger.Error(tesErr)
|
||||
|
||||
testDebug := "hello Bill, who are you?"
|
||||
logger.Debug(testDebug)
|
||||
|
||||
m.Shutdown()
|
||||
|
||||
lines := strings.Split(testBuffer.String(), "\n")
|
||||
assert.Len(t, lines, 3, "only expected two strings in the buffer")
|
||||
|
||||
infoLine := lines[0]
|
||||
debugLine := lines[1]
|
||||
|
||||
compareInfo := fmt.Sprintf("%s%s", testTime, testInfo)
|
||||
assert.Equal(t, compareInfo, infoLine, "expect the strings to match")
|
||||
|
||||
compareDebug := fmt.Sprintf("%s%s", testTime, testDebug)
|
||||
assert.Equal(t, compareDebug, debugLine, "expect the strings to match")
|
||||
}
|
||||
|
||||
func TestOutputWrite(t *testing.T) {
|
||||
timeFormat := "2006-01-02"
|
||||
f := NewDefaultFormatter(timeFormat)
|
||||
m := NewWriteManager()
|
||||
|
||||
var testBuffer bytes.Buffer
|
||||
logger := NewOutputWriter(m)
|
||||
logger.Add(&testBuffer, f, InfoLevel)
|
||||
|
||||
logger.Debugf("debug message not logged here")
|
||||
|
||||
testData := "hello Bob Bork, how are you doing?"
|
||||
logger.Info(testData)
|
||||
testTime := f.Timestamp(InfoLevel, time.Now())
|
||||
|
||||
m.Shutdown()
|
||||
|
||||
scanner := bufio.NewScanner(&testBuffer)
|
||||
scanner.Scan()
|
||||
line := scanner.Text()
|
||||
assert.NoError(t, scanner.Err())
|
||||
|
||||
compareLine := fmt.Sprintf("%s%s", testTime, testData)
|
||||
assert.Equal(t, compareLine, line, "expect the strings to match")
|
||||
}
|
||||
|
||||
func TestFatalWrite(t *testing.T) {
|
||||
timeFormat := "2006-01-02"
|
||||
f := NewDefaultFormatter(timeFormat)
|
||||
m := NewWriteManager()
|
||||
|
||||
var testBuffer bytes.Buffer
|
||||
logger := NewOutputWriter(m)
|
||||
logger.Add(&testBuffer, f, FatalLevel)
|
||||
|
||||
oldOsExit := osExit
|
||||
defer func() { osExit = oldOsExit }()
|
||||
|
||||
var got int
|
||||
myExit := func(code int) {
|
||||
got = code
|
||||
}
|
||||
|
||||
osExit = myExit
|
||||
|
||||
testData := "so long y'all"
|
||||
logger.Fatal(testData)
|
||||
testTime := f.Timestamp(FatalLevel, time.Now())
|
||||
|
||||
scanner := bufio.NewScanner(&testBuffer)
|
||||
scanner.Scan()
|
||||
line := scanner.Text()
|
||||
assert.NoError(t, scanner.Err())
|
||||
|
||||
compareLine := fmt.Sprintf("%s%s", testTime, testData)
|
||||
assert.Equal(t, compareLine, line, "expect the strings to match")
|
||||
assert.Equal(t, got, 1, "exit code should be one for a fatal log")
|
||||
}
|
||||
|
|
@ -10,12 +10,12 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/trace"
|
||||
|
||||
"github.com/cloudflare/cloudflared/connection"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/rs/zerolog"
|
||||
"golang.org/x/net/trace"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -23,12 +23,12 @@ const (
|
|||
startupTime = time.Millisecond * 500
|
||||
)
|
||||
|
||||
func newMetricsHandler(connectionEvents <-chan connection.Event, log logger.Service) *http.ServeMux {
|
||||
func newMetricsHandler(connectionEvents <-chan connection.Event, log *zerolog.Logger) *http.ServeMux {
|
||||
readyServer := NewReadyServer(connectionEvents, log)
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/metrics", promhttp.Handler())
|
||||
mux.HandleFunc("/healthcheck", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "OK\n")
|
||||
_, _ = fmt.Fprintf(w, "OK\n")
|
||||
})
|
||||
mux.Handle("/ready", readyServer)
|
||||
return mux
|
||||
|
|
@ -38,14 +38,14 @@ func ServeMetrics(
|
|||
l net.Listener,
|
||||
shutdownC <-chan struct{},
|
||||
connectionEvents <-chan connection.Event,
|
||||
logger logger.Service,
|
||||
log *zerolog.Logger,
|
||||
) (err error) {
|
||||
var wg sync.WaitGroup
|
||||
// Metrics port is privileged, so no need for further access control
|
||||
trace.AuthRequest = func(*http.Request) (bool, bool) { return true, true }
|
||||
// TODO: parameterize ReadTimeout and WriteTimeout. The maximum time we can
|
||||
// profile CPU usage depends on WriteTimeout
|
||||
h := newMetricsHandler(connectionEvents, logger)
|
||||
h := newMetricsHandler(connectionEvents, log)
|
||||
server := &http.Server{
|
||||
ReadTimeout: 10 * time.Second,
|
||||
WriteTimeout: 10 * time.Second,
|
||||
|
|
@ -57,22 +57,22 @@ func ServeMetrics(
|
|||
defer wg.Done()
|
||||
err = server.Serve(l)
|
||||
}()
|
||||
logger.Infof("Starting metrics server on %s", fmt.Sprintf("%v/metrics", l.Addr()))
|
||||
log.Info().Msgf("Starting metrics server on %s", fmt.Sprintf("%v/metrics", l.Addr()))
|
||||
// server.Serve will hang if server.Shutdown is called before the server is
|
||||
// fully started up. So add artificial delay.
|
||||
time.Sleep(startupTime)
|
||||
|
||||
<-shutdownC
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
|
||||
server.Shutdown(ctx)
|
||||
_ = server.Shutdown(ctx)
|
||||
cancel()
|
||||
|
||||
wg.Wait()
|
||||
if err == http.ErrServerClosed {
|
||||
logger.Info("Metrics server stopped")
|
||||
log.Info().Msg("Metrics server stopped")
|
||||
return nil
|
||||
}
|
||||
logger.Errorf("Metrics server quit with error: %s", err)
|
||||
log.Error().Msgf("Metrics server quit with error: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,18 +7,19 @@ import (
|
|||
"sync"
|
||||
|
||||
conn "github.com/cloudflare/cloudflared/connection"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// ReadyServer serves HTTP 200 if the tunnel can serve traffic. Intended for k8s readiness checks.
|
||||
type ReadyServer struct {
|
||||
sync.RWMutex
|
||||
isConnected map[int]bool
|
||||
log logger.Service
|
||||
log *zerolog.Logger
|
||||
}
|
||||
|
||||
// NewReadyServer initializes a ReadyServer and starts listening for dis/connection events.
|
||||
func NewReadyServer(connectionEvents <-chan conn.Event, log logger.Service) *ReadyServer {
|
||||
func NewReadyServer(connectionEvents <-chan conn.Event, log *zerolog.Logger) *ReadyServer {
|
||||
rs := ReadyServer{
|
||||
isConnected: make(map[int]bool, 0),
|
||||
log: log,
|
||||
|
|
@ -37,7 +38,7 @@ func NewReadyServer(connectionEvents <-chan conn.Event, log logger.Service) *Rea
|
|||
case conn.SetURL:
|
||||
continue
|
||||
default:
|
||||
rs.log.Errorf("Unknown connection event case %v", c)
|
||||
rs.log.Error().Msgf("Unknown connection event case %v", c)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
|
@ -59,9 +60,9 @@ func (rs *ReadyServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
msg, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, `{"error": "%s"}`, err)
|
||||
_, _ = fmt.Fprintf(w, `{"error": "%s"}`, err)
|
||||
}
|
||||
w.Write(msg)
|
||||
_, _ = w.Write(msg)
|
||||
}
|
||||
|
||||
// This is the bulk of the logic for ServeHTTP, broken into its own pure function
|
||||
|
|
|
|||
|
|
@ -13,10 +13,11 @@ import (
|
|||
"github.com/cloudflare/cloudflared/buffer"
|
||||
"github.com/cloudflare/cloudflared/connection"
|
||||
"github.com/cloudflare/cloudflared/ingress"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
||||
"github.com/cloudflare/cloudflared/websocket"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -26,15 +27,15 @@ const (
|
|||
type client struct {
|
||||
ingressRules ingress.Ingress
|
||||
tags []tunnelpogs.Tag
|
||||
logger logger.Service
|
||||
log *zerolog.Logger
|
||||
bufferPool *buffer.Pool
|
||||
}
|
||||
|
||||
func NewClient(ingressRules ingress.Ingress, tags []tunnelpogs.Tag, logger logger.Service) connection.OriginClient {
|
||||
func NewClient(ingressRules ingress.Ingress, tags []tunnelpogs.Tag, log *zerolog.Logger) connection.OriginClient {
|
||||
return &client{
|
||||
ingressRules: ingressRules,
|
||||
tags: tags,
|
||||
logger: logger,
|
||||
log: log,
|
||||
bufferPool: buffer.NewPool(512 * 1024),
|
||||
}
|
||||
}
|
||||
|
|
@ -97,14 +98,14 @@ func (c *client) proxyHTTP(w connection.ResponseWriter, req *http.Request, rule
|
|||
return nil, errors.Wrap(err, "Error writing response header")
|
||||
}
|
||||
if connection.IsServerSentEvent(resp.Header) {
|
||||
c.logger.Debug("Detected Server-Side Events from Origin")
|
||||
c.log.Debug().Msg("Detected Server-Side Events from Origin")
|
||||
c.writeEventStream(w, resp.Body)
|
||||
} else {
|
||||
// Use CopyBuffer, because Copy only allocates a 32KiB buffer, and cross-stream
|
||||
// compression generates dictionary on first write
|
||||
buf := c.bufferPool.Get()
|
||||
defer c.bufferPool.Put(buf)
|
||||
io.CopyBuffer(w, resp.Body, buf)
|
||||
_, _ = io.CopyBuffer(w, resp.Body, buf)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
|
@ -129,7 +130,7 @@ func (c *client) proxyWebsocket(w connection.ResponseWriter, req *http.Request,
|
|||
go func() {
|
||||
// serveCtx is done if req is cancelled, or streamWebsocket returns
|
||||
<-serveCtx.Done()
|
||||
conn.Close()
|
||||
_ = conn.Close()
|
||||
close(connClosedChan)
|
||||
}()
|
||||
|
||||
|
|
@ -159,7 +160,7 @@ func (c *client) writeEventStream(w connection.ResponseWriter, respBody io.ReadC
|
|||
if err != nil {
|
||||
break
|
||||
}
|
||||
w.Write(line)
|
||||
_, _ = w.Write(line)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,46 +172,46 @@ func (c *client) appendTagHeaders(r *http.Request) {
|
|||
|
||||
func (c *client) logRequest(r *http.Request, cfRay string, lbProbe bool, ruleNum int) {
|
||||
if cfRay != "" {
|
||||
c.logger.Debugf("CF-RAY: %s %s %s %s", cfRay, r.Method, r.URL, r.Proto)
|
||||
c.log.Debug().Msgf("CF-RAY: %s %s %s %s", cfRay, r.Method, r.URL, r.Proto)
|
||||
} else if lbProbe {
|
||||
c.logger.Debugf("CF-RAY: %s Load Balancer health check %s %s %s", cfRay, r.Method, r.URL, r.Proto)
|
||||
c.log.Debug().Msgf("CF-RAY: %s Load Balancer health check %s %s %s", cfRay, r.Method, r.URL, r.Proto)
|
||||
} else {
|
||||
c.logger.Debugf("All requests should have a CF-RAY header. Please open a support ticket with Cloudflare. %s %s %s ", r.Method, r.URL, r.Proto)
|
||||
c.log.Debug().Msgf("All requests should have a CF-RAY header. Please open a support ticket with Cloudflare. %s %s %s ", r.Method, r.URL, r.Proto)
|
||||
}
|
||||
c.logger.Debugf("CF-RAY: %s Request Headers %+v", cfRay, r.Header)
|
||||
c.logger.Debugf("CF-RAY: %s Serving with ingress rule %d", cfRay, ruleNum)
|
||||
c.log.Debug().Msgf("CF-RAY: %s Request Headers %+v", cfRay, r.Header)
|
||||
c.log.Debug().Msgf("CF-RAY: %s Serving with ingress rule %d", cfRay, ruleNum)
|
||||
|
||||
if contentLen := r.ContentLength; contentLen == -1 {
|
||||
c.logger.Debugf("CF-RAY: %s Request Content length unknown", cfRay)
|
||||
c.log.Debug().Msgf("CF-RAY: %s Request Content length unknown", cfRay)
|
||||
} else {
|
||||
c.logger.Debugf("CF-RAY: %s Request content length %d", cfRay, contentLen)
|
||||
c.log.Debug().Msgf("CF-RAY: %s Request content length %d", cfRay, contentLen)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *client) logOriginResponse(r *http.Response, cfRay string, lbProbe bool, ruleNum int) {
|
||||
responseByCode.WithLabelValues(strconv.Itoa(r.StatusCode)).Inc()
|
||||
if cfRay != "" {
|
||||
c.logger.Debugf("CF-RAY: %s Status: %s served by ingress %d", cfRay, r.Status, ruleNum)
|
||||
c.log.Info().Msgf("CF-RAY: %s Status: %s served by ingress %d", cfRay, r.Status, ruleNum)
|
||||
} else if lbProbe {
|
||||
c.logger.Debugf("Response to Load Balancer health check %s", r.Status)
|
||||
c.log.Debug().Msgf("Response to Load Balancer health check %s", r.Status)
|
||||
} else {
|
||||
c.logger.Debugf("Status: %s served by ingress %d", r.Status, ruleNum)
|
||||
c.log.Debug().Msgf("Status: %s served by ingress %d", r.Status, ruleNum)
|
||||
}
|
||||
c.logger.Debugf("CF-RAY: %s Response Headers %+v", cfRay, r.Header)
|
||||
c.log.Debug().Msgf("CF-RAY: %s Response Headers %+v", cfRay, r.Header)
|
||||
|
||||
if contentLen := r.ContentLength; contentLen == -1 {
|
||||
c.logger.Debugf("CF-RAY: %s Response content length unknown", cfRay)
|
||||
c.log.Debug().Msgf("CF-RAY: %s Response content length unknown", cfRay)
|
||||
} else {
|
||||
c.logger.Debugf("CF-RAY: %s Response content length %d", cfRay, contentLen)
|
||||
c.log.Debug().Msgf("CF-RAY: %s Response content length %d", cfRay, contentLen)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *client) logRequestError(err error, cfRay string, ruleNum int) {
|
||||
requestErrors.Inc()
|
||||
if cfRay != "" {
|
||||
c.logger.Errorf("CF-RAY: %s Proxying to ingress %d error: %v", cfRay, ruleNum, err)
|
||||
c.log.Error().Msgf("CF-RAY: %s Proxying to ingress %d error: %v", cfRay, ruleNum, err)
|
||||
} else {
|
||||
c.logger.Errorf("Proxying to ingress %d error: %v", ruleNum, err)
|
||||
c.log.Error().Msgf("Proxying to ingress %d error: %v", ruleNum, err)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ import (
|
|||
"github.com/cloudflare/cloudflared/connection"
|
||||
"github.com/cloudflare/cloudflared/hello"
|
||||
"github.com/cloudflare/cloudflared/ingress"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/gobwas/ws/wsutil"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -49,7 +49,7 @@ func (w *mockHTTPRespWriter) WriteRespHeaders(resp *http.Response) error {
|
|||
|
||||
| ||||