blob: 8e43157aabec2fb5a28583a6f4c3b7abb17823b1 [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 config
import (
"context"
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"golang.org/x/crypto/ssh"
"fuchsia.googlesource.com/host_target_testing/device"
"fuchsia.googlesource.com/host_target_testing/util"
)
type DeviceConfig struct {
sshKeyFile string
netaddrPath string
DeviceName string
deviceHostname string
sshPrivateKey ssh.Signer
}
func NewDeviceConfig(fs *flag.FlagSet) *DeviceConfig {
c := &DeviceConfig{}
testDataPath := filepath.Join(filepath.Dir(os.Args[0]), "test_data", "system-tests")
fs.StringVar(&c.sshKeyFile, "ssh-private-key", os.Getenv("FUCHSIA_SSH_KEY"), "SSH private key file that can access the device")
fs.StringVar(&c.DeviceName, "device", os.Getenv("FUCHSIA_NODENAME"), "device name")
fs.StringVar(&c.deviceHostname, "device-hostname", os.Getenv("FUCHSIA_IPV4_ADDR"), "device hostname or IPv4/IPv6 address")
fs.StringVar(&c.netaddrPath, "netaddr-path", filepath.Join(testDataPath, "netaddr"), "zircon netaddr tool path")
return c
}
func (c *DeviceConfig) DeviceHostname(ctx context.Context) (string, error) {
if c.deviceHostname == "" {
var err error
c.deviceHostname, err = c.netaddr(ctx, "--nowait", "--timeout=1000", "--fuchsia", c.DeviceName)
if err != nil {
return "", fmt.Errorf("ERROR: netaddr failed: %s", err)
}
if c.deviceHostname == "" {
return "", fmt.Errorf("unable to determine the device hostname")
}
}
return c.deviceHostname, nil
}
func (c *DeviceConfig) netaddr(ctx context.Context, arg ...string) (string, error) {
stdout, stderr, err := util.RunCommand(ctx, c.netaddrPath, arg...)
if err != nil {
return "", fmt.Errorf("netaddr failed: %s: %s", err, string(stderr))
}
return strings.TrimRight(string(stdout), "\n"), nil
}
func (c *DeviceConfig) SSHPrivateKey() (ssh.Signer, error) {
if c.sshPrivateKey == nil {
if c.sshKeyFile == "" {
return nil, fmt.Errorf("ssh private key cannot be empty")
}
key, err := ioutil.ReadFile(c.sshKeyFile)
if err != nil {
return nil, err
}
privateKey, err := ssh.ParsePrivateKey(key)
if err != nil {
return nil, err
}
c.sshPrivateKey = privateKey
}
return c.sshPrivateKey, nil
}
func (c *DeviceConfig) NewDeviceClient(ctx context.Context) (*device.Client, error) {
deviceHostname, err := c.DeviceHostname(ctx)
if err != nil {
return nil, err
}
sshPrivateKey, err := c.SSHPrivateKey()
if err != nil {
return nil, err
}
return device.NewClient(ctx, deviceHostname, sshPrivateKey)
}