blob: 9a334bcc4b5fafa649c6f33bb6b94159c8746e6a [file] [log] [blame]
// Copyright 2019 The Chromium 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 main
import (
"fmt"
"go.chromium.org/luci/common/data/stringset"
"infra/appengine/depot_tools_metrics/schema"
)
func checkConstraints(m *schema.Metrics) error {
for _, httpRequest := range m.HttpRequests {
if err := checkHTTPRequestConstraints(httpRequest); err != nil {
return err
}
}
for _, subCommand := range m.SubCommands {
if err := checkSubCommandConstraints(subCommand); err != nil {
return err
}
}
unknownArguments := unknownStrings(knownArguments, m.Arguments)
unknownProjectURLs := unknownStrings(knownProjectURLs, m.ProjectUrls)
switch {
case m.MetricsVersion < 0:
return fmt.Errorf("invalid metrics version: %v", m.MetricsVersion)
case m.Timestamp < 0:
return fmt.Errorf("invalid timestamp: %v", m.Timestamp)
case m.Command != "" && !knownCommands.Has(m.Command):
return fmt.Errorf("unknown command: %v", m.Command)
case unknownArguments.Len() != 0:
return fmt.Errorf("unknown arguments: %v", unknownArguments)
case m.ExecutionTime < 0:
return fmt.Errorf("invalid execution time: %v", m.ExecutionTime)
case unknownProjectURLs.Len() != 0:
return fmt.Errorf("unknown project URLs: %v", unknownProjectURLs)
case m.DepotToolsAge < 0:
return fmt.Errorf("invalid depot_tools age: %v", m.DepotToolsAge)
case m.HostArch != "" && !knownArchs.Has(m.HostArch):
return fmt.Errorf("unknown architecture: %v", m.HostArch)
case m.HostOs != "" && !knownOSs.Has(m.HostOs):
return fmt.Errorf("unknown OS: %v", m.HostOs)
case m.PythonVersion != "" && !pythonVersionRegex.MatchString(m.PythonVersion):
return fmt.Errorf("invalid python version: %v", m.PythonVersion)
case m.GitVersion != "" && !gitVersionRegex.MatchString(m.GitVersion):
return fmt.Errorf("invalid git version: %v", m.GitVersion)
default:
return nil
}
}
func checkSubCommandConstraints(c *schema.SubCommand) error {
unknownArguments := unknownStrings(knownSubCommandArguments, c.Arguments)
switch {
case c.Command != "" && !knownSubCommands.Has(c.Command):
return fmt.Errorf("invalid sub-command: %v", c.Command)
case unknownArguments.Len() != 0:
return fmt.Errorf("unknown sub-command arguments: %v", unknownArguments)
case c.ExecutionTime < 0:
return fmt.Errorf("invalid sub-command execution time: %v", c.ExecutionTime)
default:
return nil
}
}
func checkHTTPRequestConstraints(r *schema.HttpRequest) error {
unknownArguments := unknownStrings(knownHTTPArguments, r.Arguments)
switch {
case r.Host != "" && !knownHTTPHosts.Has(r.Host):
return fmt.Errorf("unknown HTTP host: %v", r.Host)
case r.Method != "" && !knownHTTPMethods.Has(r.Method):
return fmt.Errorf("unknown HTTP method: %v", r.Method)
case r.Path != "" && !knownHTTPPaths.Has(r.Path):
return fmt.Errorf("unknown HTTP path: %v", r.Path)
case unknownArguments.Len() != 0:
return fmt.Errorf("unknown HTTP arguments: %v", unknownArguments)
case r.Status < 200 || 599 < r.Status:
return fmt.Errorf("invalid HTTP status: %v", r.Status)
case r.ResponseTime < 0:
return fmt.Errorf("invalid response time: %v", r.ResponseTime)
default:
return nil
}
}
func unknownStrings(knownStrings stringset.Set, strings []string) stringset.Set {
return stringset.NewFromSlice(strings...).Difference(knownStrings)
}