in confgenerator/config.go [181:305]
func newValidator() *validator.Validate {
v := validator.New()
v.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("yaml"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
// duration validates that the value is a valid duration and >= the parameter
v.RegisterValidation("duration", func(fl validator.FieldLevel) bool {
fieldStr := fl.Field().String()
if fieldStr == "" {
// Ignore the case where this field is not actually specified or is left empty.
return true
}
t, err := time.ParseDuration(fl.Field().String())
if err != nil {
return false
}
tmin, err := time.ParseDuration(fl.Param())
if err != nil {
panic(err)
}
return t >= tmin
})
v.RegisterStructValidation(validatePrometheusConfig, &promconfig.Config{})
// filter validates that a Cloud Logging filter condition is valid
v.RegisterValidation("filter", func(fl validator.FieldLevel) bool {
_, err := filter.NewFilter(fl.Field().String())
return err == nil
})
// field validates that a Cloud Logging field expression is valid
v.RegisterValidation("field", func(fl validator.FieldLevel) bool {
_, err := filter.NewMember(fl.Field().String())
// TODO: Disallow specific target fields?
return err == nil
})
v.RegisterValidation("fieldlegacy", func(fl validator.FieldLevel) bool {
_, err := filter.NewMemberLegacy(fl.Field().String())
// TODO: Disallow specific target fields?
return err == nil
})
// distinctfield validates that a key in a map refers to different fields from the other keys in the map.
// Use this as keys,distinctfield,endkeys
v.RegisterValidation("distinctfield", func(fl validator.FieldLevel) bool {
// Get the map that contains this key.
parent, parentkind, found := fl.GetStructFieldOKAdvanced(fl.Parent(), fl.StructFieldName()[:strings.Index(fl.StructFieldName(), "[")])
if !found {
return false
}
if parentkind != reflect.Map {
fmt.Printf("not map\n")
return false
}
k1 := fl.Field().String()
field, err := filter.NewMember(k1)
if err != nil {
fmt.Printf("newmember %q: %v", fl.Field().String(), err)
return false
}
for _, key := range parent.MapKeys() {
k2 := key.String()
if k1 == k2 {
// Skip itself
continue
}
field2, err := filter.NewMember(k2)
if err != nil {
continue
}
if field2.Equals(*field) {
return false
}
}
return true
})
// writablefield checks to make sure the field is writable
v.RegisterValidation("writablefield", func(fl validator.FieldLevel) bool {
m1, err := filter.NewMember(fl.Field().String())
if err != nil {
// The "field" validator will handle this better.
return true
}
// Currently, instrumentation_source is the only field that is not writable.
m2, err := filter.NewMember(InstrumentationSourceLabel)
if err != nil {
panic(err)
}
return !m2.Equals(*m1)
})
// multipleof_time validates that the value duration is a multiple of the parameter
v.RegisterValidation("multipleof_time", func(fl validator.FieldLevel) bool {
t, ok := fl.Field().Interface().(time.Duration)
if !ok {
panic(fmt.Sprintf("multipleof_time: could not convert %s to time duration", fl.Field().String()))
}
tfactor, err := time.ParseDuration(fl.Param())
if err != nil {
panic(fmt.Sprintf("multipleof_time: could not convert %s to time duration", fl.Param()))
}
return t%tfactor == 0
})
// winlogchannels wraps validateWinlogChannels when receiver_version > 1 and validateWinlogV1Channels when receiver_version = 1
// TODO: relax the "receiver_version > 1" constraint and replace validateWinlogChannels with built-in validator primitives
v.RegisterValidationCtx("winlogchannels", func(ctx context.Context, fl validator.FieldLevel) bool {
receiver, ok := fl.Parent().Interface().(LoggingReceiverWindowsEventLog)
if !ok {
panic(fmt.Sprintf("winlogchannels: could not convert %s's parent to LoggingReceiverWindowsEventLog", fl.Field().String()))
}
if receiver.IsDefaultVersion() {
if err := validateWinlogV1Channels(ctx, receiver.Channels); err != nil {
// Only emit a soft failure (warning) here, because:
// 1) we want this to be backwards compatible, and
// 2) the implementation of the validation is not officially documented to be the "correct" way to do it
log.Print(err)
}
return true
}
return validateWinlogChannels(receiver.Channels) == nil
})
// Validates that experimental config components are enabled via EXPERIMENTAL_FEATURES
registerExperimentalValidations(v)
return v
}