blob: 0781fb6b038cb84490d0041c9b6498d568a1211c [file] [log] [blame]
// Copyright 2020 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package job
import (
"reflect"
"time"
"google.golang.org/protobuf/proto"
"go.chromium.org/luci/common/errors"
swarmingpb "go.chromium.org/luci/swarming/proto/api"
)
type swInfo struct {
*Swarming
casUserPayload *swarmingpb.CASReference
}
var _ Info = swInfo{}
func (s swInfo) SwarmingHostname() string {
return s.GetHostname()
}
func (s swInfo) TaskName() string {
return s.GetTask().GetName()
}
func (s swInfo) CurrentIsolated() (*swarmingpb.CASReference, error) {
casOptions := map[string]*swarmingpb.CASReference{}
if p := s.casUserPayload; p.GetDigest().GetHash() != "" {
casOptions[p.Digest.Hash] = p
}
if sw := s.Swarming; sw != nil {
for _, slc := range sw.GetTask().GetTaskSlices() {
input := slc.GetProperties().GetCasInputRoot()
if input != nil {
casOptions[input.Digest.GetHash()] = input
}
}
}
if len(casOptions) > 1 {
return nil, errors.Reason(
"Definition contains multiple RBE-CAS inputs: %v", casOptions).Err()
}
for _, v := range casOptions {
return proto.Clone(v).(*swarmingpb.CASReference), nil
}
return nil, nil
}
func (s swInfo) Dimensions() (ExpiringDimensions, error) {
ldims := logicalDimensions{}
var totalExpiration time.Duration
for _, slc := range s.GetTask().GetTaskSlices() {
if err := slc.Expiration.CheckValid(); err != nil {
return nil, errors.Annotate(err, "malformed expiration").Err()
}
exp := slc.Expiration.AsDuration()
totalExpiration += exp
for _, dim := range slc.GetProperties().GetDimensions() {
for _, val := range dim.Values {
ldims.updateDuration(dim.Key, val, totalExpiration)
}
}
}
return ldims.toExpiringDimensions(), nil
}
func (s swInfo) CIPDPkgs() (ret CIPDPkgs, err error) {
slices := s.GetTask().GetTaskSlices()
if len(slices) >= 1 {
if pkgs := slices[0].GetProperties().GetCipdInputs(); len(pkgs) > 0 {
ret = CIPDPkgs{}
ret.fromList(pkgs)
}
}
if len(slices) > 1 {
for idx, slc := range slices[1:] {
pkgDict := CIPDPkgs{}
pkgDict.fromList(slc.GetProperties().GetCipdInputs())
if !ret.equal(pkgDict) {
return nil, errors.Reason(
"slice %d has cipd pkgs which differ from slice 0: %v vs %v",
idx+1, pkgDict, ret).Err()
}
}
}
return
}
func (s swInfo) Env() (ret map[string]string, err error) {
slices := s.GetTask().GetTaskSlices()
extractEnv := func(slc *swarmingpb.TaskSlice) (slcEnv map[string]string) {
if env := slices[0].GetProperties().GetEnv(); len(env) > 0 {
slcEnv = make(map[string]string, len(env))
for _, pair := range env {
slcEnv[pair.Key] = pair.Value
}
}
return
}
if len(slices) >= 1 {
ret = extractEnv(slices[0])
for idx, slc := range slices[1:] {
if slcEnv := extractEnv(slc); !reflect.DeepEqual(ret, slcEnv) {
return nil, errors.Reason(
"slice %d has env which differs from slice 0: %v vs %v",
idx+1, slcEnv, ret).Err()
}
}
}
return
}
func (s swInfo) Priority() int32 {
return s.GetTask().GetPriority()
}
func (s swInfo) PrefixPathEnv() (ret []string, err error) {
slices := s.GetTask().GetTaskSlices()
if len(slices) >= 1 {
for _, keyVals := range slices[0].GetProperties().GetEnvPaths() {
if keyVals.Key == "PATH" {
ret = make([]string, len(keyVals.Values))
copy(ret, keyVals.Values)
break
}
}
}
if len(slices) > 1 {
for idx, slc := range slices[1:] {
foundIt := false
for _, keyVal := range slc.GetProperties().GetEnvPaths() {
if keyVal.Key == "PATH" {
foundIt = true
if !reflect.DeepEqual(ret, keyVal.Values) {
return nil, errors.Reason(
"slice %d has $PATH env prefixes which differ from slice 0: %v vs %v",
idx+1, keyVal.Values, ret).Err()
}
break
}
}
if !foundIt && len(ret) > 0 {
return nil, errors.Reason(
"slice %d has $PATH env prefixes which differ from slice 0: %v vs %v",
idx+1, []string{}, ret).Err()
}
}
}
return
}
func (s swInfo) Tags() (ret []string) {
if tags := s.GetTask().GetTags(); len(tags) > 0 {
ret = make([]string, len(tags))
copy(ret, tags)
}
return
}