blob: 1dfce807e853432584ff3fb59d67bdda5840025e [file]
// Copyright 2021 The Chromium OS 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 servers defines utilitizes that allow tests to access various
// servers, such as servo and provisions, provided in the lab or
// development environment.
package servers
import (
"strings"
"sync"
"chromiumos/tast/errors"
"chromiumos/tast/testing"
)
// ServerType defines the supported server types of this utility.
type ServerType int
// The specific server type for each server.
const (
Servo ServerType = iota
Provision
DUT
)
// Provide constant for primary DUTs roles for tests to use.
// Note: currently, we use "cd1", "cd2", ... for companinon DUT roles.
// There is no process to allow customization it yet.
const (
Primary = "" // Name for primary role.
)
// ErrNotFound is used the requested server information was not specified on command line.
var ErrNotFound = errors.New("cannot find server information")
var (
// servoServers is a runtime variable to store host information
// of servo servers.
servoServers = testing.RegisterVarString(
"servers.servo",
"",
"A variable to store host information of servo servers")
// provisionServers is a runtime variable to store host information
// of provision servers.
provisionServers = testing.RegisterVarString(
"servers.provision",
"",
"A variable to store host information of provision servers")
// dutServers is a runtime variable to store host information
// of DUT servers.
dutServers = testing.RegisterVarString(
"servers.dut",
"",
"A variable to store host information of DUT servers")
)
// Server returns the host target information of a server.
// This function should not be called from the init functions of tests.
func Server(serverType ServerType, role string) (string, error) {
var serverTypeName string
switch serverType {
case Servo:
serverTypeName = "servo"
case Provision:
serverTypeName = "provision server"
case DUT:
serverTypeName = "DUT server"
}
allServer, err := allServerHosts()
if err != nil {
return "", errors.Wrapf(
err, "failed to find %s for role %s", serverTypeName, role)
}
hosts := allServer[serverType]
if hosts == nil {
return "", errors.Wrapf(
ErrNotFound, "could not find %s for role %s", serverTypeName, role)
}
return hosts[role], nil
}
// Servers returns a map of role to host information of a particular server type.
// This function should not be called from the init functions of tests.
func Servers(serverType ServerType) (map[string]string, error) {
allServer, err := allServerHosts()
if err != nil {
return nil, err
}
result := make(map[string]string)
src, _ := allServer[serverType]
for role, host := range src {
result[role] = host
}
return result, nil
}
var (
allServers map[ServerType](map[string]string)
once sync.Once
parseErr error
)
func allServerHosts() (map[ServerType](map[string]string), error) {
once.Do(func() {
servoHosts, err := parseServerVarValues(servoServers.Value())
if err != nil {
parseErr = errors.Wrap(err, "failed to parse servo information")
return
}
provisionServerHosts, err := parseServerVarValues(provisionServers.Value())
if err != nil {
parseErr = errors.Wrap(err, "failed to parse provision server information")
return
}
dutServerHosts, err := parseServerVarValues(dutServers.Value())
if err != nil {
parseErr = errors.Wrap(err, "failed to parse DUT server information")
return
}
allServers = map[ServerType](map[string]string){
Servo: servoHosts,
Provision: provisionServerHosts,
DUT: dutServerHosts,
}
})
return allServers, parseErr
}
// parseServerVarValues parse the values of server related run time variables
// and return a role to server host map.
// Example input: ":addr1:22,cd1:addr2:2222"
// Example output: { "": "addr1:22", "cd1": "addr2:2222" }
func parseServerVarValues(inputValue string) (result map[string]string, err error) {
result = make(map[string]string)
if len(inputValue) == 0 {
return result, nil
}
serverInfos := strings.Split(inputValue, ",")
for _, serverInfo := range serverInfos {
roleHost := strings.SplitN(serverInfo, ":", 2)
if len(roleHost) != 2 {
return nil, errors.Errorf("invalid role/server value %s", serverInfo)
}
result[roleHost[0]] = roleHost[1]
}
return result, nil
}