Skip to content

Commit 76aa3d3

Browse files
committed
feat(logging): enhance L4LBConfig and LoggingConfig with improved validation rules for optionalFields
1 parent 5ec2475 commit 76aa3d3

File tree

4 files changed

+38
-35
lines changed

4 files changed

+38
-35
lines changed

cmd/glbc/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ func main() {
192192
var l4LBConfigClient l4lbconfigclient.Interface
193193
if flags.F.ManageL4LBLogging && (flags.F.RunL4Controller || flags.F.RunL4NetLBController) {
194194
l4LBConfigCRDMeta := l4lbconfig.CRDMeta()
195+
klog.V(0).Info("Ensuring L4LBConfig CRD exists")
195196
if _, err := crdHandler.EnsureCRD(l4LBConfigCRDMeta, true); err != nil {
196197
klog.Fatalf("Failed to ensure L4LBConfig CRD: %v", err)
197198
}

pkg/apis/l4lbconfig/v1/types.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ type L4LBConfig struct {
3737
// +k8s:openapi-gen=true
3838
type L4LBConfigSpec struct {
3939
// Logging defines the telemetry and flow logging configuration for the L4 Load Balancer.
40+
// +k8s:validation:cel[0]:rule="(self.optionalMode == 'CUSTOM' && has(self.optionalFields) && size(self.optionalFields) > 0) || (self.optionalMode != 'CUSTOM' && (!has(self.optionalFields) || size(self.optionalFields) == 0))"
41+
// +k8s:validation:cel[0]:message="optionalFields can only be set when optionalMode is 'CUSTOM', and must be set when optionalMode is 'CUSTOM'"
4042
// +optional
4143
Logging *LoggingConfig `json:"logging,omitempty"`
4244
}
@@ -57,7 +59,6 @@ type L4LBConfigList struct {
5759
}
5860

5961
// LoggingConfig defines the parameters for LB logging.
60-
// +kubebuilder:validation:XValidation:rule="has(self.optionalFields) && size(self.optionalFields) > 0 ? self.optionalMode == 'CUSTOM' : true",message="optionalFields can only be set when optionalMode is 'CUSTOM'"
6162
// +k8s:openapi-gen=true
6263
type LoggingConfig struct {
6364
// Enabled allows toggling of Cloud Logging.
@@ -66,14 +67,15 @@ type LoggingConfig struct {
6667

6768
// SampleRate is the percentage of flows to log, from 0 to 1000000.
6869
// 1000000 means 100% of packets are logged.
69-
// +kubebuilder:validation:Minimum=0
70-
// +kubebuilder:validation:Maximum=1000000
70+
// +k8s:validation:cel[0]:rule="self >= 0 && self <= 1000000"
71+
// +k8s:validation:cel[0]:message="sampleRate must be between 0 and 1_000_000"
7172
// +optional
7273
SampleRate *int32 `json:"sampleRate,omitempty"`
7374

7475
// OptionalMode defines which metadata fields to include in the logs.
7576
// Options: INCLUDE_ALL_OPTIONAL, EXCLUDE_ALL_OPTIONAL, CUSTOM.
76-
// +kubebuilder:validation:Enum=INCLUDE_ALL_OPTIONAL;EXCLUDE_ALL_OPTIONAL;CUSTOM
77+
// +k8s:validation:cel[0]:rule="self in ['INCLUDE_ALL_OPTIONAL', 'EXCLUDE_ALL_OPTIONAL', 'CUSTOM']"
78+
// +k8s:validation:cel[0]:message="optionalMode must be one of 'INCLUDE_ALL_OPTIONAL', 'EXCLUDE_ALL_OPTIONAL', 'CUSTOM'"
7779
// +optional
7880
OptionalMode string `json:"optionalMode,omitempty"`
7981

pkg/apis/l4lbconfig/v1/zz_generated.openapi.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/l4lbconfig/l4lbconfig.go

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ import (
2828
"k8s.io/ingress-gce/pkg/crd"
2929
"k8s.io/ingress-gce/pkg/flags"
3030
"k8s.io/ingress-gce/pkg/l4annotations"
31-
common "k8s.io/kube-openapi/pkg/common"
3231
)
3332

3433
var (
35-
ErrL4LBConfigDoesNotExist = errors.New("no L4LBConfig for service port exists.")
36-
ErrL4LBConfigFailedToGet = errors.New("client had error getting L4LBConfig for service.")
37-
ErrL4LBConfigInvalidMode = errors.New("invalid OptionalMode in L4LBConfig for service.")
38-
allowedOptionalModes = []interface{}{"INCLUDE_ALL_OPTIONAL", "EXCLUDE_ALL_OPTIONAL", "CUSTOM"}
34+
ErrL4LBConfigDoesNotExist = errors.New("no L4LBConfig for service port exists.")
35+
ErrL4LBConfigFailedToGet = errors.New("client had error getting L4LBConfig for service.")
36+
ErrL4LBConfigInvalidMode = errors.New("invalid OptionalMode in L4LBConfig for service.")
37+
ErrL4LBConfigInvalidSampleRate = errors.New("invalid SampleRate in L4LBConfig for service.")
38+
allowedOptionalModes = []interface{}{"INCLUDE_ALL_OPTIONAL", "EXCLUDE_ALL_OPTIONAL", "CUSTOM"}
3939
)
4040

4141
const (
@@ -62,37 +62,12 @@ func CRDMeta() *crd.CRDMeta {
6262
"l4lbconfig",
6363
"l4lbconfigs",
6464
[]*crd.Version{
65-
crd.NewVersion("v1", "k8s.io/ingress-gce/pkg/apis/l4lbconfig/v1.L4LBConfig", getOpenAPIDefinitions, false),
65+
crd.NewVersion("v1", "k8s.io/ingress-gce/pkg/apis/l4lbconfig/v1.L4LBConfig", l4lbconfigv1.GetOpenAPIDefinitions, false),
6666
},
6767
)
6868
return meta
6969
}
7070

71-
func getOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
72-
defs := l4lbconfigv1.GetOpenAPIDefinitions(ref)
73-
74-
if def, ok := defs["k8s.io/ingress-gce/pkg/apis/l4lbconfig/v1.LoggingConfig"]; ok {
75-
// Patch SampleRate
76-
if prop, ok := def.Schema.SchemaProps.Properties["sampleRate"]; ok {
77-
min := minSampleRate
78-
max := maxSampleRate
79-
prop.SchemaProps.Minimum = &min
80-
prop.SchemaProps.Maximum = &max
81-
def.Schema.SchemaProps.Properties["sampleRate"] = prop
82-
}
83-
84-
// Patch OptionalMode (Enum)
85-
if prop, ok := def.Schema.SchemaProps.Properties["optionalMode"]; ok {
86-
prop.SchemaProps.Enum = allowedOptionalModes
87-
def.Schema.SchemaProps.Properties["optionalMode"] = prop
88-
}
89-
90-
defs["k8s.io/ingress-gce/pkg/apis/l4lbconfig/v1.LoggingConfig"] = def
91-
}
92-
93-
return defs
94-
}
95-
9671
// GetL4LBConfigForService returns the corresponding L4LBConfig for
9772
// the given Service if specified.
9873
func GetL4LBConfigForService(l4lbConfigLister cache.Store, svc *corev1.Service) (*l4lbconfigv1.L4LBConfig, error) {
@@ -157,13 +132,17 @@ func DetermineL4LoggingConfig(
157132
resolvedConfig.OptionalMode = "EXCLUDE_ALL_OPTIONAL"
158133
}
159134

135+
// Double-check OptionalMode validity before proceeding with OptionalFields checks
136+
// Validation already occurs at the API level, but this serves as a safeguard against any unexpected values.
160137
switch resolvedConfig.OptionalMode {
161138
case "EXCLUDE_ALL_OPTIONAL", "INCLUDE_ALL_OPTIONAL", "CUSTOM":
162139
// Valid
163140
default:
164141
return nil, NewConditionLoggingInvalid(ErrL4LBConfigInvalidMode), ErrL4LBConfigInvalidMode
165142
}
166143

144+
// Double-check consistency between OptionalMode and OptionalFields
145+
// Validation already occurs at the API level, but this serves as a safeguard against any unexpected states.
167146
if resolvedConfig.OptionalMode != "CUSTOM" && len(resolvedConfig.OptionalFields) > 0 {
168147
return nil, NewConditionLoggingInvalid(ErrL4LBConfigInvalidMode), ErrL4LBConfigInvalidMode
169148
}
@@ -178,6 +157,12 @@ func DetermineL4LoggingConfig(
178157
resolvedConfig.SampleRate = defaultSampleRate
179158
}
180159

160+
// Doube-check SampleRate validity before returning the resolved config
161+
// Validation already occurs at the API level, but this serves as a safeguard against any unexpected values.
162+
if resolvedConfig.SampleRate < 0 || resolvedConfig.SampleRate > 1 {
163+
return nil, NewConditionLoggingInvalid(ErrL4LBConfigInvalidSampleRate), ErrL4LBConfigInvalidSampleRate
164+
}
165+
181166
return resolvedConfig, NewConditionLoggingReconciled(), nil
182167
}
183168

0 commit comments

Comments
 (0)