Пример #1
0
// 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
}
Пример #2
0
// 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
}
Пример #3
0
// 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}
}
Пример #4
0
// 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}
}
Пример #5
0
// 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,
	}
}
Пример #6
0
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)
	})
}
Пример #7
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
}
Пример #8
0
// 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
}
Пример #9
0
// 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)
}
Пример #10
0
	"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")
}