go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/client/cmd/swarming/main.go (about)

     1  // Copyright 2015 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  //go:build !copybara
    16  // +build !copybara
    17  
    18  // Package main is a client to a Swarming server.
    19  package main
    20  
    21  import (
    22  	"context"
    23  	"flag"
    24  	"net/http"
    25  	"os"
    26  
    27  	"github.com/bazelbuild/remote-apis-sdks/go/pkg/client"
    28  	"github.com/maruel/subcommands"
    29  
    30  	"go.chromium.org/luci/auth"
    31  	"go.chromium.org/luci/auth/client/authcli"
    32  	"go.chromium.org/luci/client/casclient"
    33  	"go.chromium.org/luci/client/versioncli"
    34  	"go.chromium.org/luci/common/cli"
    35  	"go.chromium.org/luci/common/errors"
    36  	"go.chromium.org/luci/common/logging/gologger"
    37  
    38  	"go.chromium.org/luci/client/cmd/swarming/swarmingimpl"
    39  	"go.chromium.org/luci/swarming/client/swarming"
    40  
    41  	"go.chromium.org/luci/hardcoded/chromeinfra"
    42  )
    43  
    44  type authFlags struct {
    45  	flags       authcli.Flags
    46  	defaultOpts auth.Options
    47  	parsedOpts  *auth.Options
    48  }
    49  
    50  func (af *authFlags) Register(f *flag.FlagSet) {
    51  	af.flags.Register(f, af.defaultOpts)
    52  }
    53  
    54  func (af *authFlags) Parse() error {
    55  	opts, err := af.flags.Options()
    56  	if err != nil {
    57  		return err
    58  	}
    59  	af.parsedOpts = &opts
    60  	return nil
    61  }
    62  
    63  func (af *authFlags) NewHTTPClient(ctx context.Context) (*http.Client, error) {
    64  	if af.parsedOpts == nil {
    65  		return nil, errors.Reason("AuthFlags.Parse() must be called").Err()
    66  	}
    67  	return auth.NewAuthenticator(ctx, auth.OptionalLogin, *af.parsedOpts).Client()
    68  }
    69  
    70  func (af *authFlags) NewRBEClient(ctx context.Context, addr string, instance string) (*client.Client, error) {
    71  	if af.parsedOpts == nil {
    72  		return nil, errors.Reason("AuthFlags.Parse() must be called").Err()
    73  	}
    74  	return casclient.NewLegacy(ctx, addr, instance, *af.parsedOpts, true)
    75  }
    76  
    77  func getApplication() *cli.Application {
    78  	authOpts := chromeinfra.DefaultAuthOptions()
    79  	af := &authFlags{defaultOpts: authOpts}
    80  
    81  	return &cli.Application{
    82  		Name:  "swarming",
    83  		Title: "Client tool to access a swarming server.",
    84  
    85  		// Note: this decouples logging implementation from subcommands
    86  		// implementation. Useful when reusing subcommands in g3.
    87  		Context: func(ctx context.Context) context.Context {
    88  			return gologger.StdConfig.Use(ctx)
    89  		},
    90  
    91  		// Keep in alphabetical order of their name.
    92  		Commands: []*subcommands.Command{
    93  			subcommands.Section("Tasks\n"),
    94  			swarmingimpl.CmdCancelTask(af),
    95  			swarmingimpl.CmdCancelTasks(af),
    96  			swarmingimpl.CmdCollect(af),
    97  			swarmingimpl.CmdReproduce(af),
    98  			swarmingimpl.CmdRequestShow(af),
    99  			swarmingimpl.CmdSpawnTasks(af),
   100  			swarmingimpl.CmdTasks(af),
   101  			swarmingimpl.CmdTrigger(af),
   102  			subcommands.Section("Bots\n"),
   103  			swarmingimpl.CmdBots(af),
   104  			swarmingimpl.CmdDeleteBots(af),
   105  			swarmingimpl.CmdTerminateBot(af),
   106  			swarmingimpl.CmdBotTasks(af),
   107  			subcommands.Section("Other\n"),
   108  			subcommands.CmdHelp,
   109  			authcli.SubcommandInfo(authOpts, "whoami", false),
   110  			authcli.SubcommandLogin(authOpts, "login", false),
   111  			authcli.SubcommandLogout(authOpts, "logout", false),
   112  			versioncli.CmdVersion(swarming.UserAgent),
   113  		},
   114  
   115  		EnvVars: map[string]subcommands.EnvVarDefinition{
   116  			swarming.ServerEnvVar: {
   117  				ShortDesc: "URL or a hostname of a Swarming server to use by default when omitting -server or -S flag",
   118  			},
   119  			swarming.UserEnvVar: {
   120  				ShortDesc: "used as \"user\" field in spawned Swarming tasks",
   121  			},
   122  			swarming.TaskIDEnvVar: {
   123  				Advanced: true,
   124  				ShortDesc: "set when running within a Swarming task to ID of that task; " +
   125  					"used as \"parent_task_id\" field in spawned Swarming tasks",
   126  			},
   127  		},
   128  	}
   129  }
   130  
   131  func main() {
   132  	os.Exit(subcommands.Run(getApplication(), nil))
   133  }