go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/gce/cmd/agent/connect.go (about)

     1  // Copyright 2018 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  package main
    16  
    17  import (
    18  	"context"
    19  	"runtime"
    20  
    21  	"github.com/maruel/subcommands"
    22  
    23  	"go.chromium.org/luci/common/cli"
    24  	"go.chromium.org/luci/common/errors"
    25  
    26  	"go.chromium.org/luci/gce/api/instances/v1"
    27  )
    28  
    29  // connectCmd is the command to connect to a Swarming server.
    30  type connectCmd struct {
    31  	cmdRunBase
    32  	// dir is the path to use as the Swarming bot directory.
    33  	dir string
    34  	// server is the Swarming server URL to connect to.
    35  	server string
    36  	// provider is the Provider server URL to retrieve the Swarming server URL from.
    37  	provider string
    38  	// user is the name of the local user to start the Swarming bot process as.
    39  	user string
    40  	// python is the path to the python to start the Swarming bot process.
    41  	python string
    42  }
    43  
    44  // validateFlags validates parsed command line flags.
    45  func (cmd *connectCmd) validateFlags(c context.Context) error {
    46  	switch {
    47  	case cmd.dir == "":
    48  		return errors.New("-dir is required")
    49  	// TODO(crbug/945063): Remove -server.
    50  	case cmd.provider == "" && cmd.server == "":
    51  		return errors.New("-provider or -server is required")
    52  	case cmd.user == "":
    53  		return errors.New("-user is required")
    54  	}
    55  	return nil
    56  }
    57  
    58  // Run runs the command to connect to a Swarming server.
    59  func (cmd *connectCmd) Run(app subcommands.Application, args []string, env subcommands.Env) int {
    60  	c := cli.GetContext(app, cmd, env)
    61  	if err := cmd.run(c, args, env); err != nil {
    62  		errors.Log(c, err)
    63  		return 1
    64  	}
    65  	return 0
    66  }
    67  
    68  func (cmd *connectCmd) run(c context.Context, args []string, env subcommands.Env) error {
    69  	if err := cmd.validateFlags(c); err != nil {
    70  		return err
    71  	}
    72  	if cmd.server == ":metadata" {
    73  		meta := getMetadata(c)
    74  		srv, err := meta.Get("instance/attributes/swarming-server")
    75  		if err != nil {
    76  			return err
    77  		}
    78  		cmd.server = srv
    79  	}
    80  	if cmd.provider != "" {
    81  		meta := getMetadata(c)
    82  		name, err := meta.InstanceName()
    83  		if err != nil {
    84  			return err
    85  		}
    86  		if cmd.provider == ":metadata" {
    87  			cmd.provider, err = meta.Get("instance/attributes/provider")
    88  			if err != nil {
    89  				return err
    90  			}
    91  		}
    92  		prov, err := newInstances(c, cmd.serviceAccount, cmd.provider)
    93  		if err != nil {
    94  			return err
    95  		}
    96  		inst, err := prov.Get(c, &instances.GetRequest{
    97  			Hostname: name,
    98  		})
    99  		if err != nil {
   100  			return err
   101  		}
   102  		cmd.server = inst.Swarming
   103  	}
   104  
   105  	swr := getSwarming(c)
   106  	swr.server = cmd.server
   107  	if err := swr.Configure(c, cmd.dir, cmd.user, cmd.python); err != nil {
   108  		return err
   109  	}
   110  	return nil
   111  }
   112  
   113  // defaultFlagPython returns the default python that runs Swarming bot process.
   114  func defaultFlagPython() string {
   115  	if runtime.GOOS == "windows" {
   116  		return "C:\\tools\\python\\bin\\python.exe"
   117  	} else {
   118  		return "/usr/bin/python"
   119  	}
   120  }
   121  
   122  // newConnectCmd returns a new command to connect to a Swarming server.
   123  func newConnectCmd() *subcommands.Command {
   124  	return &subcommands.Command{
   125  		UsageLine: "connect -dir <path> -server <server> -user <name>",
   126  		ShortDesc: "connects to a swarming server",
   127  		LongDesc:  "Connects to a Swarming server.",
   128  		CommandRun: func() subcommands.CommandRun {
   129  			cmd := &connectCmd{}
   130  			cmd.Initialize()
   131  			cmd.Flags.StringVar(&cmd.dir, "dir", "", "Path to use as the Swarming bot directory.")
   132  			cmd.Flags.StringVar(&cmd.provider, "provider", "", "Provider server URL to retrieve Swarming server URL from.")
   133  			cmd.Flags.StringVar(&cmd.server, "server", "", "Deprecated. Use -provider.")
   134  			cmd.Flags.StringVar(&cmd.user, "user", "", "Name of the local user to start the Swarming bot process as.")
   135  			cmd.Flags.StringVar(&cmd.python, "python", defaultFlagPython(), "Path to the python to start the Swarming bot process.")
   136  			return cmd
   137  		},
   138  	}
   139  }