github.com/Axway/agent-sdk@v1.1.101/pkg/config/validator.go (about)

     1  package config
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/Axway/agent-sdk/pkg/util"
     7  )
     8  
     9  // ValidateConfig - Validates the agent config
    10  // Uses reflection to get the IConfigValidator interface on the config struct or
    11  // struct variable.
    12  // Makes call to ValidateCfg method except if the struct variable is of CentralConfig type
    13  // as the validation for CentralConfig is already done during parseCentralConfig
    14  func ValidateConfig(cfg interface{}) error {
    15  	// This defer func is to catch a possible panic that WILL occur if the cfg object that is passed in embeds the IConfigValidator interface
    16  	// within its struct, but does NOT implement the ValidateCfg method. While it might be that this method really isn't necessary, we will
    17  	// log an error alerting the user in case it wasn't intentional.
    18  	defer util.HandleInterfaceFuncNotImplemented(cfg, "ValidateCfg", "IConfigValidator")
    19  
    20  	// Check if top level struct has Validate. If it does then call Validate
    21  	// only at top level
    22  	if cfg == nil {
    23  		return nil
    24  	}
    25  
    26  	if objInterface, ok := cfg.(IConfigValidator); ok {
    27  		err := objInterface.ValidateCfg()
    28  		if err != nil {
    29  			return err
    30  		}
    31  	}
    32  
    33  	// If the parameter is of struct pointer, use indirection to get the
    34  	// real value object
    35  	v := reflect.ValueOf(cfg)
    36  	if v.Kind() == reflect.Ptr {
    37  		v = reflect.Indirect(v)
    38  	}
    39  
    40  	return validateFields(cfg, v)
    41  }
    42  
    43  func validateFields(cfg interface{}, v reflect.Value) error {
    44  	// Look for Validate method on struct properties and invoke it
    45  	for i := 0; i < v.NumField(); i++ {
    46  		if v.Field(i).CanInterface() {
    47  			fieldInterface := v.Field(i).Interface()
    48  			// Skip the property it is CentralConfig type as its already Validated
    49  			// during parseCentralConfig
    50  
    51  			if shouldValidateField(cfg, fieldInterface) {
    52  				if objInterface, ok := fieldInterface.(IConfigValidator); ok {
    53  					err := ValidateConfig(objInterface)
    54  					if err != nil {
    55  						return err
    56  					}
    57  				}
    58  			}
    59  		}
    60  	}
    61  
    62  	return nil
    63  }
    64  
    65  func shouldValidateField(cfg interface{}, fieldInterface interface{}) bool {
    66  	_, isTopLevelCentralCfg := cfg.(CentralConfig)
    67  	if isTopLevelCentralCfg {
    68  		return true
    69  	}
    70  
    71  	_, isFieldCentralCfg := fieldInterface.(CentralConfig)
    72  	return !isFieldCentralCfg
    73  }