TUN-3470: Replace in-house logger calls with zerolog

This commit is contained in:
Areg Harutyunyan
2020-11-25 00:55:13 -06:00
committed by Adam Chalmers
parent 06404bf3e8
commit 870f5fa907
151 changed files with 7120 additions and 3365 deletions

View File

@@ -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
}

View File

@@ -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")
}

View File

@@ -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)
}

View File

@@ -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()
}

View File

@@ -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{}{}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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")
}

View File

@@ -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
}

View File

@@ -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`)
}

View File

@@ -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"),

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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,

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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() {

View File

@@ -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