|
6 | 6 | goerrors "errors" |
7 | 7 | "fmt" |
8 | 8 | "log" |
| 9 | + "math" |
9 | 10 | "os" |
10 | 11 | "reflect" |
11 | 12 | "sort" |
@@ -681,16 +682,26 @@ func (c *Config) ValidateGlobalConfig(ctx context.Context) *gerr.GatewayDError { |
681 | 682 | } |
682 | 683 |
|
683 | 684 | for configGroup := range globalConfig.Servers { |
684 | | - if globalConfig.Servers[configGroup] == nil { |
| 685 | + serverConfig := globalConfig.Servers[configGroup] |
| 686 | + |
| 687 | + if serverConfig == nil { |
685 | 688 | err := fmt.Errorf("\"servers.%s\" is nil or empty", configGroup) |
686 | 689 | span.RecordError(err) |
687 | 690 | errors = append(errors, gerr.ErrValidationFailed.Wrap(err)) |
| 691 | + continue |
688 | 692 | } |
689 | 693 | if configGroup != strings.ToLower(configGroup) { |
690 | 694 | err := fmt.Errorf(`"servers.%s" is not lowercase`, configGroup) |
691 | 695 | span.RecordError(err) |
692 | 696 | errors = append(errors, gerr.ErrValidationFailed.Wrap(err)) |
693 | 697 | } |
| 698 | + |
| 699 | + // Validate Load Balancing Rules |
| 700 | + validatelBRulesErrors := ValidateLoadBalancingRules(serverConfig, configGroup, clientConfigGroups) |
| 701 | + for _, err := range validatelBRulesErrors { |
| 702 | + span.RecordError(err) |
| 703 | + errors = append(errors, gerr.ErrValidationFailed.Wrap(err)) |
| 704 | + } |
694 | 705 | } |
695 | 706 |
|
696 | 707 | if len(globalConfig.Servers) > 1 { |
@@ -797,3 +808,113 @@ func generateTagMapping(structs []interface{}, tagMapping map[string]string) { |
797 | 808 | } |
798 | 809 | } |
799 | 810 | } |
| 811 | + |
| 812 | +// ValidateLoadBalancingRules validates the load balancing rules in the server configuration. |
| 813 | +func ValidateLoadBalancingRules( |
| 814 | + serverConfig *Server, |
| 815 | + configGroup string, |
| 816 | + clientConfigGroups map[string]map[string]bool, |
| 817 | +) []error { |
| 818 | + var errors []error |
| 819 | + |
| 820 | + // Return early if there are no load balancing rules |
| 821 | + if serverConfig.LoadBalancer.LoadBalancingRules == nil { |
| 822 | + return errors |
| 823 | + } |
| 824 | + |
| 825 | + // Validate each load balancing rule |
| 826 | + for _, rule := range serverConfig.LoadBalancer.LoadBalancingRules { |
| 827 | + // Validate the condition of the rule |
| 828 | + if err := validateRuleCondition(rule.Condition, configGroup); err != nil { |
| 829 | + errors = append(errors, err) |
| 830 | + } |
| 831 | + |
| 832 | + // Validate the distribution of the rule |
| 833 | + if err := validateDistribution( |
| 834 | + rule.Distribution, |
| 835 | + configGroup, |
| 836 | + rule.Condition, |
| 837 | + clientConfigGroups, |
| 838 | + ); err != nil { |
| 839 | + errors = append(errors, err) |
| 840 | + } |
| 841 | + } |
| 842 | + |
| 843 | + return errors |
| 844 | +} |
| 845 | + |
| 846 | +// validateRuleCondition checks if the rule condition is empty for LoadBalancingRules. |
| 847 | +func validateRuleCondition(condition string, configGroup string) error { |
| 848 | + if condition == "" { |
| 849 | + err := fmt.Errorf(`"servers.%s.loadBalancer.loadBalancingRules.condition" is nil or empty`, configGroup) |
| 850 | + return err |
| 851 | + } |
| 852 | + return nil |
| 853 | +} |
| 854 | + |
| 855 | +// validateDistribution checks if the distribution list is valid for LoadBalancingRules. |
| 856 | +func validateDistribution( |
| 857 | + distributionList []Distribution, |
| 858 | + configGroup string, |
| 859 | + condition string, |
| 860 | + clientConfigGroups map[string]map[string]bool, |
| 861 | +) error { |
| 862 | + // Check if the distribution list is empty |
| 863 | + if len(distributionList) == 0 { |
| 864 | + return fmt.Errorf( |
| 865 | + `"servers.%s.loadBalancer.loadBalancingRules.distribution" is empty`, |
| 866 | + configGroup, |
| 867 | + ) |
| 868 | + } |
| 869 | + |
| 870 | + var totalWeight int |
| 871 | + for _, distribution := range distributionList { |
| 872 | + // Validate each distribution entry |
| 873 | + if err := validateDistributionEntry(distribution, configGroup, condition, clientConfigGroups); err != nil { |
| 874 | + return err |
| 875 | + } |
| 876 | + |
| 877 | + // Check if adding the weight would exceed the maximum integer value |
| 878 | + if totalWeight > math.MaxInt-distribution.Weight { |
| 879 | + return fmt.Errorf( |
| 880 | + `"servers.%s.loadBalancer.loadBalancingRules.%s" total weight exceeds maximum int value`, |
| 881 | + configGroup, |
| 882 | + condition, |
| 883 | + ) |
| 884 | + } |
| 885 | + |
| 886 | + totalWeight += distribution.Weight |
| 887 | + } |
| 888 | + |
| 889 | + return nil |
| 890 | +} |
| 891 | + |
| 892 | +// validateDistributionEntry validates a single distribution entry for LoadBalancingRules. |
| 893 | +func validateDistributionEntry( |
| 894 | + distribution Distribution, |
| 895 | + configGroup string, |
| 896 | + condition string, |
| 897 | + clientConfigGroups map[string]map[string]bool, |
| 898 | +) error { |
| 899 | + // Check if the distribution.ProxyName is referenced in the proxy configuration |
| 900 | + if !clientConfigGroups[configGroup][distribution.ProxyName] { |
| 901 | + return fmt.Errorf( |
| 902 | + `"servers.%s.loadBalancer.loadBalancingRules.%s.%s" not referenced in proxy configuration`, |
| 903 | + configGroup, |
| 904 | + condition, |
| 905 | + distribution.ProxyName, |
| 906 | + ) |
| 907 | + } |
| 908 | + |
| 909 | + // Ensure that the distribution weight is positive |
| 910 | + if distribution.Weight <= 0 { |
| 911 | + return fmt.Errorf( |
| 912 | + `"servers.%s.loadBalancer.loadBalancingRules.%s.%s.weight" must be positive`, |
| 913 | + configGroup, |
| 914 | + condition, |
| 915 | + distribution.ProxyName, |
| 916 | + ) |
| 917 | + } |
| 918 | + |
| 919 | + return nil |
| 920 | +} |
0 commit comments