@@ -3944,6 +3944,179 @@ func TestRenderOVNKubernetesEnablePersistentIPs(t *testing.T) {
39443944 g .Expect (objs ).To (ContainElement (HaveKubernetesID ("CustomResourceDefinition" , "" , "ipamclaims.k8s.cni.cncf.io" )))
39453945}
39463946
3947+ // TestRenderOVNKubernetesReachability tests egress IP reachability timeout rendering
3948+ func TestRenderOVNKubernetesReachability (t * testing.T ) {
3949+ g := NewGomegaWithT (t )
3950+
3951+ testCases := []struct {
3952+ name string
3953+ reachabilityTimeout * uint32
3954+ expectKubernetesFeatureReachability bool
3955+ expectErr bool
3956+ }{
3957+ {
3958+ name : "No reachability timeout (nil)" ,
3959+ reachabilityTimeout : nil ,
3960+ expectKubernetesFeatureReachability : false ,
3961+ expectErr : false ,
3962+ },
3963+ {
3964+ name : "Reachability timeout set to 0" ,
3965+ reachabilityTimeout : ptrToUint32 (0 ),
3966+ expectKubernetesFeatureReachability : true ,
3967+ expectErr : false ,
3968+ },
3969+ {
3970+ name : "Reachability timeout changed to 10" ,
3971+ reachabilityTimeout : ptrToUint32 (10 ),
3972+ expectKubernetesFeatureReachability : true ,
3973+ expectErr : false ,
3974+ },
3975+ {
3976+ name : "Reachability timeout unchanged to 10" ,
3977+ reachabilityTimeout : ptrToUint32 (10 ),
3978+ expectKubernetesFeatureReachability : true ,
3979+ expectErr : false ,
3980+ },
3981+ {
3982+ name : "Reachability timeout changed to 5" ,
3983+ reachabilityTimeout : ptrToUint32 (5 ),
3984+ expectKubernetesFeatureReachability : true ,
3985+ expectErr : false ,
3986+ },
3987+ {
3988+ name : "Reachability timeout disabled" ,
3989+ reachabilityTimeout : nil ,
3990+ expectKubernetesFeatureReachability : false ,
3991+ expectErr : false ,
3992+ },
3993+ }
3994+
3995+ for _ , tc := range testCases {
3996+ t .Run (tc .name , func (t * testing.T ) {
3997+ crd := OVNKubernetesConfig .DeepCopy ()
3998+ config := & crd .Spec
3999+ config .DefaultNetwork .OVNKubernetesConfig .EgressIPConfig .ReachabilityTotalTimeoutSeconds = tc .reachabilityTimeout
4000+
4001+ errs := validateOVNKubernetes (config )
4002+ g .Expect (errs ).To (HaveLen (0 ))
4003+ fillDefaults (config , nil )
4004+
4005+ // at the same time we have an upgrade
4006+ t .Setenv ("RELEASE_VERSION" , "2.0.0" )
4007+
4008+ bootstrapResult := fakeBootstrapResult ()
4009+ bootstrapResult .OVN = bootstrap.OVNBootstrapResult {
4010+ ControlPlaneReplicaCount : 3 ,
4011+ OVNKubernetesConfig : & bootstrap.OVNConfigBoostrapResult {
4012+ DpuHostModeLabel : OVN_NODE_SELECTOR_DEFAULT_DPU_HOST ,
4013+ DpuModeLabel : OVN_NODE_SELECTOR_DEFAULT_DPU ,
4014+ SmartNicModeLabel : OVN_NODE_SELECTOR_DEFAULT_SMART_NIC ,
4015+ MgmtPortResourceName : "" ,
4016+ HyperShiftConfig : & bootstrap.OVNHyperShiftBootstrapResult {
4017+ Enabled : false ,
4018+ },
4019+ },
4020+ }
4021+
4022+ featureGatesCNO := getDefaultFeatureGates ()
4023+ fakeClient := cnofake .NewFakeClient ()
4024+ // Set is as Hypershift hosted control plane.
4025+ bootstrapResult .Infra = bootstrap.InfraStatus {}
4026+ bootstrapResult .Infra .HostedControlPlane = & hypershift.HostedControlPlane {}
4027+ objs , _ , err := renderOVNKubernetes (config , bootstrapResult , manifestDirOvn , fakeClient , featureGatesCNO )
4028+ if tc .expectErr {
4029+ g .Expect (err ).To (HaveOccurred ())
4030+ return
4031+ }
4032+ g .Expect (err ).NotTo (HaveOccurred ())
4033+
4034+ // Find the ovnkube-config ConfigMap and check the template data
4035+ var configMap * uns.Unstructured
4036+ for _ , obj := range objs {
4037+ if obj .GetKind () == "ConfigMap" && obj .GetName () == "ovnkube-config" {
4038+ configMap = obj
4039+ break
4040+ }
4041+ }
4042+ g .Expect (configMap ).NotTo (BeNil (), "ovnkube-config ConfigMap should exist" )
4043+
4044+ // Check the transport value in the rendered ConfigMap
4045+ configMapData , found , err := uns .NestedStringMap (configMap .Object , "data" )
4046+ g .Expect (err ).NotTo (HaveOccurred ())
4047+ g .Expect (found ).To (BeTrue (), "ConfigMap should have data field" )
4048+ ovnkubeConf := configMapData ["ovnkube.conf" ]
4049+
4050+ var scriptCP string
4051+ var scriptNode string
4052+ for _ , obj := range objs {
4053+ // Gets script that starts ovnkube-control-plane pod, ovnkube-cluster-manager container
4054+ if obj .GetKind () == "Deployment" && obj .GetName () == "ovnkube-control-plane" && obj .GetNamespace () == "openshift-ovn-kubernetes" {
4055+ containers , found , err := uns .NestedSlice (obj .Object , "spec" , "template" , "spec" , "containers" )
4056+ g .Expect (err ).NotTo (HaveOccurred ())
4057+ g .Expect (found ).To (BeTrue ())
4058+ for _ , c := range containers {
4059+ cm := c .(map [string ]interface {})
4060+ if name , ok := cm ["name" ]; ok && (name == "ovnkube-cluster-manager" || name == "ovnkube-control-plane" ) {
4061+ command , found , err := uns .NestedSlice (cm , "command" )
4062+ g .Expect (err ).NotTo (HaveOccurred ())
4063+ g .Expect (found ).To (BeTrue ())
4064+ g .Expect (len (command )).To (BeNumerically (">" , 2 ))
4065+ scriptCP = command [2 ].(string )
4066+ break
4067+ }
4068+ }
4069+ }
4070+
4071+ // Gets script that starts ovnkube-node pod, ovnkube-controller container
4072+ if obj .GetKind () == "ConfigMap" && obj .GetName () == "ovnkube-script-lib" {
4073+ configMap = obj
4074+ configMapData , found , err := uns .NestedStringMap (configMap .Object , "data" )
4075+ g .Expect (err ).NotTo (HaveOccurred ())
4076+ g .Expect (found ).To (BeTrue (), "ovnkube-script-lib ConfigMap should have data field" )
4077+ scriptNode = configMapData ["ovnkube-lib.sh" ]
4078+ }
4079+ }
4080+ g .Expect (scriptCP ).NotTo (BeEmpty ())
4081+ g .Expect (scriptNode ).NotTo (BeEmpty ())
4082+
4083+ if tc .expectKubernetesFeatureReachability {
4084+ g .Expect (ovnkubeConf ).To (ContainSubstring ("[ovnkubernetesfeature]" ),
4085+ "ConfigMap should contain [ovnkubernetesfeature] section when enabled" )
4086+ g .Expect (tc .reachabilityTimeout ).NotTo (BeNil ())
4087+ g .Expect (ovnkubeConf ).To (
4088+ ContainSubstring (fmt .Sprintf ("egressip-reachability-total-timeout=%d" , * tc .reachabilityTimeout )),
4089+ "ConfigMap should contain the configured reachability timeout value" ,
4090+ )
4091+ g .Expect (ovnkubeConf ).To (ContainSubstring ("egressip-reachability-total-timeout=" ),
4092+ "ConfigMap should contain egressip-reachability-total-timeout=" )
4093+
4094+ g .Expect (scriptCP ).To (
4095+ ContainSubstring (fmt .Sprintf ("--egressip-reachability-total-timeout %d" , * tc .reachabilityTimeout )),
4096+ "ovnkube-control-plane pod template should contain the configured reachability timeout value" ,
4097+ )
4098+ g .Expect (scriptNode ).To (
4099+ ContainSubstring (fmt .Sprintf ("--egressip-reachability-total-timeout %d" , * tc .reachabilityTimeout )),
4100+ "ovnkube-node pod template should contain the configured reachability timeout value" ,
4101+ )
4102+
4103+ } else {
4104+ g .Expect (ovnkubeConf ).NotTo (ContainSubstring ("egressip-reachability-total-timeout=" ),
4105+ "ConfigMap should not contain egressip-reachability-total-timeout= section when disabled" )
4106+
4107+ g .Expect (scriptCP ).NotTo (
4108+ ContainSubstring ("--egressip-reachability-total-timeout" ),
4109+ "ovnkube-control-plane pod template should not contain the configured reachability timeout value" ,
4110+ )
4111+ g .Expect (scriptNode ).NotTo (
4112+ ContainSubstring ("--egressip-reachability-total-timeout" ),
4113+ "ovnkube-node pod template should not contain the configured reachability timeout value" ,
4114+ )
4115+ }
4116+ })
4117+ }
4118+ }
4119+
39474120type fakeClientReader struct {
39484121 configMap * v1.ConfigMap
39494122}
0 commit comments