blob: 88751f2579d98c7653bd8cb8d6d8e9026122274d [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package ufspb
import (
"fmt"
"reflect"
"regexp"
"strings"
"github.com/golang/protobuf/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"go.chromium.org/chromiumos/config/go/payload"
"go.chromium.org/luci/common/errors"
ufspb "infra/unifiedfleet/api/v1/models"
chromeosLab "infra/unifiedfleet/api/v1/models/chromeos/lab"
"infra/unifiedfleet/app/util"
)
// Error messages for input validation
var (
NilEntity string = "Invalid input - No Entity to add/update."
EmptyID string = "Invalid input - Entity ID is empty."
EmptyName string = "Invalid input - Entity Name is empty."
InvalidMac string = "invalid mac address"
ValidName string = "Name must match the regular expression `^[a-zA-Z0-9-)(_:.]{3,63}$`"
HostnamePattern string = "Name must match the regular expression `^[a-zA-Z0-9-.]{1,63}$`"
InvalidCharacters string = fmt.Sprintf("%s%s", "Invalid input - ", ValidName)
InvalidHostname string = fmt.Sprintf("%s%s", "Invalid input - ", HostnamePattern)
InvalidTags string = "Invalid input - Tags must not include '='."
InvalidPageSize string = "Invalid input - PageSize should be non-negative."
AssetNameFormat string = "Invalid input - Entity Name pattern should be assets/{asset}."
MachineNameFormat string = "Invalid input - Entity Name pattern should be machines/{machine}."
RackNameFormat string = "Invalid input - Entity Name pattern should be racks/{rack}."
ChromePlatformNameFormat string = "Invalid input - Entity Name pattern should be chromeplatforms/{chromeplatform}."
CachingServiceNameFormat string = "Invalid input - Entity Name pattern should be cachingservices/{hostname or ipv4}."
MachineLSENameFormat string = "Invalid input - Entity Name pattern should be machineLSEs/{machineLSE}."
MachineLSEDeploymentNameFormat string = "Invalid input - Entity Name pattern should be machineLSEDeployments/{name}."
VMNameFormat string = "Invalid input - Entity Name pattern should be vms/{vm}."
RackLSENameFormat string = "Invalid input - Entity Name pattern should be rackLSEs/{rackLSE}."
NicNameFormat string = "Invalid input - Entity Name pattern should be nics/{nic}."
KVMNameFormat string = "Invalid input - Entity Name pattern should be kvms/{kvm}."
RPMNameFormat string = "Invalid input - Entity Name pattern should be rpms/{rpm}."
DracNameFormat string = "Invalid input - Entity Name pattern should be dracs/{drac}."
SwitchNameFormat string = "Invalid input - Entity Name pattern should be switches/{switch}."
SchedulingUnitNameFormat string = "Invalid input - Entity Name pattern should be schedulingunits/{schedulingunit}."
VlanNameFormat string = "Invalid input - Entity Name pattern should be vlans/{vlan}."
MachineLSEPrototypeNameFormat string = "Invalid input - Entity Name pattern should be machineLSEPrototypes/{machineLSEPrototype}."
RackLSEPrototypeNameFormat string = "Invalid input - Entity Name pattern should be rackLSEPrototypes/{rackLSEPrototype}."
DefaultWifiNameFormat string = "Invalid input - Entity Name pattern should be defaultwifis/{defaultwifi}."
ResourceFormat string = "Invalid input - Entity Name pattern should be in a format of resource_names/XXX, resource_names includes machines/racks/vms/hosts/vlans."
EmptyMachineName string = "Invalid input - Machine name cannot be empty."
EmptyHostName string = "Invalid input - Host name cannot be empty."
EmptyRackName string = "Invalid input - Rack name cannot be empty."
FilterFormat string = "Filter format Egs:\n" + "'machine=mac-1'\n" + "'machine=mac-1,mac-2'\n" + "'machine=mac-1 & nic=nic-1'\n" + "'machine=mac-1 & nic=nic-1 & kvm=kvm-1,kvm-2'"
InvalidFilterFormat string = fmt.Sprintf("%s%s", "Invalid input - ", FilterFormat)
EmptyRequest string = "Empty Request"
)
var (
emptyMachineDBSourceStatus = status.New(codes.InvalidArgument, "Invalid argument - MachineDB source is empty")
invalidHostInMachineDBSourceStatus = status.New(codes.InvalidArgument, "Invalid argument - Host in MachineDB source is empty/invalid")
)
// IDRegex regular expression for checking resource Name/ID
var IDRegex = regexp.MustCompile(`^[a-zA-Z0-9-)(_:.]{3,63}$`)
// HostnameRegex regular expression for checking hostname for host/vm
var HostnameRegex = regexp.MustCompile(`^[a-zA-Z0-9-.]{1,63}$`)
var chromePlatformRegex = regexp.MustCompile(`chromeplatforms\.*`)
var machineRegex = regexp.MustCompile(`machines\.*`)
var rackRegex = regexp.MustCompile(`racks\.*`)
var machineLSERegex = regexp.MustCompile(`machineLSEs\.*`)
var rackLSERegex = regexp.MustCompile(`rackLSEs\.*`)
var nicRegex = regexp.MustCompile(`nics\.*`)
var kvmRegex = regexp.MustCompile(`kvms\.*`)
var rpmRegex = regexp.MustCompile(`rpms\.*`)
var dracRegex = regexp.MustCompile(`dracs\.*`)
var switchRegex = regexp.MustCompile(`switches\.*`)
var vlanRegex = regexp.MustCompile(`vlans\.*`)
var machineLSEPrototypeRegex = regexp.MustCompile(`machineLSEPrototypes\.*`)
var rackLSEPrototypeRegex = regexp.MustCompile(`rackLSEPrototypes\.*`)
var assetRegex = regexp.MustCompile(`assets\.*`)
var machineLSEDeploymentRegex = regexp.MustCompile(`machineLSEDeployments\.*`)
var schedulingUnitRegex = regexp.MustCompile(`schedulingunits\.*`)
var defaultWifiRegex = regexp.MustCompile(`defaultwifis\.*`)
// matches "cachingservices/{hostname or ipv4}"
var cachingServiceRegex = regexp.MustCompile(`cachingservices/[a-zA-Z0-9-.]{1,63}$`)
// It's used to validate a host or vm in resource_name
var hostRegex = regexp.MustCompile(`hosts\.*`)
var vmRegex = regexp.MustCompile(`vms\.*`)
var resourceRegexs = []*regexp.Regexp{
machineRegex,
rackRegex,
vlanRegex,
hostRegex,
vmRegex,
}
// FilterRegex is the regex for filter string for all List requests
//
// resource1=resourcename1
// resource1=resourcename1,resourcename2
// resource1=resourcename1 & resource2=resourcename21
// resource1=resourcename1,resourcename2 & resource2=resourcename21,resourcename22
// resource1=resourcename1 & resource2=resourcename21 & resource3=resourcename31
// machine=mac-1
// machine=mac-1,mac-2
// machine=mac-1 & nic=nic-1
// machine=mac-1 & nic=nic-1 & kvm=kvm-1,kvm-2
var FilterRegex = regexp.MustCompile(`^([a-z]*\=[a-zA-Z0-9-)(_:.\/]*)(\,[a-zA-Z0-9-)(_:.\/]*)*(\&([a-z]*\=[a-zA-Z0-9-)(_:.\/]*)(\,[a-zA-Z0-9-)(_:.\/]*)*)*$`)
// Validate validates input requests of RackRegistration.
func (r *RackRegistrationRequest) Validate() error {
if r.Rack == nil {
return status.Errorf(codes.InvalidArgument, "Rack "+NilEntity)
}
id := strings.TrimSpace(r.Rack.GetName())
if id == "" {
return status.Errorf(codes.InvalidArgument, "Rack "+EmptyName)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Rack %q: %s", id, InvalidCharacters)
}
if !util.ValidateTags(r.Rack.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
r.Rack.Name = id
if r.GetRack().GetChromeBrowserRack() != nil {
if r.GetRack().GetChromeBrowserRack().GetSwitchObjects() != nil {
switches := r.GetRack().GetChromeBrowserRack().GetSwitchObjects()
for _, s := range switches {
id = strings.TrimSpace(s.GetName())
if id == "" {
return status.Errorf(codes.InvalidArgument, "Switch "+EmptyName)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Switch %q: %s", id, InvalidCharacters)
}
}
}
if r.GetRack().GetChromeBrowserRack().GetKvmObjects() != nil {
kvms := r.GetRack().GetChromeBrowserRack().GetKvmObjects()
for _, kvm := range kvms {
id = strings.TrimSpace(kvm.GetName())
if id == "" {
return status.Errorf(codes.InvalidArgument, "KVM "+EmptyName)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "KVM %q: %s", id, InvalidCharacters)
}
}
}
if r.GetRack().GetChromeBrowserRack().GetRpmObjects() != nil {
rpms := r.GetRack().GetChromeBrowserRack().GetRpmObjects()
for _, rpm := range rpms {
id = strings.TrimSpace(rpm.GetName())
if id == "" {
return status.Errorf(codes.InvalidArgument, "RPM "+EmptyName)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "RPM %q: %s", id, InvalidCharacters)
}
}
}
}
return nil
}
// Validate validates input requests of CreateChromePlatform.
func (r *CreateChromePlatformRequest) Validate() error {
if r.ChromePlatform == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.ChromePlatformId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Chrome Platform %q: %s", id, InvalidCharacters)
}
if !util.ValidateTags(r.ChromePlatform.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
r.ChromePlatformId = id
return nil
}
// Validate validates input requests of UpdateChromePlatform.
func (r *UpdateChromePlatformRequest) Validate() error {
if r.ChromePlatform == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if !util.ValidateTags(r.ChromePlatform.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
return validateResourceName(chromePlatformRegex, ChromePlatformNameFormat, r.ChromePlatform.GetName())
}
// Validate validates input requests of GetDHCPConfig.
func (r *GetDHCPConfigRequest) Validate() error {
if r.GetHostname() == "" {
return status.Errorf(codes.InvalidArgument, EmptyName)
}
return nil
}
// Validate validates input requests of GetChromePlatform.
func (r *GetChromePlatformRequest) Validate() error {
return validateResourceName(chromePlatformRegex, ChromePlatformNameFormat, r.Name)
}
// ListRequest is the interface for all ListXXXRequest.
type ListRequest interface {
GetFilter() string
GetPageSize() int32
}
// ValidateListRequest validates the request to list a kind of entity.
func ValidateListRequest(r ListRequest) error {
if err := ValidateFilter(r.GetFilter()); err != nil {
return err
}
return validatePageSize(r.GetPageSize())
}
// Validate validates input requests of DeleteChromePlatform.
func (r *DeleteChromePlatformRequest) Validate() error {
return validateResourceName(chromePlatformRegex, ChromePlatformNameFormat, r.Name)
}
// Validate validates input requests of CreateMachineLSEPrototype.
func (r *CreateMachineLSEPrototypeRequest) Validate() error {
if r.MachineLSEPrototype == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.MachineLSEPrototypeId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Host Prototype %q: %s", id, InvalidCharacters)
}
r.MachineLSEPrototypeId = id
return nil
}
// Validate validates input requests of UpdateMachineLSEPrototype.
func (r *UpdateMachineLSEPrototypeRequest) Validate() error {
if r.MachineLSEPrototype == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
return validateResourceName(machineLSEPrototypeRegex, MachineLSEPrototypeNameFormat, r.MachineLSEPrototype.GetName())
}
// Validate validates input requests of GetMachineLSEPrototype.
func (r *GetMachineLSEPrototypeRequest) Validate() error {
return validateResourceName(machineLSEPrototypeRegex, MachineLSEPrototypeNameFormat, r.Name)
}
// Validate validates input requests of DeleteMachineLSEPrototype.
func (r *DeleteMachineLSEPrototypeRequest) Validate() error {
return validateResourceName(machineLSEPrototypeRegex, MachineLSEPrototypeNameFormat, r.Name)
}
// Validate validates input requests of CreateRackLSEPrototype.
func (r *CreateRackLSEPrototypeRequest) Validate() error {
if r.RackLSEPrototype == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.RackLSEPrototypeId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Rack prototype %q: %s", id, InvalidCharacters)
}
r.RackLSEPrototypeId = id
return nil
}
// Validate validates input requests of UpdateRackLSEPrototype.
func (r *UpdateRackLSEPrototypeRequest) Validate() error {
if r.RackLSEPrototype == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
return validateResourceName(rackLSEPrototypeRegex, RackLSEPrototypeNameFormat, r.RackLSEPrototype.GetName())
}
// Validate validates input requests of GetRackLSEPrototype.
func (r *GetRackLSEPrototypeRequest) Validate() error {
return validateResourceName(rackLSEPrototypeRegex, RackLSEPrototypeNameFormat, r.Name)
}
// Validate validates input requests of DeleteRackLSEPrototype.
func (r *DeleteRackLSEPrototypeRequest) Validate() error {
return validateResourceName(rackLSEPrototypeRegex, RackLSEPrototypeNameFormat, r.Name)
}
// Validate validates input requests of MachineRegistrationRequest.
func (r *MachineRegistrationRequest) Validate() error {
if r.Machine == nil {
return status.Errorf(codes.InvalidArgument, "Machine "+NilEntity)
}
id := strings.TrimSpace(r.Machine.GetName())
if id == "" {
return status.Errorf(codes.InvalidArgument, "Machine "+EmptyName)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Machine %q: %s", id, InvalidCharacters)
}
if !util.ValidateTags(r.Machine.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
r.Machine.Name = id
r.Machine.SerialNumber = strings.TrimSpace(r.Machine.SerialNumber)
if r.GetMachine().GetChromeBrowserMachine() != nil {
if r.GetMachine().GetChromeBrowserMachine().GetNicObjects() != nil {
nics := r.GetMachine().GetChromeBrowserMachine().GetNicObjects()
for _, nic := range nics {
id = strings.TrimSpace(nic.GetName())
if id == "" {
return status.Errorf(codes.InvalidArgument, "Nic "+EmptyName)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Nic %q: %s", id, InvalidCharacters)
}
if err := validateNic(nic); err != nil {
return err
}
}
}
if r.GetMachine().GetChromeBrowserMachine().GetDracObject() != nil {
drac := r.GetMachine().GetChromeBrowserMachine().GetDracObject()
if drac != nil {
id = strings.TrimSpace(drac.GetName())
if id == "" {
return status.Errorf(codes.InvalidArgument, "Drac "+EmptyName)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Drac %q: %s", id, InvalidCharacters)
}
if err := validateDrac(drac); err != nil {
return err
}
}
}
}
return nil
}
// Validate validates input requests of UpdateMachine.
func (r *UpdateMachineRequest) Validate() error {
if r.Machine == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if !util.ValidateTags(r.Machine.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
r.Machine.Name = strings.TrimSpace(r.Machine.GetName())
r.Machine.SerialNumber = strings.TrimSpace(r.Machine.SerialNumber)
return validateResourceName(machineRegex, MachineNameFormat, r.Machine.GetName())
}
// Validate validates input requests of GetMachine.
func (r *GetMachineRequest) Validate() error {
return validateResourceName(machineRegex, MachineNameFormat, r.Name)
}
// Validate validates input requests of DeleteMachine.
func (r *DeleteMachineRequest) Validate() error {
return validateResourceName(machineRegex, MachineNameFormat, r.Name)
}
// Validate validates input requests of RenameMachine.
func (r *RenameMachineRequest) Validate() error {
if err := validateResourceName(machineRegex, MachineNameFormat, r.GetName()); err != nil {
return err
}
return validateResourceName(machineRegex, MachineNameFormat, r.GetNewName())
}
// Validate validates input requests of UpdateRack.
func (r *UpdateRackRequest) Validate() error {
if r.Rack == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if !util.ValidateTags(r.Rack.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
return validateResourceName(rackRegex, RackNameFormat, r.Rack.GetName())
}
// Validate validates input requests of GetRack.
func (r *GetRackRequest) Validate() error {
return validateResourceName(rackRegex, RackNameFormat, r.Name)
}
// Validate validates input requests of DeleteRack.
func (r *DeleteRackRequest) Validate() error {
return validateResourceName(rackRegex, RackNameFormat, r.Name)
}
// Validate validates input requests of RenameRack.
func (r *RenameRackRequest) Validate() error {
if r.Name == "" {
return status.Errorf(codes.InvalidArgument, EmptyName)
}
if r.NewName == "" {
return status.Errorf(codes.InvalidArgument, "Missing new rack name to rename")
}
if strings.ToLower(r.NewName) != r.NewName {
return status.Errorf(codes.InvalidArgument, "Invalid name %s: new rack name should be in all lowercase.", r.NewName)
}
return validateResourceName(rackRegex, RackNameFormat, r.GetNewName())
}
// Validate validates input requests of CreateMachineLSE.
func (r *CreateMachineLSERequest) Validate() error {
if r.MachineLSE == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.MachineLSEId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !HostnameRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, InvalidHostname)
}
if r.MachineLSE.GetHostname() == "" {
return status.Errorf(codes.InvalidArgument, "Hostname cannot be empty for a host. It must be same as name of the host")
}
if !HostnameRegex.MatchString(r.MachineLSE.GetHostname()) {
return status.Errorf(codes.InvalidArgument, InvalidHostname)
}
if r.MachineLSE.GetMachines() == nil || len(r.MachineLSE.GetMachines()) == 0 {
return status.Errorf(codes.InvalidArgument, EmptyMachineName)
}
if err := validateNetworkOption(r.GetNetworkOption()); err != nil {
return err
}
for _, machineName := range r.MachineLSE.GetMachines() {
if machineName == "" {
return status.Errorf(codes.InvalidArgument, EmptyMachineName)
}
}
if !util.ValidateTags(r.MachineLSE.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
r.MachineLSEId = id
return nil
}
// Validate validates input requests of UpdateMachineLSE.
func (r *UpdateMachineLSERequest) Validate() error {
if r.MachineLSE == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if !util.ValidateTags(r.MachineLSE.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
for k, v := range r.GetNetworkOptions() {
if err := validateNetworkOption(v); err != nil {
return errors.Annotate(err, "fail to validate host %s", k).Err()
}
}
return validateResourceName(machineLSERegex, MachineLSENameFormat, r.MachineLSE.GetName())
}
// Validate validates input requests of GetMachineLSE.
func (r *GetMachineLSERequest) Validate() error {
return validateResourceName(machineLSERegex, MachineLSENameFormat, r.Name)
}
// Validate validates input requests of GetMachineLSEBySerial.
func (r *GetMachineLSEBySerialRequest) Validate() error {
if r.Serial == "" {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
return nil
}
// Validate validates input requests of GetHostData.
func (r *GetHostDataRequest) Validate() error {
r.Serial = strings.TrimSpace(r.Serial)
if r.Serial == "" {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
return nil
}
// Validate validates input requests of DeleteMachineLSE.
func (r *DeleteMachineLSERequest) Validate() error {
return validateResourceName(machineLSERegex, MachineLSENameFormat, r.Name)
}
// Validate validates input requests of CreateVM.
func (r *CreateVMRequest) Validate() error {
if r.GetVm() == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if !HostnameRegex.MatchString(r.GetVm().GetName()) {
return status.Errorf(codes.InvalidArgument, "VM name is invalid: %s", InvalidHostname)
}
id := strings.TrimSpace(r.GetVm().GetMachineLseId())
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyHostName)
}
if !HostnameRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Host name is invalid: %s", InvalidHostname)
}
if r.Vm.GetMacAddress() != "" {
newMac, err := util.ParseMac(r.Vm.GetMacAddress())
if err != nil {
return status.Errorf(codes.InvalidArgument, err.Error())
}
r.Vm.MacAddress = newMac
}
if err := validateNetworkOption(r.GetNetworkOption()); err != nil {
return err
}
if !util.ValidateTags(r.Vm.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
r.GetVm().MachineLseId = id
r.GetVm().Name = strings.TrimSpace(r.GetVm().Name)
return nil
}
func validateNetworkOption(opt *NetworkOption) error {
if opt == nil {
return nil
}
if !opt.GetDelete() && opt.GetVlan() == "" && opt.GetIp() == "" {
return status.Errorf(codes.InvalidArgument, "Network option doesn't set delete or vlan or ip.")
}
return nil
}
// Validate validates input requests of UpdateVM.
func (r *UpdateVMRequest) Validate() error {
if r.GetVm() == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if r.Vm.GetMacAddress() != "" {
newMac, err := util.ParseMac(r.Vm.GetMacAddress())
if err != nil {
return status.Errorf(codes.InvalidArgument, err.Error())
}
r.Vm.MacAddress = newMac
}
if err := validateNetworkOption(r.GetNetworkOption()); err != nil {
return err
}
if !util.ValidateTags(r.Vm.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
return validateResourceName(vmRegex, VMNameFormat, r.Vm.GetName())
}
// Validate validates input requests of DeleteVM.
func (r *DeleteVMRequest) Validate() error {
return validateResourceName(vmRegex, VMNameFormat, r.Name)
}
// Validate validates input requests of GetVM.
func (r *GetVMRequest) Validate() error {
return validateResourceName(vmRegex, VMNameFormat, r.Name)
}
// Validate validates input requests of CreateRackLSE.
func (r *CreateRackLSERequest) Validate() error {
if r.RackLSE == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.RackLSEId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Rack host %q: %s", id, InvalidCharacters)
}
r.RackLSEId = id
return nil
}
// Validate validates input requests of UpdateRackLSE.
func (r *UpdateRackLSERequest) Validate() error {
if r.RackLSE == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
return validateResourceName(rackLSERegex, RackLSENameFormat, r.RackLSE.GetName())
}
// Validate validates input requests of GetRackLSE.
func (r *GetRackLSERequest) Validate() error {
return validateResourceName(rackLSERegex, RackLSENameFormat, r.Name)
}
// Validate validates input requests of DeleteRackLSE.
func (r *DeleteRackLSERequest) Validate() error {
return validateResourceName(rackLSERegex, RackLSENameFormat, r.Name)
}
// Validate validates input requests of CreateNic.
func (r *CreateNicRequest) Validate() error {
if r.Nic == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.NicId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Nic %q: %s", id, InvalidCharacters)
}
if err := validateNic(r.GetNic()); err != nil {
return err
}
if r.GetNic().GetMachine() == "" {
return status.Errorf(codes.InvalidArgument, EmptyMachineName)
}
r.NicId = id
return nil
}
func validateNic(nic *ufspb.Nic) error {
if nic.GetMacAddress() == "" {
return status.Errorf(codes.InvalidArgument, "nic macAddress cannot be empty")
}
if !util.ValidateTags(nic.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
newMac, err := util.ParseMac(nic.GetMacAddress())
if err != nil {
return status.Errorf(codes.InvalidArgument, err.Error())
}
nic.MacAddress = newMac
return nil
}
// Validate validates input requests of RenameNic.
func (r *RenameNicRequest) Validate() error {
if err := validateResourceName(nicRegex, NicNameFormat, r.GetName()); err != nil {
return err
}
return validateResourceName(nicRegex, NicNameFormat, r.GetNewName())
}
// Validate validates input requests of RenameSwitch.
func (r *RenameSwitchRequest) Validate() error {
if err := validateResourceName(switchRegex, SwitchNameFormat, r.GetName()); err != nil {
return err
}
return validateResourceName(switchRegex, SwitchNameFormat, r.GetNewName())
}
// Validate validates input requests of UpdateState.
func (r *UpdateStateRequest) Validate() error {
if r.State == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
for _, rg := range resourceRegexs {
if err := validateResourceName(rg, "invalid resource name format", r.State.GetResourceName()); err == nil {
return nil
}
}
return status.Errorf(codes.InvalidArgument, ResourceFormat)
}
// Validate validates input requests of GetState.
func (r *GetStateRequest) Validate() error {
for _, rg := range resourceRegexs {
if err := validateResourceName(rg, "invalid resource name format", r.GetResourceName()); err == nil {
return nil
}
}
return status.Errorf(codes.InvalidArgument, ResourceFormat)
}
// Validate validates input requests of UpdateDutState
func (r *UpdateDutStateRequest) Validate() error {
if r.DutState == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if r.GetDutState().GetId() == nil {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
dutID := strings.TrimSpace(r.GetDutState().GetId().GetValue())
if dutID == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(dutID) {
return status.Errorf(codes.InvalidArgument, "DUT ID %q: %s", dutID, InvalidCharacters)
}
dutHostname := strings.TrimSpace(r.GetDutState().GetHostname())
if dutHostname == "" {
return status.Errorf(codes.InvalidArgument, "Hostname cannot be empty when updating dut states for %q", dutID)
}
if r.GetDutMeta() != nil {
if r.GetDutMeta().GetChromeosDeviceId() != dutID {
return status.Errorf(codes.InvalidArgument, fmt.Sprintf("Mismatched dut ID in DUT meta with dut state: %q", dutID))
}
if r.GetDutMeta().GetHostname() != dutHostname {
return status.Errorf(codes.InvalidArgument, fmt.Sprintf("Mismatched dut hostname in DUT meta (%q) with dut state %q", r.GetDutMeta().GetHostname(), dutHostname))
}
}
if r.GetLabMeta() != nil {
if r.GetLabMeta().GetChromeosDeviceId() != dutID {
return status.Errorf(codes.InvalidArgument, fmt.Sprintf("Mismatched dut ID in lab meta with dut state: %q", dutID))
}
if r.GetLabMeta().GetHostname() != dutHostname {
return status.Errorf(codes.InvalidArgument, fmt.Sprintf("Mismatched dut hostname in lab meta (%q) with dut state %q", r.GetLabMeta().GetHostname(), dutHostname))
}
}
return nil
}
// Validate validates input requests of UpdateDeviceRecoveryData
func (r *UpdateDeviceRecoveryDataRequest) Validate() error {
if err := r.validateDutId(); err != nil {
return err
}
if err := r.validateHostname(); err != nil {
return err
}
if r.GetResourceType() == UpdateDeviceRecoveryDataRequest_RESOURCE_TYPE_CHROMEOS_DEVICE {
if err := r.validateDutWifiRouterHostnames(); err != nil {
return err
}
if err := r.validateBluetoothPeerHostnames(); err != nil {
return err
}
}
return nil
}
func (r *UpdateDeviceRecoveryDataRequest) validateDutId() error {
dutId := r.GetDeviceId()
if dutId == "" {
return status.Errorf(codes.InvalidArgument, "Empty dut id. %s", EmptyID)
}
if !IDRegex.MatchString(dutId) {
return status.Errorf(codes.InvalidArgument, "DUT ID %q: %s", dutId, InvalidCharacters)
}
if r.GetResourceType() == UpdateDeviceRecoveryDataRequest_RESOURCE_TYPE_CHROMEOS_DEVICE {
if r.GetChromeos().GetDutState() == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
// Request device id should match the dut state id
if dutStateId := strings.TrimSpace(r.GetChromeos().GetDutState().GetId().GetValue()); dutStateId != dutId {
return status.Errorf(codes.InvalidArgument, "Mismatched device id(%q) with dut state id: %q", dutId, dutStateId)
}
}
return nil
}
func (r *UpdateDeviceRecoveryDataRequest) validateHostname() error {
dutHostname := r.GetHostname()
if dutHostname == "" {
return status.Errorf(codes.InvalidArgument, "Empty request hostname (%q)", r.GetHostname())
}
if r.GetResourceType() == UpdateDeviceRecoveryDataRequest_RESOURCE_TYPE_CHROMEOS_DEVICE {
if r.GetChromeos().GetDutState() == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
// Request hostname has to match the dut state hostname
dutStateHostname := strings.TrimSpace(r.GetChromeos().GetDutState().GetHostname())
if dutStateHostname == "" {
return status.Errorf(codes.InvalidArgument, "Empty dut state hostname (%q)", dutHostname)
}
if dutStateHostname != dutHostname {
return status.Errorf(codes.InvalidArgument, "Mismatched request hostname (%q) with dut state hostname %q", dutHostname, dutStateHostname)
}
}
return nil
}
// validateHostnames checks for empty or duplicates in hostnames. Uses typ to construct error message.
func validateHostnames(hostnames []string, typ string) error {
set := make(map[string]bool)
for _, h := range hostnames {
if len(strings.TrimSpace(h)) == 0 {
return status.Errorf(codes.InvalidArgument, "Empty hostname in %s lab data: %v", typ, hostnames)
}
if set[h] {
return status.Errorf(codes.InvalidArgument, "Duplicate hostname (%q) in %s lab data: %v", h, typ, hostnames)
}
set[h] = true
}
return nil
}
func (r *UpdateDeviceRecoveryDataRequest) validateDutWifiRouterHostnames() error {
if r.GetChromeos().GetLabData() == nil {
return nil
}
var hostnames []string
for _, router := range r.GetChromeos().GetLabData().GetWifiRouters() {
hostnames = append(hostnames, router.GetHostname())
}
return validateHostnames(hostnames, "WiFi")
}
func (r *UpdateDeviceRecoveryDataRequest) validateBluetoothPeerHostnames() error {
if r.GetChromeos().GetLabData() == nil {
return nil
}
var hostnames []string
for _, peer := range r.GetChromeos().GetLabData().GetBluetoothPeers() {
hostnames = append(hostnames, peer.GetHostname())
}
return validateHostnames(hostnames, "Bluetooth peers")
}
// Validate validates input requests of GetDutStateRequest.
func (r *GetDutStateRequest) Validate() error {
if r == nil {
return status.Errorf(codes.InvalidArgument, EmptyRequest)
}
if r.ChromeosDeviceId == "" && r.Hostname == "" {
return status.Errorf(codes.InvalidArgument, "Both Id and hostname are empty")
}
return nil
}
// Validate validates input requests of UpdateTestData
func (r *UpdateTestDataRequest) Validate() error {
if err := r.validateDutId(); err != nil {
return err
}
if err := r.validateHostname(); err != nil {
return err
}
if chromeos := r.GetChromeosData(); chromeos != nil {
if chromeos.GetDutState() == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
// Always use ID and hostname from request for DutStates.
if chromeos.GetDutState().GetId() == nil {
chromeos.GetDutState().Id = &chromeosLab.ChromeOSDeviceID{
Value: r.GetDeviceId(),
}
} else {
chromeos.GetDutState().GetId().Value = r.GetDeviceId()
}
chromeos.GetDutState().Hostname = r.GetHostname()
}
return nil
}
func (r *UpdateTestDataRequest) validateDutId() error {
if r.GetDeviceId() == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(r.GetDeviceId()) {
return status.Errorf(codes.InvalidArgument, "DUT ID %q: %s", r.GetDeviceId(), InvalidCharacters)
}
return nil
}
func (r *UpdateTestDataRequest) validateHostname() error {
if r.GetHostname() == "" {
return status.Errorf(codes.InvalidArgument, EmptyHostName)
}
return nil
}
// Validate validates input requests of UpdateNic.
func (r *UpdateNicRequest) Validate() error {
if r.Nic == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if r.Nic.GetMacAddress() != "" {
newMac, err := util.ParseMac(r.Nic.GetMacAddress())
if err != nil {
return status.Errorf(codes.InvalidArgument, err.Error())
}
r.Nic.MacAddress = newMac
}
if !util.ValidateTags(r.Nic.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
return validateResourceName(nicRegex, NicNameFormat, r.Nic.GetName())
}
// Validate validates input requests of GetNic.
func (r *GetNicRequest) Validate() error {
return validateResourceName(nicRegex, NicNameFormat, r.Name)
}
// Validate validates input requests of DeleteNic.
func (r *DeleteNicRequest) Validate() error {
return validateResourceName(nicRegex, NicNameFormat, r.Name)
}
// Validate validates input requests of CreateKVM.
func (r *CreateKVMRequest) Validate() error {
if r.KVM == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.KVMId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "KVM %q: %s", id, InvalidCharacters)
}
if r.GetKVM().GetRack() == "" {
return status.Errorf(codes.InvalidArgument, EmptyRackName)
}
if r.KVM.GetMacAddress() != "" {
newMac, err := util.ParseMac(r.KVM.GetMacAddress())
if err != nil {
return status.Errorf(codes.InvalidArgument, err.Error())
}
r.KVM.MacAddress = newMac
}
if !util.ValidateTags(r.KVM.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
r.KVMId = id
return nil
}
// Validate validates input requests of UpdateKVM.
func (r *UpdateKVMRequest) Validate() error {
if r.KVM == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if r.KVM.GetMacAddress() != "" {
newMac, err := util.ParseMac(r.KVM.GetMacAddress())
if err != nil {
return status.Errorf(codes.InvalidArgument, err.Error())
}
r.KVM.MacAddress = newMac
}
if !util.ValidateTags(r.KVM.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
return validateResourceName(kvmRegex, KVMNameFormat, r.KVM.GetName())
}
// Validate validates input requests of GetKVM.
func (r *GetKVMRequest) Validate() error {
return validateResourceName(kvmRegex, KVMNameFormat, r.Name)
}
// Validate validates input requests of DeleteKVM.
func (r *DeleteKVMRequest) Validate() error {
return validateResourceName(kvmRegex, KVMNameFormat, r.Name)
}
// Validate validates input requests of CreateRPM.
func (r *CreateRPMRequest) Validate() error {
if r.RPM == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.RPMId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "RPM %q: %s", id, InvalidCharacters)
}
if r.GetRPM().GetRack() == "" {
return status.Errorf(codes.InvalidArgument, EmptyRackName)
}
if r.RPM.GetMacAddress() != "" {
newMac, err := util.ParseMac(r.RPM.GetMacAddress())
if err != nil {
return status.Errorf(codes.InvalidArgument, err.Error())
}
r.RPM.MacAddress = newMac
}
if !util.ValidateTags(r.RPM.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
r.RPMId = id
return nil
}
// Validate validates input requests of UpdateRPM.
func (r *UpdateRPMRequest) Validate() error {
if r.RPM == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if r.RPM.GetMacAddress() != "" {
newMac, err := util.ParseMac(r.RPM.GetMacAddress())
if err != nil {
return status.Errorf(codes.InvalidArgument, err.Error())
}
r.RPM.MacAddress = newMac
}
if !util.ValidateTags(r.RPM.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
return validateResourceName(rpmRegex, RPMNameFormat, r.RPM.GetName())
}
// Validate validates input requests of GetRPM.
func (r *GetRPMRequest) Validate() error {
return validateResourceName(rpmRegex, RPMNameFormat, r.Name)
}
// Validate validates input requests of DeleteRPM.
func (r *DeleteRPMRequest) Validate() error {
return validateResourceName(rpmRegex, RPMNameFormat, r.Name)
}
// Validate validates input requests of CreateDrac.
func (r *CreateDracRequest) Validate() error {
if r.Drac == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.DracId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Drac %q: %s", id, InvalidCharacters)
}
if err := validateDrac(r.GetDrac()); err != nil {
return err
}
if r.GetDrac().GetMachine() == "" {
return status.Errorf(codes.InvalidArgument, EmptyMachineName)
}
r.DracId = id
return nil
}
func validateDrac(drac *ufspb.Drac) error {
if drac.GetMacAddress() == "" {
return status.Errorf(codes.InvalidArgument, "drac macAddress cannot be empty")
}
if !util.ValidateTags(drac.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
newMac, err := util.ParseMac(drac.GetMacAddress())
if err != nil {
return status.Errorf(codes.InvalidArgument, err.Error())
}
drac.MacAddress = newMac
return nil
}
// Validate validates input requests of UpdateDrac.
func (r *UpdateDracRequest) Validate() error {
if r.Drac == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if r.Drac.GetMacAddress() != "" {
newMac, err := util.ParseMac(r.Drac.GetMacAddress())
if err != nil {
return status.Errorf(codes.InvalidArgument, err.Error())
}
r.Drac.MacAddress = newMac
}
if !util.ValidateTags(r.Drac.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
return validateResourceName(dracRegex, DracNameFormat, r.Drac.GetName())
}
// Validate validates input requests of GetDrac.
func (r *GetDracRequest) Validate() error {
return validateResourceName(dracRegex, DracNameFormat, r.Name)
}
// Validate validates input requests of DeleteDrac.
func (r *DeleteDracRequest) Validate() error {
return validateResourceName(dracRegex, DracNameFormat, r.Name)
}
// Validate validates input requests of CreateSwitch.
func (r *CreateSwitchRequest) Validate() error {
if r.Switch == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.SwitchId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Switch %q: %s", id, InvalidCharacters)
}
if r.GetSwitch().GetRack() == "" {
return status.Errorf(codes.InvalidArgument, EmptyRackName)
}
if !util.ValidateTags(r.Switch.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
r.SwitchId = id
return nil
}
// Validate validates input requests of UpdateSwitch.
func (r *UpdateSwitchRequest) Validate() error {
if r.Switch == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if !util.ValidateTags(r.Switch.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
return validateResourceName(switchRegex, SwitchNameFormat, r.Switch.GetName())
}
// Validate validates input requests of GetSwitch.
func (r *GetSwitchRequest) Validate() error {
return validateResourceName(switchRegex, SwitchNameFormat, r.Name)
}
// Validate validates input requests of DeleteSwitch.
func (r *DeleteSwitchRequest) Validate() error {
return validateResourceName(switchRegex, SwitchNameFormat, r.Name)
}
// Validate validates input requests of CreateVlan.
func (r *CreateVlanRequest) Validate() error {
if r.Vlan == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.VlanId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Vlan %q: %s", id, InvalidCharacters)
}
if r.Vlan.GetVlanAddress() == "" {
return status.Errorf(codes.InvalidArgument, "Empty cidr block for vlan")
}
if !util.ValidateTags(r.Vlan.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
r.VlanId = id
return nil
}
// Validate validates input requests of UpdateVlan.
func (r *UpdateVlanRequest) Validate() error {
if r.Vlan == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if !util.ValidateTags(r.Vlan.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
return validateResourceName(vlanRegex, VlanNameFormat, r.Vlan.GetName())
}
// Validate validates input requests of GetVlan.
func (r *GetVlanRequest) Validate() error {
return validateResourceName(vlanRegex, VlanNameFormat, r.Name)
}
// Validate validates input requests of DeleteVlan.
func (r *DeleteVlanRequest) Validate() error {
return validateResourceName(vlanRegex, VlanNameFormat, r.Name)
}
// Validate validates input requests of CreateAsset
func (r *CreateAssetRequest) Validate() error {
if r.GetAsset() == nil {
return status.Errorf(codes.InvalidArgument, "Empty asset")
}
name := strings.TrimSpace(r.GetAsset().GetName())
if name == "" {
return status.Errorf(codes.InvalidArgument, "Asset name missing")
}
if !assetRegex.MatchString(name) {
return status.Errorf(codes.InvalidArgument, "Invalid asset name %s", name)
}
if !IDRegex.MatchString(util.RemovePrefix(name)) {
return status.Errorf(codes.InvalidArgument, "Asset %q: %s", util.RemovePrefix(name), InvalidCharacters)
}
if r.GetAsset().GetLocation() == nil {
return status.Errorf(codes.InvalidArgument, "Asset location missing")
}
if r.GetAsset().GetLocation().GetZone() == ufspb.Zone_ZONE_UNSPECIFIED {
return status.Errorf(codes.InvalidArgument, "Lab unspecified")
}
if r.GetAsset().GetLocation().GetRack() == "" {
return status.Errorf(codes.InvalidArgument, "Rack missing")
}
r.GetAsset().Name = name
return nil
}
// Validate validates input requests of UpdateAsset.
func (r *UpdateAssetRequest) Validate() error {
if r.Asset == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
return validateResourceName(assetRegex, AssetNameFormat, r.Asset.GetName())
}
// Validate validates input requests of GetAsset.
func (r *GetAssetRequest) Validate() error {
return validateResourceNameAllowAllCharacters(assetRegex, AssetNameFormat, r.Name)
}
// Validate validates input requests of DeleteAsset.
func (r *DeleteAssetRequest) Validate() error {
return validateResourceNameAllowAllCharacters(assetRegex, AssetNameFormat, r.Name)
}
// Validate validates input requests of GetChromeOSDeviceDataRequest.
func (r *GetChromeOSDeviceDataRequest) Validate() error {
if r == nil {
return status.Errorf(codes.InvalidArgument, EmptyRequest)
}
if r.ChromeosDeviceId == "" && r.Hostname == "" {
return status.Errorf(codes.InvalidArgument, "Both Id and hostname are empty")
}
return nil
}
// Validate validates input requests of GetMachineLSEDeployment.
func (r *GetMachineLSEDeploymentRequest) Validate() error {
return validateResourceName(machineLSEDeploymentRegex, MachineLSEDeploymentNameFormat, r.Name)
}
// Validate validates input requests of UpdateMachineLSEDeploymentRequest.
func (r *UpdateMachineLSEDeploymentRequest) Validate() error {
if r == nil {
return status.Errorf(codes.InvalidArgument, EmptyRequest)
}
if r.GetMachineLseDeployment().GetSerialNumber() == "" {
return status.Errorf(codes.InvalidArgument, "cannot update a deployment record with empty serial number")
}
r.MachineLseDeployment.Hostname = strings.TrimSpace(r.MachineLseDeployment.Hostname)
r.MachineLseDeployment.SerialNumber = strings.TrimSpace(r.MachineLseDeployment.SerialNumber)
return nil
}
// Validate validates input requests of CreateCachingService.
func (r *CreateCachingServiceRequest) Validate() error {
if r.CachingService == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.CachingServiceId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !HostnameRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, fmt.Sprintf("name: %s", InvalidHostname))
}
if len(r.GetCachingService().GetServingSubnets()) != 0 && len(r.GetCachingService().GetZones()) != 0 {
return status.Error(codes.InvalidArgument, "Cannot specify both subnets and zones.")
}
switch n := r.GetCachingService().GetPrimaryNode(); {
case n == "":
return status.Errorf(codes.InvalidArgument, "Empty primary node name.")
case !HostnameRegex.MatchString(n):
return status.Errorf(codes.InvalidArgument, fmt.Sprintf("primaryNode: %s", InvalidHostname))
}
switch n := r.GetCachingService().GetSecondaryNode(); {
case n == "":
return status.Errorf(codes.InvalidArgument, "Empty secondary node name.")
case !HostnameRegex.MatchString(n):
return status.Errorf(codes.InvalidArgument, fmt.Sprintf("secondaryNode: %s", InvalidHostname))
}
r.CachingServiceId = id
return nil
}
// Validate validates input requests of UpdateCachingService.
func (r *UpdateCachingServiceRequest) Validate() error {
if r.CachingService == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
name := strings.TrimSpace(r.GetCachingService().GetName())
if name == "" {
return status.Errorf(codes.InvalidArgument, EmptyName)
}
if !cachingServiceRegex.MatchString(name) {
return status.Errorf(codes.InvalidArgument, CachingServiceNameFormat)
}
if n := r.GetCachingService().GetPrimaryNode(); n != "" && !HostnameRegex.MatchString(n) {
return status.Errorf(codes.InvalidArgument, fmt.Sprintf("primaryNode: %s", InvalidHostname))
}
if n := r.GetCachingService().GetSecondaryNode(); n != "" && !HostnameRegex.MatchString(n) {
return status.Errorf(codes.InvalidArgument, fmt.Sprintf("secondaryNode: %s", InvalidHostname))
}
return nil
}
// Validate validates input requests of GetCachingService.
func (r *GetCachingServiceRequest) Validate() error {
name := strings.TrimSpace(r.Name)
if name == "" {
return status.Errorf(codes.InvalidArgument, EmptyName)
}
if !cachingServiceRegex.MatchString(name) {
return status.Errorf(codes.InvalidArgument, CachingServiceNameFormat)
}
return nil
}
// Validate validates input requests of DeleteCachingService.
func (r *DeleteCachingServiceRequest) Validate() error {
name := strings.TrimSpace(r.Name)
if name == "" {
return status.Errorf(codes.InvalidArgument, EmptyName)
}
if !cachingServiceRegex.MatchString(name) {
return status.Errorf(codes.InvalidArgument, CachingServiceNameFormat)
}
return nil
}
// Validate validates input requests of CreateSchedulingUnit.
func (r *CreateSchedulingUnitRequest) Validate() error {
if r.SchedulingUnit == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
id := strings.TrimSpace(r.SchedulingUnitId)
if id == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if !IDRegex.MatchString(id) {
return status.Errorf(codes.InvalidArgument, "Scheduling Unit %q: %s", id, InvalidCharacters)
}
if !util.ValidateTags(r.SchedulingUnit.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
r.SchedulingUnitId = id
return nil
}
// Validate validates input requests of UpdateSchedulingUnit.
func (r *UpdateSchedulingUnitRequest) Validate() error {
if r.SchedulingUnit == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
if !util.ValidateTags(r.SchedulingUnit.GetTags()) {
return status.Errorf(codes.InvalidArgument, InvalidTags)
}
return validateResourceName(schedulingUnitRegex, SchedulingUnitNameFormat, r.SchedulingUnit.GetName())
}
// Validate validates input requests of GetSchedulingUnit.
func (r *GetSchedulingUnitRequest) Validate() error {
return validateResourceName(schedulingUnitRegex, SchedulingUnitNameFormat, r.Name)
}
// Validate the MachineLSE rename request.
func (r *RenameMachineLSERequest) Validate() error {
if r.Name == "" {
return status.Errorf(codes.InvalidArgument, EmptyName)
}
if r.NewName == "" {
return status.Errorf(codes.InvalidArgument, "Missing new name to rename")
}
return nil
}
// Validate the Asset rename request.
func (r *RenameAssetRequest) Validate() error {
if r.Name == "" {
return status.Errorf(codes.InvalidArgument, EmptyName)
}
if r.NewName == "" {
return status.Errorf(codes.InvalidArgument, "Missing new name to rename")
}
return nil
}
// Validate validates input requests of DeleteSchedulingUnit.
func (r *DeleteSchedulingUnitRequest) Validate() error {
return validateResourceName(schedulingUnitRegex, SchedulingUnitNameFormat, r.Name)
}
func validateResourceName(resourceRegex *regexp.Regexp, resourceNameFormat, name string) error {
name = strings.TrimSpace(name)
if name == "" {
return status.Errorf(codes.InvalidArgument, EmptyName)
}
if !resourceRegex.MatchString(name) {
return status.Errorf(codes.InvalidArgument, "Resource name %q: %s", name, resourceNameFormat)
}
if !IDRegex.MatchString(util.RemovePrefix(name)) {
return status.Errorf(codes.InvalidArgument, "ID %q: %s", util.RemovePrefix(name), InvalidCharacters)
}
return nil
}
func validateResourceNameAllowAllCharacters(resourceRegex *regexp.Regexp, resourceNameFormat, name string) error {
name = strings.TrimSpace(name)
if name == "" {
return status.Errorf(codes.InvalidArgument, EmptyName)
}
if !resourceRegex.MatchString(name) {
return status.Errorf(codes.InvalidArgument, resourceNameFormat)
}
return nil
}
// Validate validates input requests of UpdateConfigBundleRequest.
func (r *UpdateConfigBundleRequest) Validate() error {
var cb payload.ConfigBundle
if err := proto.Unmarshal(r.ConfigBundle, &cb); err != nil {
return err
}
if cb.GetDesignList()[0].GetProgramId().GetValue() == "" {
return status.Errorf(codes.InvalidArgument, "cannot update a ConfigBundle with empty program id")
}
if cb.GetDesignList()[0].GetId().GetValue() == "" {
return status.Errorf(codes.InvalidArgument, "cannot update a ConfigBundle with empty design id")
}
return nil
}
// Validate validates input requests of GetOwnershipData.
func (r *GetOwnershipDataRequest) Validate() error {
if r.GetHostname() == "" {
return status.Errorf(codes.InvalidArgument, EmptyName)
}
return nil
}
func validatePageSize(pageSize int32) error {
if pageSize < 0 {
return status.Errorf(codes.InvalidArgument, InvalidPageSize)
}
return nil
}
// ValidateMachineDBSource validates the MachineDBSource
func ValidateMachineDBSource(machinedb *MachineDBSource) error {
if machinedb == nil {
return emptyMachineDBSourceStatus.Err()
}
if machinedb.GetHost() == "" {
return invalidHostInMachineDBSourceStatus.Err()
}
return nil
}
// ValidateResourceKey validates a key of a resource
//
// TODO(xixuan): add validation for all imported data
func ValidateResourceKey(resources interface{}, k string) error {
vs := ParseResources(resources, k)
for _, v := range vs {
if !IDRegex.MatchString(v) {
return status.Errorf(codes.InvalidArgument, fmt.Sprintf("%s ('%s')", InvalidCharacters, v))
}
}
return nil
}
// ValidateFilter validates if the filter format is correct
func ValidateFilter(filter string) error {
if filter != "" {
filter = strings.Replace(filter, " ", "", -1)
if !FilterRegex.MatchString(filter) {
return status.Errorf(codes.InvalidArgument, InvalidFilterFormat)
}
}
return nil
}
// ParseResources parse a list of resources and returns a string slice by key
func ParseResources(args interface{}, k string) []string {
names := make([]string, 0)
v := reflect.ValueOf(args)
switch v.Kind() {
case reflect.Ptr:
names = append(names, parse(v.Elem(), k))
case reflect.Slice:
for i := 0; i < v.Len(); i++ {
n := parse(v.Index(i).Elem(), k)
if n != "" {
names = append(names, n)
}
}
}
return names
}
func parse(v reflect.Value, k string) string {
typeOfT := v.Type()
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
if typeOfT.Field(i).Name == k {
return f.Interface().(string)
}
}
return ""
}
// Validate validates input requests of GetDeviceDataRequest.
func (r *GetDeviceDataRequest) Validate() error {
if r == nil {
return status.Errorf(codes.InvalidArgument, EmptyRequest)
}
if r.DeviceId == "" && r.Hostname == "" {
return status.Errorf(codes.InvalidArgument, "Both Id and hostname are empty")
}
return nil
}
func (r *CreateDefaultWifiRequest) Validate() error {
if r == nil {
return status.Errorf(codes.InvalidArgument, EmptyRequest)
}
if r.GetDefaultWifiId() == "" {
return status.Errorf(codes.InvalidArgument, EmptyID)
}
if r.GetDefaultWifi() == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
return nil
}
func (r *GetDefaultWifiRequest) Validate() error {
if r == nil {
return status.Errorf(codes.InvalidArgument, EmptyRequest)
}
if r.GetName() == "" {
return status.Errorf(codes.InvalidArgument, "DefaultWifi name is empty")
}
return nil
}
func (r *DeleteDefaultWifiRequest) Validate() error {
return validateResourceName(defaultWifiRegex, DefaultWifiNameFormat, r.Name)
}
// Validate validates input requests of UpdateDefaultWifi.
func (r *UpdateDefaultWifiRequest) Validate() error {
if r.DefaultWifi == nil {
return status.Errorf(codes.InvalidArgument, NilEntity)
}
return validateResourceName(defaultWifiRegex, DefaultWifiNameFormat, r.DefaultWifi.GetName())
}