@@ -780,3 +780,110 @@ func TestCustomizeMultipleDeployment(t *testing.T) {
780780 })
781781 }
782782}
783+
784+ func TestParseFeatureGates (t * testing.T ) {
785+ tests := []struct {
786+ name string
787+ args []string
788+ expected map [string ]bool
789+ }{
790+ {
791+ name : "no feature gates" ,
792+ args : []string {"--webhook-port=2345" },
793+ expected : map [string ]bool {},
794+ },
795+ {
796+ name : "single feature gate" ,
797+ args : []string {"--feature-gates=MachinePool=true" },
798+ expected : map [string ]bool {"MachinePool" : true },
799+ },
800+ {
801+ name : "multiple feature gates" ,
802+ args : []string {"--feature-gates=MachinePool=true,ClusterTopology=false,RuntimeSDK=true" },
803+ expected : map [string ]bool {"MachinePool" : true , "ClusterTopology" : false , "RuntimeSDK" : true },
804+ },
805+ {
806+ name : "feature gates among other args" ,
807+ args : []string {"--webhook-port=2345" , "--feature-gates=MachinePool=true,ClusterTopology=false" , "--v=5" },
808+ expected : map [string ]bool {"MachinePool" : true , "ClusterTopology" : false },
809+ },
810+ }
811+
812+ for _ , tt := range tests {
813+ t .Run (tt .name , func (t * testing.T ) {
814+ result := parseFeatureGates (tt .args )
815+ if ! reflect .DeepEqual (result , tt .expected ) {
816+ t .Errorf ("parseFeatureGates() = %v, want %v" , result , tt .expected )
817+ }
818+ })
819+ }
820+ }
821+
822+ func TestAdditiveFeatureGates (t * testing.T ) {
823+ deplWithExistingGates := & appsv1.Deployment {
824+ ObjectMeta : metav1.ObjectMeta {
825+ Name : "manager" ,
826+ Namespace : metav1 .NamespaceSystem ,
827+ },
828+ Spec : appsv1.DeploymentSpec {
829+ Template : corev1.PodTemplateSpec {
830+ ObjectMeta : metav1.ObjectMeta {
831+ Name : "manager" ,
832+ },
833+ Spec : corev1.PodSpec {
834+ Containers : []corev1.Container {
835+ {
836+ Name : "manager" ,
837+ Image : "registry.k8s.io/a-manager:1.6.2" ,
838+ Args : []string {
839+ "--webhook-port=2345" ,
840+ "--feature-gates=MachinePool=true,MachineSetPreflightChecks=true,PriorityQueue=false" ,
841+ },
842+ },
843+ },
844+ },
845+ },
846+ },
847+ }
848+
849+ managerSpec := & operatorv1.ManagerSpec {
850+ FeatureGates : map [string ]bool {
851+ "ClusterTopology" : true ,
852+ "MachineSetPreflightChecks" : false ,
853+ },
854+ }
855+
856+ container := findManagerContainer (& deplWithExistingGates .Spec )
857+ if container == nil {
858+ t .Fatal ("expected container to be found" )
859+ }
860+
861+ if err := customizeManagerContainer (managerSpec , container ); err != nil {
862+ t .Fatalf ("customizeManagerContainer failed: %v" , err )
863+ }
864+
865+ featureGatesArg := ""
866+
867+ for _ , arg := range container .Args {
868+ if len (arg ) > 16 && arg [:16 ] == "--feature-gates=" {
869+ featureGatesArg = arg [16 :]
870+ break
871+ }
872+ }
873+
874+ if featureGatesArg == "" {
875+ t .Fatal ("expected --feature-gates arg to be present" )
876+ }
877+
878+ actualGates := parseFeatureGates ([]string {"--feature-gates=" + featureGatesArg })
879+ expectedGates := map [string ]bool {
880+ "MachinePool" : true ,
881+ "ClusterTopology" : true ,
882+ "MachineSetPreflightChecks" : false ,
883+ "PriorityQueue" : false ,
884+ }
885+
886+ if ! reflect .DeepEqual (actualGates , expectedGates ) {
887+ t .Errorf ("Feature gates not merged correctly.\n Got: %v\n Want: %v" , actualGates , expectedGates )
888+ }
889+ }
0 commit comments