blob: ba0da5b712177523bea62a8b9bfa0ef0a3b8b802 [file] [log] [blame]
// Copyright 2015 The LUCI Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package main
import (
"errors"
"flag"
"fmt"
"net/http"
"path/filepath"
"github.com/maruel/subcommands"
"golang.org/x/net/context"
"github.com/luci/luci-go/client/authcli"
"github.com/luci/luci-go/client/internal/common"
"github.com/luci/luci-go/client/isolate"
"github.com/luci/luci-go/common/auth"
"github.com/luci/luci-go/common/isolatedclient"
"github.com/luci/luci-go/common/logging/gologger"
)
type commonFlags struct {
subcommands.CommandRunBase
defaultFlags common.Flags
}
func (c *commonFlags) Init() {
c.defaultFlags.Init(&c.Flags)
}
func (c *commonFlags) Parse() error {
return c.defaultFlags.Parse()
}
type commonServerFlags struct {
commonFlags
isolatedFlags isolatedclient.Flags
authFlags authcli.Flags
parsedAuthOpts auth.Options
}
func (c *commonServerFlags) Init(authOpts auth.Options) {
c.commonFlags.Init()
c.isolatedFlags.Init(&c.Flags)
c.authFlags.Register(&c.Flags, authOpts)
}
func (c *commonServerFlags) Parse() error {
var err error
if err = c.commonFlags.Parse(); err != nil {
return err
}
if err = c.isolatedFlags.Parse(); err != nil {
return err
}
c.parsedAuthOpts, err = c.authFlags.Options()
return err
}
func (c *commonServerFlags) createAuthClient() (*http.Client, error) {
// Don't enforce authentication by using OptionalLogin mode. This is needed
// for IP whitelisted bots: they have NO credentials to send.
ctx := gologger.StdConfig.Use(context.Background())
return auth.NewAuthenticator(ctx, auth.OptionalLogin, c.parsedAuthOpts).Client()
}
type isolateFlags struct {
// TODO(tandrii): move ArchiveOptions from isolate pkg to here.
isolate.ArchiveOptions
}
func (c *isolateFlags) Init(f *flag.FlagSet) {
c.ArchiveOptions.Init()
f.StringVar(&c.Isolate, "isolate", "", ".isolate file to load the dependency data from")
f.StringVar(&c.Isolate, "i", "", "Alias for --isolate")
f.StringVar(&c.Isolated, "isolated", "", ".isolated file to generate or read")
f.StringVar(&c.Isolated, "s", "", "Alias for --isolated")
f.Var(&c.Blacklist, "blacklist", "List of regexp to use as blacklist filter when uploading directories")
f.Var(&c.ConfigVariables, "config-variable", "Config variables are used to determine which conditions should be matched when loading a .isolate file, default: [].")
f.Var(&c.PathVariables, "path-variable", "Path variables are used to replace file paths when loading a .isolate file, default: {}")
f.Var(&c.ExtraVariables, "extra-variable", "Extraneous variables are replaced on the command entry and on paths in the .isolate file but are not considered relative paths.")
}
// RequiredIsolateFlags specifies which flags are required on the command line
// being parsed.
type RequiredIsolateFlags uint
const (
// RequireIsolateFile means the --isolate flag is required.
RequireIsolateFile RequiredIsolateFlags = 1 << iota
// RequireIsolatedFile means the --isolated flag is required.
RequireIsolatedFile
)
func (c *isolateFlags) Parse(cwd string, flags RequiredIsolateFlags) error {
if !filepath.IsAbs(cwd) {
return errors.New("cwd must be absolute path")
}
for _, vars := range [](map[string]string){c.ConfigVariables, c.ExtraVariables, c.PathVariables} {
for k := range vars {
if !isolate.IsValidVariable(k) {
return fmt.Errorf("invalid key %s", k)
}
}
}
if c.Isolate == "" {
if flags&RequireIsolateFile != 0 {
return errors.New("-isolate must be specified")
}
} else {
if !filepath.IsAbs(c.Isolate) {
c.Isolate = filepath.Clean(filepath.Join(cwd, c.Isolate))
}
}
if c.Isolated == "" {
if flags&RequireIsolatedFile != 0 {
return errors.New("-isolated must be specified")
}
} else {
if !filepath.IsAbs(c.Isolated) {
c.Isolated = filepath.Clean(filepath.Join(cwd, c.Isolated))
}
}
return nil
}
// loggingFlags configures eventlog logging.
type loggingFlags struct {
EventlogEndpoint string
}
func (lf *loggingFlags) Init(f *flag.FlagSet) {
f.StringVar(&lf.EventlogEndpoint, "eventlog-endpoint", "", `The URL destination for eventlogs. The special values "prod" or "test" may be used to target the standard prod or test urls repspectively. An empty string disables eventlogging.`)
}