blob: 175dfa318de7a5e416f2ddebff535b3a10a3d292 [file] [log] [blame]
// Copyright 2021 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 device
import (
"context"
"fmt"
"strings"
"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/util"
"go.fuchsia.dev/fuchsia/tools/lib/logger"
)
type DeviceResolver interface {
Name() string
ResolveName(ctx context.Context) (string, error)
}
type ConstantHostResolver struct {
name string
host string
}
func NewConstantHostResolver(name string, host string) ConstantHostResolver {
return ConstantHostResolver{
name: name,
host: host,
}
}
func (r ConstantHostResolver) Name() string {
return r.name
}
func (r ConstantHostResolver) ResolveName(ctx context.Context) (string, error) {
return r.host, nil
}
// The logic here should match get-fuchsia-device-addr (//tools/devshell/lib/vars.sh).
type DeviceFinderResolver struct {
deviceFinderPath string
deviceName string
}
func NewDeviceFinderResolver(ctx context.Context, deviceFinderPath string, deviceName string) (*DeviceFinderResolver, error) {
if deviceName == "" {
var err error
var deviceList string
deviceList, err = deviceFinder(
ctx,
deviceFinderPath,
"list",
"-ipv4=false",
"-timeout=5s",
"-full",
)
if err != nil {
return nil, fmt.Errorf("ERROR: Failed to list devices: %w", err)
}
if strings.Contains(deviceList, "\n") {
return nil, fmt.Errorf("ERROR: Found multiple devices. Use -device to specify one.")
}
// Device finder (with -full) outputs in the format "<address> <domain>".
var entry = strings.Split(deviceList, " ")
if len(entry) != 2 {
return nil, fmt.Errorf("ERROR: device-finder return unexpected output: %s.", deviceList)
}
deviceName = entry[1]
if deviceName == "" {
return nil, fmt.Errorf("unable to determine the device name")
}
}
return &DeviceFinderResolver{
deviceFinderPath: deviceFinderPath,
deviceName: deviceName,
}, nil
}
func (r *DeviceFinderResolver) Name() string {
return r.deviceName
}
func (r *DeviceFinderResolver) ResolveName(ctx context.Context) (string, error) {
deviceHostname, err := deviceFinder(
ctx,
r.deviceFinderPath,
"resolve",
"-ipv4=false",
"-timeout=5s",
"-device-limit=1",
r.deviceName,
)
if err != nil {
return "", fmt.Errorf("ERROR: Failed to resolve device name %q: %w", r.deviceName, err)
}
logger.Infof(ctx, "resolved %q to %q", r.deviceName, deviceHostname)
if deviceHostname == "" {
return "", fmt.Errorf("unable to determine the device hostname")
}
return deviceHostname, nil
}
func deviceFinder(ctx context.Context, deviceFinderPath string, arg ...string) (string, error) {
stdout, stderr, err := util.RunCommand(ctx, deviceFinderPath, arg...)
if err != nil {
return "", fmt.Errorf("device-finder failed: %w: %s", err, string(stderr))
}
return strings.TrimRight(string(stdout), "\n"), nil
}