github.com/google/cloudprober@v0.11.3/validators/validators.go (about)

     1  // Copyright 2018-2019 The Cloudprober Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package validators provides an entrypoint for the cloudprober's validators
    16  // framework.
    17  package validators
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/google/cloudprober/logger"
    23  	"github.com/google/cloudprober/metrics"
    24  	"github.com/google/cloudprober/validators/http"
    25  	"github.com/google/cloudprober/validators/integrity"
    26  	configpb "github.com/google/cloudprober/validators/proto"
    27  	"github.com/google/cloudprober/validators/regex"
    28  )
    29  
    30  // Validator implements a validator.
    31  //
    32  // A validator runs a test on the provided input, usually the probe response,
    33  // and returns the test result. If test cannot be run successfully for some
    34  // reason (e.g. for malformed input), an error is returned.
    35  type Validator struct {
    36  	Name     string
    37  	Validate func(input *Input) (bool, error)
    38  }
    39  
    40  // Init initializes the validators defined in the config.
    41  func Init(validatorConfs []*configpb.Validator, l *logger.Logger) ([]*Validator, error) {
    42  	var validators []*Validator
    43  	names := make(map[string]bool)
    44  
    45  	for _, vc := range validatorConfs {
    46  		if names[vc.GetName()] {
    47  			return nil, fmt.Errorf("validator %s is defined twice", vc.GetName())
    48  		}
    49  
    50  		v, err := initValidator(vc, l)
    51  		if err != nil {
    52  			return nil, err
    53  		}
    54  
    55  		validators = append(validators, v)
    56  		names[vc.GetName()] = true
    57  	}
    58  
    59  	return validators, nil
    60  }
    61  
    62  func initValidator(validatorConf *configpb.Validator, l *logger.Logger) (validator *Validator, err error) {
    63  	validator = &Validator{Name: validatorConf.GetName()}
    64  
    65  	switch validatorConf.Type.(type) {
    66  	case *configpb.Validator_HttpValidator:
    67  		v := &http.Validator{}
    68  		if err := v.Init(validatorConf.GetHttpValidator(), l); err != nil {
    69  			return nil, err
    70  		}
    71  		validator.Validate = func(input *Input) (bool, error) {
    72  			return v.Validate(input.Response, input.ResponseBody)
    73  		}
    74  		return
    75  
    76  	case *configpb.Validator_IntegrityValidator:
    77  		v := &integrity.Validator{}
    78  		if err := v.Init(validatorConf.GetIntegrityValidator(), l); err != nil {
    79  			return nil, err
    80  		}
    81  		validator.Validate = func(input *Input) (bool, error) {
    82  			return v.Validate(input.ResponseBody)
    83  		}
    84  		return
    85  
    86  	case *configpb.Validator_Regex:
    87  		v := &regex.Validator{}
    88  		if err := v.Init(validatorConf.GetRegex(), l); err != nil {
    89  			return nil, err
    90  		}
    91  		validator.Validate = func(input *Input) (bool, error) {
    92  			return v.Validate(input.ResponseBody)
    93  		}
    94  		return
    95  	default:
    96  		err = fmt.Errorf("unknown validator type: %v", validatorConf.Type)
    97  		return
    98  	}
    99  }
   100  
   101  // Input encapsulates the input for validators.
   102  type Input struct {
   103  	Response     interface{}
   104  	ResponseBody []byte
   105  }
   106  
   107  // RunValidators runs the list of validators on the given response and
   108  // responseBody, updates the given validationFailure map and returns the list
   109  // of failures.
   110  func RunValidators(vs []*Validator, input *Input, validationFailure *metrics.Map, l *logger.Logger) []string {
   111  	var failures []string
   112  
   113  	for _, v := range vs {
   114  		success, err := v.Validate(input)
   115  		if err != nil {
   116  			l.Error("Error while running the validator ", v.Name, ": ", err.Error())
   117  			continue
   118  		}
   119  		if !success {
   120  			validationFailure.IncKey(v.Name)
   121  			failures = append(failures, v.Name)
   122  		}
   123  	}
   124  
   125  	return failures
   126  }
   127  
   128  // ValidationFailureMap returns an initialized validation failures map.
   129  func ValidationFailureMap(vs []*Validator) *metrics.Map {
   130  	m := metrics.NewMap("validator", metrics.NewInt(0))
   131  	// Initialize validation failure map with validator keys, so that we always
   132  	// export the metrics.
   133  	for _, v := range vs {
   134  		m.IncKeyBy(v.Name, metrics.NewInt(0))
   135  	}
   136  	return m
   137  }