From 589b2d4342d4f066190170cd723e49c602252203 Mon Sep 17 00:00:00 2001 From: Yaowen Mei Date: Thu, 1 Aug 2024 20:00:43 +0000 Subject: [PATCH 1/2] Update doc for how to re-run an action with another RBE instance. This CL update the readme file to show how to re-run an action on another RBE instance. This CL also fix the flag conflict issue, for execute_action, one and only one of these two flags should be set: [--action_root=PATH|--digest=DIGEST]. --- go/README.md | 38 +++++++++++++++++++++++++++++++++++++ go/pkg/tool/embeddedtool.go | 20 +++++++++++++++---- go/pkg/tool/tool.go | 5 +++-- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/go/README.md b/go/README.md index 472d867dd..4634b1086 100644 --- a/go/README.md +++ b/go/README.md @@ -12,6 +12,14 @@ Flags that describe the RBE instance used and the authentication method are comm `--alsologtostderr` and `-v VERBOSITY_LEVEL` can be used to tune the verbosity and location of the output, e.g. `--alsologtosrderr -v 1`. +For example, the common flags could be: + +``` + --service remotebuildexecution.googleapis.com:443 \ + --use_application_default_credentials=true \ + --alsologtostderr \ + --v 1 +``` #### Downloading an action's inputs and metadata ``` bazelisk run //go/cmd/remotetool -- \ @@ -42,6 +50,36 @@ bazelisk run //go/cmd/remotetool -- \ - An action digest formatted as `"{hash}/{size}"` can be provided directly using the `--digest` flag, or a previously downloaded action can be used with `--action_root`. The `--action_root` path should point to the `--path` of a previous `download_action` invocation. Specifically, the `--action_root` folder must contain a `cmd.textproto` and `ac.textproto` files. - `--path` is the destination where the outputs of the action will be downloaded +#### Re-running a downloaded action remotely on a different RBE instance + +If you want to download an action from an RBE instance `FOO`, and remotely +execute it on another RBE instance `BAR` (probably because you only have the +permission to download actions from `FOO`, but lack of permission to don't have +the permission to execute an action with instance `FOO`). In this case, you want +to download the action first, and then re-run it on another RBE instance with +`--instance` and `--action_root` flags. + +1. download the action from instance `FOO` to dir `/tmp/out/downloaded_action` + +``` +bazelisk run //go/cmd/remotetool -- \ + --operation download_action \ + --instance=FOO \ + --digest=DIGEST + COMMON_FLAGS + --path /tmp/out/downloaded_action +``` +2. run the downloaded action with another RBE instance `BAR` +``` +bazelisk run //go/cmd/remotetool -- \ + --operation execute_action \ + --instance=BAR \ + --action_root /tmp/out/downloaded_action \ + COMMON_FLAGS + --path /tmp/output_file_path +``` + + #### Running a modified version of a downloaded action 1. Download an action to a given `PATH` following the [instructions for downloading an action](#downloading-an-actions-inputs-and-metadata), diff --git a/go/pkg/tool/embeddedtool.go b/go/pkg/tool/embeddedtool.go index 44ab4ef1f..79ffb5629 100644 --- a/go/pkg/tool/embeddedtool.go +++ b/go/pkg/tool/embeddedtool.go @@ -27,10 +27,10 @@ var ( // RegisterFlags registers the flags necessary for the embedded tool to work. func RegisterFlags() { - flag.StringVar(&inputDigest, "digest", "", "Digest in format.") + flag.StringVar(&inputDigest, "digest", "", "Digest in format. This flag should not be provided if action_root is set.") flag.StringVar(&pathPrefix, "path", "", "Path to which outputs should be downloaded to.") flag.BoolVar(&overwrite, "overwrite", false, "Overwrite the output path if it already exist.") - flag.StringVar(&actionRoot, "action_root", "", "For execute_action: the root of the action spec, containing ac.textproto (Action proto), cmd.textproto (Command proto), and input/ (root of the input tree).") + flag.StringVar(&actionRoot, "action_root", "", "For execute_action: the root of the action spec, containing ac.textproto (Action proto), cmd.textproto (Command proto), and input/ (root of the input tree). This flag should not be provided if digest is set.") flag.IntVar(&execAttempts, "exec_attempts", 10, "For check_determinism: the number of times to remotely execute the action and check for mismatches.") flag.StringVar(&jsonOutput, "json", "", "Path to output operation result as JSON. Currently supported for \"upload_dir\", and includes various upload metadata (see UploadStats).") } @@ -99,12 +99,14 @@ var RemoteToolOperations = map[OpType]func(ctx context.Context, c *Client){ fmt.Printf("Action downloaded to %v\n", getPathFlag()) }, executeAction: func(ctx context.Context, c *Client) { - if _, err := c.ExecuteAction(ctx, getDigestFlag(), actionRoot, getPathFlag(), outerr.SystemOutErr); err != nil { + dg, root := validateActionRootAndDg() + if _, err := c.ExecuteAction(ctx, dg, root, getPathFlag(), outerr.SystemOutErr); err != nil { log.Exitf("error executing action: %v", err) } }, checkDeterminism: func(ctx context.Context, c *Client) { - if err := c.CheckDeterminism(ctx, getDigestFlag(), actionRoot, execAttempts); err != nil { + dg, root := validateActionRootAndDg() + if err := c.CheckDeterminism(ctx, dg, root, execAttempts); err != nil { log.Exitf("error checking determinism: %v", err) } }, @@ -157,3 +159,13 @@ func getPathFlag() string { } return pathPrefix } + +func validateActionRootAndDg() (string, string) { + if inputDigest != "" && actionRoot != "" { + log.Exitf("either specify --digest or --action_root, should not set both of them together.") + } + if inputDigest == "" && actionRoot == "" { + log.Exitf("either specify --digest or --action_root, at least one of these two flag must be set.") + } + return inputDigest, actionRoot +} diff --git a/go/pkg/tool/tool.go b/go/pkg/tool/tool.go index 604a0c71b..715f04bb9 100644 --- a/go/pkg/tool/tool.go +++ b/go/pkg/tool/tool.go @@ -6,6 +6,7 @@ import ( "bufio" "bytes" "context" + "errors" "fmt" "os" "path/filepath" @@ -13,7 +14,6 @@ import ( "strings" "time" - "errors" log "github.com/golang/glog" "golang.org/x/sync/errgroup" "google.golang.org/protobuf/encoding/prototext" @@ -98,7 +98,7 @@ func (c *Client) prepCommand(ctx context.Context, client *rexec.Client, actionDi return nil, err } - log.Infof("Reading command from action digest..") + log.Infof("Reading command from action digest: %v", acDg) if _, err := c.GrpcClient.ReadProto(ctx, cmdDg, commandProto); err != nil { return nil, err } @@ -656,6 +656,7 @@ func (c *Client) ExecuteAction(ctx context.Context, actionDigest, actionRoot, ou case command.LocalErrorResultStatus: oe.WriteErr([]byte(fmt.Sprintf("Local error: %v.\n", ec.Result.Err))) } + fmt.Printf("Result: %+v\n", ec.Result) if ec.Result.Err == nil && outDir != "" { ec.DownloadOutputs(outDir) fmt.Printf("Output written to %v\n", outDir) From bb088870f80fe415a1baf5995edfba1b2c32cd35 Mon Sep 17 00:00:00 2001 From: Yaowen Mei Date: Tue, 6 Aug 2024 15:31:02 +0000 Subject: [PATCH 2/2] Update doc for how to re-run an action with another RBE instance. This CL update the readme file to show how to re-run an action on another RBE instance. This CL also fix the flag conflict issue, for execute_action, one and only one of these two flags should be set: [--action_root=PATH|--digest=DIGEST]. --- go/README.md | 6 +++--- go/pkg/tool/embeddedtool.go | 13 ++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/go/README.md b/go/README.md index 4634b1086..6efc586bc 100644 --- a/go/README.md +++ b/go/README.md @@ -54,9 +54,9 @@ bazelisk run //go/cmd/remotetool -- \ If you want to download an action from an RBE instance `FOO`, and remotely execute it on another RBE instance `BAR` (probably because you only have the -permission to download actions from `FOO`, but lack of permission to don't have -the permission to execute an action with instance `FOO`). In this case, you want -to download the action first, and then re-run it on another RBE instance with +permission to download actions from `FOO`, but don't have the permission to +execute that instance). In this case, you want to download the action first, and +then re-run it on another RBE instance with `--instance` and `--action_root` flags. 1. download the action from instance `FOO` to dir `/tmp/out/downloaded_action` diff --git a/go/pkg/tool/embeddedtool.go b/go/pkg/tool/embeddedtool.go index 79ffb5629..23009f2f9 100644 --- a/go/pkg/tool/embeddedtool.go +++ b/go/pkg/tool/embeddedtool.go @@ -99,14 +99,14 @@ var RemoteToolOperations = map[OpType]func(ctx context.Context, c *Client){ fmt.Printf("Action downloaded to %v\n", getPathFlag()) }, executeAction: func(ctx context.Context, c *Client) { - dg, root := validateActionRootAndDg() - if _, err := c.ExecuteAction(ctx, dg, root, getPathFlag(), outerr.SystemOutErr); err != nil { + validateActionRootAndDg() + if _, err := c.ExecuteAction(ctx, inputDigest, actionRoot, getPathFlag(), outerr.SystemOutErr); err != nil { log.Exitf("error executing action: %v", err) } }, checkDeterminism: func(ctx context.Context, c *Client) { - dg, root := validateActionRootAndDg() - if err := c.CheckDeterminism(ctx, dg, root, execAttempts); err != nil { + validateActionRootAndDg() + if err := c.CheckDeterminism(ctx, inputDigest, actionRoot, execAttempts); err != nil { log.Exitf("error checking determinism: %v", err) } }, @@ -160,12 +160,11 @@ func getPathFlag() string { return pathPrefix } -func validateActionRootAndDg() (string, string) { +func validateActionRootAndDg() { if inputDigest != "" && actionRoot != "" { log.Exitf("either specify --digest or --action_root, should not set both of them together.") } if inputDigest == "" && actionRoot == "" { - log.Exitf("either specify --digest or --action_root, at least one of these two flag must be set.") + log.Exitf("either specify --digest or --action_root, one of these flags must be set, but not both.") } - return inputDigest, actionRoot }