blob: 207bc7d98738d3ffa125e564b8ae59099414c73c [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package script
import (
"context"
"fmt"
"os"
"os/exec"
"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/device"
"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/packages"
"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/sl4f"
"go.fuchsia.dev/fuchsia/tools/lib/logger"
)
// RunScript runs a script on the device and returns the result. It's possible
// this script could reboot the device, so to help with connection management,
// this function optionally takes a pointer to an sl4f.Client. If specified,
// this client will be closed, and the pointer will be updated to a new
// sl4f.Client after the script completes.
func RunScript(
ctx context.Context,
device *device.Client,
repo *packages.Repository,
rpcClient **sl4f.Client,
script string,
) error {
if script == "" {
return nil
}
ch := device.DisconnectionListener()
logger.Debugf(ctx, "running script: %s", script)
cmd := exec.CommandContext(ctx, "/bin/sh", "-c", script)
cmd.Env = os.Environ()
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("script %v failed to run: %w", script, err)
}
// Reconnect to sl4f if we disconnected.
//
// FIXME(47145) To avoid fxbug.dev/47145, we need to delay
// disconnecting from sl4f until after we reboot the device. Otherwise
// we risk leaving the ssh session in a bad state.
if rpcClient != nil && *rpcClient != nil {
select {
case <-ch:
var err error
(*rpcClient).Close()
*rpcClient, err = device.StartRpcSession(ctx, repo)
if err != nil {
return fmt.Errorf("unable to connect to sl4f after running script: %w", err)
}
default:
}
}
return nil
}