blob: 3fdf776f7f52601a8fffbebea371c05f39481753 [file] [log] [blame]
// Copyright 2019 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 worker implements a constructor for skylab_swarming_worker
// commands. This package is intended to be used by package that need
// to construct a command line for running skylab_swarming_worker.
package worker
import (
"encoding/json"
"fmt"
"strings"
"time"
)
// DefaultPath is the default path for skylab_swarming_worker.
const DefaultPath = "/opt/infra-tools/skylab_swarming_worker"
// isolateOutdirMagicVal is a magic cmd argument that gets replaced by
// Swarming with the path to the isolated output directory inside the
// Swarming bot. Anything written by the worker to the isolated output
// directory is automatically uploaded to the Isolate server.
const isolatedOutdirMagicVal = "${ISOLATED_OUTDIR}"
// Command is a constructor for skylab_swarming_worker commands.
type Command struct {
Actions string
ClientTest bool
Deadline time.Time
Keyvals map[string]string
// LogDogAnnotationURL can be set automatically with Env.
LogDogAnnotationURL string
// If true, pass the magic var ${ISOLATED_OUTDIR} to the worker.
OutputToIsolate bool
// Path to skylab_swarming_worker. The default is DefaultPath.
Path string
ProvisionLabels []string
// TaskName is required.
TaskName string
TestArgs string
}
// Args returns the arg strings for running the command.
func (c *Command) Args() []string {
var args []string
if c.Path != "" {
args = append(args, c.Path)
} else {
args = append(args, DefaultPath)
}
if c.Actions != "" {
args = append(args, "-actions", c.Actions)
}
if c.ClientTest {
args = append(args, "-client-test")
}
if !c.Deadline.IsZero() {
args = append(args, "-deadline", stiptime(c.Deadline))
}
if c.Keyvals != nil {
b, err := json.Marshal(c.Keyvals)
// Marshal map[string]string should never error.
if err != nil {
panic(err)
}
args = append(args, "-keyvals", string(b))
}
if c.LogDogAnnotationURL != "" {
args = append(args, "-logdog-annotation-url", c.LogDogAnnotationURL)
}
if c.OutputToIsolate {
args = append(args, "-isolated-outdir", isolatedOutdirMagicVal)
}
if len(c.ProvisionLabels) > 0 {
args = append(args, "-provision-labels", strings.Join(c.ProvisionLabels, ","))
}
if c.TaskName != "" {
args = append(args, "-task-name", c.TaskName)
}
if c.TestArgs != "" {
args = append(args, "-test-args", c.TestArgs)
}
return args
}
// Config configures the command with the given options.
func (c *Command) Config(e Environment) {
c.LogDogAnnotationURL = GenerateLogDogURL(e)
}
// Environment defines a Skylab environment (e.g., dev vs prod) for
// configuring a worker command.
type Environment interface {
LUCIProject() string
LogDogHost() string
GenerateLogPrefix() string
}
// GenerateLogDogURL generates a LogDog annotation URL that is
// suitable for a worker command.
func GenerateLogDogURL(e Environment) string {
u := logDogURL{
Host: e.LogDogHost(),
Project: e.LUCIProject(),
Prefix: e.GenerateLogPrefix(),
}
return u.String()
}
// logDogURL is a constructor for LogDog annotation URLs.
type logDogURL struct {
Host string
Project string
Prefix string
}
func (u logDogURL) String() string {
return fmt.Sprintf("logdog://%s/%s/%s/+/annotations", u.Host, u.Project, u.Prefix)
}
const stipLayout = "2006-01-02T15:04:05.99Z0700"
func stiptime(t time.Time) string {
return t.In(time.UTC).Format(stipLayout)
}