@@ -85,7 +85,7 @@ const (
8585	dnsDomain                =  "dns-domain" 
8686	serviceCIDR              =  "service-cluster-ip-range" 
8787	serviceCIDRv6            =  "service-cluster-ip-range-v6" 
88-         	ipFamily                 =  "ip-family" 
88+ 	ipFamily                 =  "ip-family" 
8989	imageRepository          =  "image-repository" 
9090	imageMirrorCountry       =  "image-mirror-country" 
9191	mountString              =  "mount-string" 
@@ -152,8 +152,8 @@ const (
152152	gpus                     =  "gpus" 
153153	autoPauseInterval        =  "auto-pause-interval" 
154154	subnetv6                 =  "subnet-v6" 
155- 	podCIDR    		 =  "pod-cidr" 
156-    	podCIDRv6  		 =  "pod-cidr-v6" 
155+ 	podCIDR                   =  "pod-cidr" 
156+ 	podCIDRv6                 =  "pod-cidr-v6" 
157157)
158158
159159var  (
@@ -296,7 +296,6 @@ func initDriverFlags() {
296296	startCmd .Flags ().String (podCIDR , "" , "IPv4 CIDR to use for pod IPs (bridge CNI)." )
297297	startCmd .Flags ().String (podCIDRv6 , "" , "IPv6 CIDR to use for pod IPs (bridge CNI)." )
298298
299- 
300299	// qemu 
301300	startCmd .Flags ().String (qemuFirmwarePath , "" , "Path to the qemu firmware file. Defaults: For Linux, the default firmware location. For macOS, the brew installation location. For Windows, C:\\ Program Files\\ qemu\\ share" )
302301}
@@ -307,7 +306,7 @@ func initNetworkingFlags() {
307306	startCmd .Flags ().StringSliceVar (& registryMirror , "registry-mirror" , nil , "Registry mirrors to pass to the Docker daemon" )
308307	startCmd .Flags ().String (imageRepository , "" , "Alternative image repository to pull docker images from. This can be used when you have limited access to gcr.io. Set it to \" auto\"  to let minikube decide one for you. For Chinese mainland users, you may use local gcr.io mirrors such as registry.cn-hangzhou.aliyuncs.com/google_containers" )
309308	startCmd .Flags ().String (imageMirrorCountry , "" , "Country code of the image mirror to be used. Leave empty to use the global one. For Chinese mainland users, set it to cn." )
310- 	startCmd .Flags ().String (serviceCIDR ,   constants .DefaultServiceCIDR ,   "The IPv4 CIDR to be used for service cluster IPs." )
309+ 	startCmd .Flags ().String (serviceCIDR , constants .DefaultServiceCIDR , "The IPv4 CIDR to be used for service cluster IPs." )
311310	startCmd .Flags ().String (serviceCIDRv6 , constants .DefaultServiceCIDRv6 , "The IPv6 CIDR to be used for service cluster IPs." )
312311	startCmd .Flags ().String (ipFamily , "ipv4" , "Cluster IP family mode: one of 'ipv4' (default), 'ipv6', or 'dual'." )
313312	startCmd .Flags ().StringArrayVar (& config .DockerEnv , "docker-env" , nil , "Environment variables to pass to the Docker daemon. (format: key=value)" )
@@ -512,99 +511,98 @@ func getNetwork(driverName string) string {
512511
513512// normalizeAndValidateIPFamily sets defaults, validates CIDRs, and guards Desktop vs Linux daemon for v6. 
514513func  normalizeAndValidateIPFamily (cc  * config.ClusterConfig ) {
515-     fam  :=  strings .ToLower (strings .TrimSpace (cc .KubernetesConfig .IPFamily ))
516-     switch  fam  {
517-     case  "" , "ipv4" , "ipv6" , "dual" :
518-         // ok 
519-     default :
520-         exit .Message (reason .Usage , "Invalid --ip-family {{.fam}}. Must be one of: ipv4, ipv6, dual." , out.V {"fam" : cc .KubernetesConfig .IPFamily })
521-     }
522-     if  fam  ==  ""  {
523-         fam  =  "ipv4" 
524-         cc .KubernetesConfig .IPFamily  =  fam 
525-     }
526-     // default v6 CIDRs if needed 
527-     if  fam  !=  "ipv4"  {
528-         if  cc .KubernetesConfig .ServiceCIDRv6  ==  ""  {
529-             cc .KubernetesConfig .ServiceCIDRv6  =  constants .DefaultServiceCIDRv6 
530-         }
531-         if  cc .KubernetesConfig .PodCIDRv6  ==  ""  {
532-             cc .KubernetesConfig .PodCIDRv6  =  constants .DefaultPodCIDRv6 
533-         }
534-     }
535-     // defaults so dual has both sides unless the user overrides 
536-     if  fam  !=  "ipv6"  &&  cc .KubernetesConfig .PodCIDR  ==  ""  {
537-     	cc .KubernetesConfig .PodCIDR  =  cni .DefaultPodCIDR 
538-     }
539- 
540-     if  fam  !=  "ipv4"  &&  cc .KubernetesConfig .PodCIDRv6  ==  ""  {
541-         cc .KubernetesConfig .PodCIDRv6  =  constants .DefaultPodCIDRv6 
542-     }
543- 
544-     // basic CIDR sanity 
545-     if  cidr  :=  cc .Subnetv6 ; cidr  !=  ""  {
546-         if  _ , _ , err  :=  net .ParseCIDR (cidr ); err  !=  nil  {
547-             exit .Message (reason .Usage , "--subnet-v6 must be a valid IPv6 CIDR: {{.e}}" , out.V {"e" : err })
548-         }
549-     }
550-     if  cidr  :=  cc .KubernetesConfig .ServiceCIDRv6 ; cidr  !=  ""  {
551-         if  _ , _ , err  :=  net .ParseCIDR (cidr ); err  !=  nil  {
552-             exit .Message (reason .Usage , "--service-cluster-ip-range-v6 must be a valid IPv6 CIDR: {{.e}}" , out.V {"e" : err })
553-         }
554-     }
555-     if  cidr  :=  cc .KubernetesConfig .PodCIDRv6 ; cidr  !=  ""  {
556-         if  _ , _ , err  :=  net .ParseCIDR (cidr ); err  !=  nil  {
557-             exit .Message (reason .Usage , "PodCIDRv6 must be a valid IPv6 CIDR: {{.e}}" , out.V {"e" : err })
558-         }
559-     }
560- 
561-     if  s  :=  cc .KubernetesConfig .PodCIDR ; s  !=  ""  {
562-     	if  _ , _ , err  :=  net .ParseCIDR (s ); err  !=  nil  {
563-         	exit .Message (reason .Usage , "--pod-cidr must be a valid IPv4 CIDR: {{.e}}" , out.V {"e" : err })
564-     	}
565-     }
566- 
567-     if  s  :=  cc .KubernetesConfig .PodCIDRv6 ; s  !=  ""  {
568-         if  _ , _ , err  :=  net .ParseCIDR (s ); err  !=  nil  {
569-                 exit .Message (reason .Usage , "--pod-cidr-v6 must be a valid IPv6 CIDR: {{.e}}" , out.V {"e" : err })
570-         }
571-     }
572- 
573-     // validate static IPv6 if provided 
574-     if  s  :=  cc .StaticIPv6 ; s  !=  ""  {
575-         ip  :=  net .ParseIP (s )
576-         if  ip  ==  nil  ||  ip .To4 () !=  nil  {
577-             exit .Message (reason .Usage , "--static-ipv6 must be a valid IPv6 address" )
578-         }
579-     }
580- 
581- 
582-     // Docker driver guardrails: Linux daemon + IPv6 must be enabled 
583-     if  driver .IsDocker (cc .Driver ) &&  fam  !=  "ipv4"  {
584- 	// Desktop vs Linux daemon hint (we can't reliably detect IPv6 enabled here) 
585-         si , err  :=  oci .CachedDaemonInfo (cc .Driver )
586-         if  err  !=  nil  {
587-             si , err  =  oci .DaemonInfo (cc .Driver )
588-             if  err  !=  nil  {
589-                 exit .Message (reason .Usage , "Failed to query Docker daemon info: {{.e}}" , out.V {"e" : err })
590-             }
591-         }
592-         // On non-Linux hosts we assume Docker Desktop; on Linux it's a native Engine 
593-         // unless DockerOS explicitly says "Docker Desktop". 
594-         isLinuxDaemon  :=  runtime .GOOS  ==  "linux"  &&  si .DockerOS  !=  "Docker Desktop" 
595-         if  ! isLinuxDaemon  {
596-             if  fam  ==  "ipv6"  {
597-                 exit .Message (reason .Usage ,
598-                     "IPv6 clusters require a Linux Docker daemon (Desktop is not supported). " + 
599-                     "Use a Linux/WSL2 daemon or set --ip-family=ipv4." )
600-             }
601-             out .WarningT ("Dual-stack on Docker Desktop may be limited. For full IPv6 support, use a Linux Docker daemon." )
602-         }
603- 
604-         // Friendly reminder about enabling daemon IPv6 (actual failure will occur during network create otherwise) 
605-         out .Styled (style .Tip ,
606-             "If Docker daemon IPv6 is disabled, enable it in /etc/docker/daemon.json and restart:\n   {\" ipv6\" : true, \" fixed-cidr-v6\" : \" fd00:55:66::/64\" }" )
607-     }
514+ 	fam  :=  strings .ToLower (strings .TrimSpace (cc .KubernetesConfig .IPFamily ))
515+ 	switch  fam  {
516+ 	case  "" , "ipv4" , "ipv6" , "dual" :
517+ 		// ok 
518+ 	default :
519+ 		exit .Message (reason .Usage , "Invalid --ip-family {{.fam}}. Must be one of: ipv4, ipv6, dual." , out.V {"fam" : cc .KubernetesConfig .IPFamily })
520+ 	}
521+ 	if  fam  ==  ""  {
522+ 		fam  =  "ipv4" 
523+ 		cc .KubernetesConfig .IPFamily  =  fam 
524+ 	}
525+ 	// default v6 CIDRs if needed 
526+ 	if  fam  !=  "ipv4"  {
527+ 		if  cc .KubernetesConfig .ServiceCIDRv6  ==  ""  {
528+ 			cc .KubernetesConfig .ServiceCIDRv6  =  constants .DefaultServiceCIDRv6 
529+ 		}
530+ 		if  cc .KubernetesConfig .PodCIDRv6  ==  ""  {
531+ 			cc .KubernetesConfig .PodCIDRv6  =  constants .DefaultPodCIDRv6 
532+ 		}
533+ 	}
534+ 	// defaults so dual has both sides unless the user overrides 
535+ 	if  fam  !=  "ipv6"  &&  cc .KubernetesConfig .PodCIDR  ==  ""  {
536+ 		cc .KubernetesConfig .PodCIDR  =  cni .DefaultPodCIDR 
537+ 	}
538+ 
539+ 	if  fam  !=  "ipv4"  &&  cc .KubernetesConfig .PodCIDRv6  ==  ""  {
540+ 		cc .KubernetesConfig .PodCIDRv6  =  constants .DefaultPodCIDRv6 
541+ 	}
542+ 
543+ 	// basic CIDR sanity 
544+ 	if  cidr  :=  cc .Subnetv6 ; cidr  !=  ""  {
545+ 		if  _ , _ , err  :=  net .ParseCIDR (cidr ); err  !=  nil  {
546+ 			exit .Message (reason .Usage , "--subnet-v6 must be a valid IPv6 CIDR: {{.e}}" , out.V {"e" : err })
547+ 		}
548+ 	}
549+ 	if  cidr  :=  cc .KubernetesConfig .ServiceCIDRv6 ; cidr  !=  ""  {
550+ 		if  _ , _ , err  :=  net .ParseCIDR (cidr ); err  !=  nil  {
551+ 			exit .Message (reason .Usage , "--service-cluster-ip-range-v6 must be a valid IPv6 CIDR: {{.e}}" , out.V {"e" : err })
552+ 		}
553+ 	}
554+ 	if  cidr  :=  cc .KubernetesConfig .PodCIDRv6 ; cidr  !=  ""  {
555+ 		if  _ , _ , err  :=  net .ParseCIDR (cidr ); err  !=  nil  {
556+ 			exit .Message (reason .Usage , "PodCIDRv6 must be a valid IPv6 CIDR: {{.e}}" , out.V {"e" : err })
557+ 		}
558+ 	}
559+ 
560+ 	if  s  :=  cc .KubernetesConfig .PodCIDR ; s  !=  ""  {
561+ 		if  _ , _ , err  :=  net .ParseCIDR (s ); err  !=  nil  {
562+ 			exit .Message (reason .Usage , "--pod-cidr must be a valid IPv4 CIDR: {{.e}}" , out.V {"e" : err })
563+ 		}
564+ 	}
565+ 
566+ 	if  s  :=  cc .KubernetesConfig .PodCIDRv6 ; s  !=  ""  {
567+ 		if  _ , _ , err  :=  net .ParseCIDR (s ); err  !=  nil  {
568+ 			exit .Message (reason .Usage , "--pod-cidr-v6 must be a valid IPv6 CIDR: {{.e}}" , out.V {"e" : err })
569+ 		}
570+ 	}
571+ 
572+ 	// validate static IPv6 if provided 
573+ 	if  s  :=  cc .StaticIPv6 ; s  !=  ""  {
574+ 		ip  :=  net .ParseIP (s )
575+ 		if  ip  ==  nil  ||  ip .To4 () !=  nil  {
576+ 			exit .Message (reason .Usage , "--static-ipv6 must be a valid IPv6 address" )
577+ 		}
578+ 	}
579+ 
580+ 	// Docker driver guardrails: Linux daemon + IPv6 must be enabled 
581+ 	if  driver .IsDocker (cc .Driver ) &&  fam  !=  "ipv4"  {
582+ 		// Desktop vs Linux daemon hint (we can't reliably detect IPv6 enabled here) 
583+ 		si , err  :=  oci .CachedDaemonInfo (cc .Driver )
584+ 		if  err  !=  nil  {
585+ 			si , err  =  oci .DaemonInfo (cc .Driver )
586+ 			if  err  !=  nil  {
587+ 				exit .Message (reason .Usage , "Failed to query Docker daemon info: {{.e}}" , out.V {"e" : err })
588+ 			}
589+ 		}
590+ 		// On non-Linux hosts we assume Docker Desktop; on Linux it's a native Engine 
591+ 		// unless DockerOS explicitly says "Docker Desktop". 
592+ 		isLinuxDaemon  :=  runtime .GOOS  ==  "linux"  &&  si .DockerOS  !=  "Docker Desktop" 
593+ 		if  ! isLinuxDaemon  {
594+ 			if  fam  ==  "ipv6"  {
595+ 				exit .Message (reason .Usage ,
596+ 					"IPv6 clusters require a Linux Docker daemon (Desktop is not supported). " + 
597+ 						"Use a Linux/WSL2 daemon or set --ip-family=ipv4." )
598+ 			}
599+ 			out .WarningT ("Dual-stack on Docker Desktop may be limited. For full IPv6 support, use a Linux Docker daemon." )
600+ 		}
601+ 
602+ 		// Friendly reminder about enabling daemon IPv6 (actual failure will occur during network create otherwise) 
603+ 		out .Styled (style .Tip ,
604+ 			"If Docker daemon IPv6 is disabled, enable it in /etc/docker/daemon.json and restart:\n   {\" ipv6\" : true, \" fixed-cidr-v6\" : \" fd00:55:66::/64\" }" )
605+ 	}
608606}
609607
610608func  validateQemuNetwork (n  string ) string  {
@@ -761,8 +759,8 @@ func generateNewConfigFromFlags(cmd *cobra.Command, k8sVersion string, rtime str
761759			NetworkPlugin :          chosenNetworkPlugin ,
762760			ServiceCIDR :            viper .GetString (serviceCIDR ),
763761			ServiceCIDRv6 :          viper .GetString (serviceCIDRv6 ),
764- 			PodCIDR :   		 viper .GetString (podCIDR ),
765- 			PodCIDRv6 : 		 viper .GetString (podCIDRv6 ),
762+ 			PodCIDR :                 viper .GetString (podCIDR ),
763+ 			PodCIDRv6 :               viper .GetString (podCIDRv6 ),
766764			IPFamily :               viper .GetString (ipFamily ),
767765			ImageRepository :        getRepository (cmd , k8sVersion ),
768766			ExtraOptions :           getExtraOptions (),
@@ -960,7 +958,7 @@ func updateExistingConfigFromFlags(cmd *cobra.Command, existing *config.ClusterC
960958	updateStringSliceFromFlag (cmd , & cc .HyperkitVSockPorts , vsockPorts )
961959	updateStringSliceFromFlag (cmd , & cc .NFSShare , nfsShare )
962960	updateStringFromFlag (cmd , & cc .NFSSharesRoot , nfsSharesRoot )
963- 	updateStringFromFlag (cmd , & cc .HostOnlyCIDR ,   hostOnlyCIDR )
961+ 	updateStringFromFlag (cmd , & cc .HostOnlyCIDR , hostOnlyCIDR )
964962	updateStringFromFlag (cmd , & cc .HostOnlyCIDRv6 , hostOnlyCIDRv6 )
965963	updateStringFromFlag (cmd , & cc .HypervVirtualSwitch , hypervVirtualSwitch )
966964	updateBoolFromFlag (cmd , & cc .HypervUseExternalSwitch , hypervUseExternalSwitch )
@@ -979,7 +977,7 @@ func updateExistingConfigFromFlags(cmd *cobra.Command, existing *config.ClusterC
979977	updateDurationFromFlag (cmd , & cc .StartHostTimeout , waitTimeout )
980978	updateStringSliceFromFlag (cmd , & cc .ExposedPorts , ports )
981979	updateStringFromFlag (cmd , & cc .SSHIPAddress , sshIPAddress )
982- 	updateStringFromFlag (cmd , & cc .StaticIPv6 ,    staticIPv6 )
980+ 	updateStringFromFlag (cmd , & cc .StaticIPv6 , staticIPv6 )
983981	updateStringFromFlag (cmd , & cc .SSHUser , sshSSHUser )
984982	updateStringFromFlag (cmd , & cc .SSHKey , sshSSHKey )
985983	updateIntFromFlag (cmd , & cc .SSHPort , sshSSHPort )
@@ -991,9 +989,9 @@ func updateExistingConfigFromFlags(cmd *cobra.Command, existing *config.ClusterC
991989	updateStringFromFlag (cmd , & cc .KubernetesConfig .ContainerRuntime , containerRuntime )
992990	updateStringFromFlag (cmd , & cc .KubernetesConfig .CRISocket , criSocket )
993991	updateStringFromFlag (cmd , & cc .KubernetesConfig .NetworkPlugin , networkPlugin )
994- 	updateStringFromFlag (cmd , & cc .KubernetesConfig .ServiceCIDR ,   serviceCIDR )
995-          updateStringFromFlag (cmd , & cc .KubernetesConfig .ServiceCIDRv6 , serviceCIDRv6 )
996-          updateStringFromFlag (cmd , & cc .KubernetesConfig .IPFamily ,      ipFamily )
992+ 	updateStringFromFlag (cmd , & cc .KubernetesConfig .ServiceCIDR , serviceCIDR )
993+ 	 updateStringFromFlag (cmd , & cc .KubernetesConfig .ServiceCIDRv6 , serviceCIDRv6 )
994+ 	 updateStringFromFlag (cmd , & cc .KubernetesConfig .IPFamily , ipFamily )
997995	updateBoolFromFlag (cmd , & cc .KubernetesConfig .ShouldLoadCachedImages , cacheImages )
998996	updateDurationFromFlag (cmd , & cc .CertExpiration , certExpiration )
999997	updateStringFromFlag (cmd , & cc .MountString , mountString )
0 commit comments