blob: 98c9dd5c6395bfc6bbf5410c29ee3b123f930419 [file] [log] [blame]
// Copyright 2019 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 (
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"fuchsia.googlesource.com/system_ota_tests/build"
"fuchsia.googlesource.com/system_ota_tests/device"
"fuchsia.googlesource.com/system_ota_tests/util"
)
type Config struct {
OutputDir string
FuchsiaDir string
SshKeyFile string
netaddrPath string
localHostname string
DeviceName string
deviceHostname string
LkgbPath string
ArtifactsPath string
BuilderName string
buildID string
archive *build.Archive
}
func NewConfig(fs *flag.FlagSet) (*Config, error) {
outputDir, err := ioutil.TempDir("", "system_ota_tests")
if err != nil {
return nil, fmt.Errorf("failed to create a temporary directory: %s", err)
}
c := &Config{
OutputDir: outputDir,
}
testDataPath := filepath.Join(filepath.Dir(os.Args[0]), "test_data", "system_ota_tests")
fs.StringVar(&c.FuchsiaDir, "fuchsia-dir", os.Getenv("FUCHSIA_DIR"), "fuchsia dir")
fs.StringVar(&c.SshKeyFile, "ssh-private-key", os.Getenv("FUCHSIA_SSH_KEY"), "SSH private key file that can access the device")
fs.StringVar(&c.netaddrPath, "netaddr-path", filepath.Join(testDataPath, "netaddr"), "zircon netaddr tool path")
fs.StringVar(&c.localHostname, "local-hostname", "", "local hostname")
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.LkgbPath, "lkgb", filepath.Join(testDataPath, "lkgb"), "path to lkgb, default is $FUCHSIA_DIR/prebuilt/tools/lkgb/lkgb")
fs.StringVar(&c.ArtifactsPath, "artifacts", filepath.Join(testDataPath, "artifacts"), "path to the artifacts binary, default is $FUCHSIA_DIR/prebuilt/tools/artifacts/artifacts")
fs.StringVar(&c.BuilderName, "builder-name", "", "download the amber repository from the latest build of this builder")
fs.StringVar(&c.buildID, "build-id", "", "download the amber repository from this build id")
return c, nil
}
func (c *Config) Validate() error {
if c.BuilderName == "" && c.buildID == "" {
return fmt.Errorf("-builder-name or -build-id must be specified")
}
return nil
}
func (c *Config) Close() {
os.RemoveAll(c.OutputDir)
}
func (c *Config) NewDeviceClient() (*device.Client, error) {
deviceHostname, err := c.DeviceHostname()
if err != nil {
return nil, err
}
if c.SshKeyFile == "" {
return nil, fmt.Errorf("ssh private key cannot be empty")
}
return device.NewClient(deviceHostname, c.SshKeyFile)
}
func (c *Config) BuildArchive() *build.Archive {
if c.archive == nil {
// Connect to the build archive service.
c.archive = build.NewArchive(c.LkgbPath, c.ArtifactsPath, c.OutputDir)
}
return c.archive
}
func (c *Config) BuildID() (string, error) {
if c.buildID == "" {
a := c.BuildArchive()
id, err := a.LookupBuildID(c.BuilderName)
if err != nil {
return "", fmt.Errorf("failed to lookup build id: %s", err)
}
c.buildID = id
}
return c.buildID, nil
}
func (c *Config) LocalHostname() (string, error) {
if c.localHostname == "" {
var err error
c.localHostname, err = c.netaddr("--local", c.DeviceName)
if err != nil {
return "", fmt.Errorf("ERROR: netaddr failed: %s", err)
}
if c.localHostname == "" {
return "", fmt.Errorf("unable to determine the local hostname")
}
}
return c.localHostname, nil
}
func (c *Config) DeviceHostname() (string, error) {
if c.deviceHostname == "" {
var err error
c.deviceHostname, err = c.netaddr("--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 *Config) netaddr(arg ...string) (string, error) {
stdout, stderr, err := util.RunCommand(c.netaddrPath, arg...)
if err != nil {
return "", fmt.Errorf("netaddr failed: %s: %s", err, string(stderr))
}
return strings.TrimRight(string(stdout), "\n"), nil
}