// NewPushBuffer returns PushBuffer that's ready to accept log entries. func NewPushBuffer(opts PushBufferOptions) PushBuffer { if opts.Logger == nil { opts.Logger = logging.Null() } if opts.Clock == nil { opts.Clock = clock.GetSystemClock() } if opts.FlushThreshold == 0 { opts.FlushThreshold = DefaultFlushThreshold } if opts.FlushTimeout == 0 { opts.FlushTimeout = DefaultFlushTimeout } if opts.MaxPushAttempts == 0 { opts.MaxPushAttempts = DefaultMaxPushAttempts } if opts.PushRetryDelay == 0 { opts.PushRetryDelay = DefaultPushRetryDelay } if opts.StopTimeout == 0 { opts.StopTimeout = DefaultStopTimeout } buf := &pushBufferImpl{ PushBufferOptions: opts, input: make(chan []Entry), output: make(chan error), timer: opts.Clock.NewTimer(), stopCh: make(chan struct{}, 1), } go buf.loop() return buf }
// NewClient initializes CIPD client object. func NewClient(opts ClientOptions) Client { if opts.ServiceURL == "" { opts.ServiceURL = ServiceURL } if opts.Logger == nil { opts.Logger = logging.Null() } if opts.AnonymousClientFactory == nil { opts.AnonymousClientFactory = func() (*http.Client, error) { return http.DefaultClient, nil } } if opts.AuthenticatedClientFactory == nil { opts.AuthenticatedClientFactory = opts.AnonymousClientFactory } if opts.UserAgent == "" { opts.UserAgent = UserAgent } c := &clientImpl{ ClientOptions: opts, clock: &clockImpl{}, } c.remote = &remoteImpl{c} c.storage = &storageImpl{c, uploadChunkSize} c.deployer = local.NewDeployer(opts.Root, opts.Logger) return c }
// NewFileSystem returns default FileSystem implementation that operates with // files under a given path. All methods accept absolute paths or paths relative // to current working directory. FileSystem will ensure they are under 'root' // directory. func NewFileSystem(root string, logger logging.Logger) FileSystem { if logger == nil { logger = logging.Null() } abs, err := filepath.Abs(root) if err != nil { return &fsImplErr{err} } return &fsImpl{abs, logger} }
// NewDeployer return default Deployer implementation. func NewDeployer(root string, logger logging.Logger) Deployer { var err error if root == "" { err = fmt.Errorf("Site root path is not provided") } else { root, err = filepath.Abs(filepath.Clean(root)) } if err != nil { return errDeployer{err} } if logger == nil { logger = logging.Null() } return &deployerImpl{NewFileSystem(root, logger), logger} }
// NewGroupsService constructs new instance of GroupsService that talks to given // service URL via given http.Client. If url is empty string, the default // backend will be used. If httpClient is nil, http.DefaultClient will be used. func NewGroupsService(url string, client *http.Client, logger logging.Logger) *GroupsService { if url == "" { url = ServiceURL } if client == nil { client = http.DefaultClient } if logger == nil { logger = logging.Null() } return &GroupsService{ client: client, serviceURL: url, logger: logger, } }
func TestDrainChannel(t *testing.T) { Convey("Works", t, func() { client := &fakeClient{} buf := NewPushBuffer(PushBufferOptions{Client: client}) ch := make(chan string) go func() { ch <- "normal line" ch <- " to be trimmed " // Empty lines are skipped. ch <- "" ch <- " " close(ch) }() drainChannel(ch, NullParser(), buf, nil) So(buf.Stop(nil), ShouldBeNil) text := []string{} for _, e := range client.getEntries() { text = append(text, e.TextPayload) } So(text, ShouldResemble, []string{"normal line", "to be trimmed"}) }) Convey("Rejects unparsed lines", t, func() { client := &fakeClient{} buf := NewPushBuffer(PushBufferOptions{Client: client}) parser := &callbackParser{ cb: func(string) *Entry { return nil }, } ch := make(chan string) go func() { ch <- "normal line" close(ch) }() drainChannel(ch, parser, buf, logging.Null()) So(buf.Stop(nil), ShouldBeNil) So(len(client.getEntries()), ShouldEqual, 0) }) }
// NewClient returns new object that knows how to push log entries to a single // log in Cloud Logging. func NewClient(opts ClientOptions) (Client, error) { if opts.Logger == nil { opts.Logger = logging.Null() } if opts.ProjectID == "" { return nil, fmt.Errorf("no ProjectID is provided") } if opts.ResourceType == "" { opts.ResourceType = DefaultResourceType } if opts.ResourceID == "" { var err error hostname, err := os.Hostname() if err != nil { return nil, err } opts.ResourceID = hostname } if opts.LogID == "" { return nil, fmt.Errorf("no LogID is provided") } service, err := cloudlog.New(opts.Client) if err != nil { return nil, err } service.UserAgent = opts.UserAgent return &loggingClient{ opts: opts, commonLabels: map[string]string{ "compute.googleapis.com/resource_id": opts.ResourceID, "compute.googleapis.com/resource_type": opts.ResourceType, }, serviceName: "compute.googleapis.com", writeFunc: func(projID, logID string, req *cloudlog.WriteLogEntriesRequest) error { _, err := service.Projects.Logs.Entries.Write(projID, logID, req).Do() return err }, }, nil }
// NewTailer spawn a goroutine that watches a file for changes and pushes // new lines to the buffer. func NewTailer(opts TailerOptions) (Tailer, error) { if opts.Parser == nil { opts.Parser = StdParser() } if opts.Logger == nil { opts.Logger = logging.Null() } var seekInfo *tail.SeekInfo if opts.SeekToEnd { seekInfo = &tail.SeekInfo{Offset: 0, Whence: os.SEEK_END} } tailer, err := tail.TailFile(opts.Path, tail.Config{ Location: seekInfo, ReOpen: true, MustExist: false, Follow: true, Logger: tail.DiscardingLogger, }) if err != nil { return nil, err } // tailer.Lines -> source -> PushBuffer (in drainChannel). source := make(chan string) go func() { defer close(source) for tailLine := range tailer.Lines { if tailLine.Err != nil { opts.Logger.Errorf("tail error: %s", tailLine.Err) continue } source <- tailLine.Text } }() go drainChannel(source, opts.Parser, opts.PushBuffer, opts.Logger) return tailer, nil }
// BuildInstance builds a new package instance for package named opts.PackageName // by archiving input files (passed via opts.Input). The final binary is written // to opts.Output. Some output may be written even if BuildInstance eventually // returns an error. func BuildInstance(opts BuildInstanceOptions) error { if opts.Logger == nil { opts.Logger = logging.Null() } err := common.ValidatePackageName(opts.PackageName) if err != nil { return err } // Make sure no files are written to package service directory. for _, f := range opts.Input { if strings.HasPrefix(f.Name(), packageServiceDir+"/") { return fmt.Errorf("Can't write to %s: %s", packageServiceDir, f.Name()) } } // Generate the manifest file, add to the list of input files. manifestFile, err := makeManifestFile(opts) if err != nil { return err } files := append(opts.Input, manifestFile) // Make sure filenames are unique. seenNames := make(map[string]struct{}, len(files)) for _, f := range files { _, seen := seenNames[f.Name()] if seen { return fmt.Errorf("File %s is provided twice", f.Name()) } seenNames[f.Name()] = struct{}{} } // Write the final zip file. return zipInputFiles(files, opts.Output, opts.Logger) }
"net/http" "os" "path/filepath" "testing" "golang.org/x/net/context" . "github.com/smartystreets/goconvey/convey" "github.com/luci/luci-go/common/auth/internal" "github.com/luci/luci-go/common/logging" ) var ( ctx = context.Background() log = logging.Null() ) func ExampleDefaultAuthenticatedClient() { client, err := AuthenticatedClient(SilentLogin, NewAuthenticator(Options{})) if err == ErrLoginRequired { log.Errorf("Run 'auth login' to login") return } if err != nil { log.Errorf("Failed to login: %s", err) return } _, _ = client.Get("https://some-server.appspot.com") }