func()

in pkg/drivers/kic/kic.go [75:205]


func (d *Driver) Create() error {
	ctx := context.Background()
	params := oci.CreateParams{
		Mounts:        d.NodeConfig.Mounts,
		Name:          d.NodeConfig.MachineName,
		Image:         d.NodeConfig.ImageDigest,
		ClusterLabel:  oci.ProfileLabelKey + "=" + d.MachineName,
		NodeLabel:     oci.NodeLabelKey + "=" + d.NodeConfig.MachineName,
		CPUs:          strconv.Itoa(d.NodeConfig.CPU),
		Memory:        strconv.Itoa(d.NodeConfig.Memory) + "mb",
		Envs:          d.NodeConfig.Envs,
		ExtraArgs:     append([]string{"--expose", fmt.Sprintf("%d", d.NodeConfig.APIServerPort)}, d.NodeConfig.ExtraArgs...),
		OCIBinary:     d.NodeConfig.OCIBinary,
		APIServerPort: d.NodeConfig.APIServerPort,
	}

	networkName := d.NodeConfig.Network
	if networkName == "" {
		networkName = d.NodeConfig.ClusterName
	}
	if gateway, err := oci.CreateNetwork(d.OCIBinary, networkName); err != nil {
		out.WarningT("Unable to create dedicated network, this might result in cluster IP change after restart: {{.error}}", out.V{"error": err})
	} else if gateway != nil {
		params.Network = networkName
		ip := gateway.To4()
		// calculate the container IP based on guessing the machine index
		index := driver.IndexFromMachineName(d.NodeConfig.MachineName)
		if int(ip[3])+index > 255 {
			return fmt.Errorf("too many machines to calculate an IP")
		}
		ip[3] += byte(index)
		klog.Infof("calculated static IP %q for the %q container", ip.String(), d.NodeConfig.MachineName)
		params.IP = ip.String()
	}
	drv := d.DriverName()

	listAddr := oci.DefaultBindIPV4
	if d.NodeConfig.ListenAddress != "" && d.NodeConfig.ListenAddress != listAddr {
		out.Step(style.Tip, "minikube is not meant for production use. You are opening non-local traffic")
		out.WarningT("Listening to {{.listenAddr}}. This is not recommended and can cause a security vulnerability. Use at your own risk",
			out.V{"listenAddr": d.NodeConfig.ListenAddress})
		listAddr = d.NodeConfig.ListenAddress
	} else if oci.IsExternalDaemonHost(drv) {
		out.WarningT("Listening to 0.0.0.0 on external docker host {{.host}}. Please be advised",
			out.V{"host": oci.DaemonHost(drv)})
		listAddr = "0.0.0.0"
	}

	// control plane specific options
	params.PortMappings = append(params.PortMappings,
		oci.PortMapping{
			ListenAddress: listAddr,
			ContainerPort: int32(params.APIServerPort),
		},
		oci.PortMapping{
			ListenAddress: listAddr,
			ContainerPort: constants.SSHPort,
		},
		oci.PortMapping{
			ListenAddress: listAddr,
			ContainerPort: constants.DockerDaemonPort,
		},
		oci.PortMapping{
			ListenAddress: listAddr,
			ContainerPort: constants.RegistryAddonPort,
		},
		oci.PortMapping{
			ListenAddress: listAddr,
			ContainerPort: constants.AutoPauseProxyPort,
		},
	)

	exists, err := oci.ContainerExists(d.OCIBinary, params.Name, true)
	if err != nil {
		klog.Warningf("failed to check if container already exists: %v", err)
	}
	if exists {
		// if container was created by minikube it is safe to delete and recreate it.
		if oci.IsCreatedByMinikube(d.OCIBinary, params.Name) {
			klog.Info("Found already existing abandoned minikube container, will try to delete.")
			if err := oci.DeleteContainer(ctx, d.OCIBinary, params.Name); err != nil {
				klog.Errorf("Failed to delete a conflicting minikube container %s. You might need to restart your %s daemon and delete it manually and try again: %v", params.Name, params.OCIBinary, err)
			}
		} else {
			// The conflicting container name was not created by minikube
			// user has a container that conflicts with minikube profile name, will not delete users container.
			return errors.Wrapf(err, "user has a conflicting container name %q with minikube container. Needs to be deleted by user's consent", params.Name)
		}
	}

	if err := oci.PrepareContainerNode(params); err != nil {
		return errors.Wrap(err, "setting up container node")
	}

	var waitForPreload sync.WaitGroup
	waitForPreload.Add(1)
	var pErr error
	go func() {
		defer waitForPreload.Done()
		// If preload doesn't exist, don't bother extracting tarball to volume
		if !download.PreloadExists(d.NodeConfig.KubernetesVersion, d.NodeConfig.ContainerRuntime, d.DriverName()) {
			return
		}
		t := time.Now()
		klog.Infof("Starting extracting preloaded images to volume ...")
		// Extract preloaded images to container
		if err := oci.ExtractTarballToVolume(d.NodeConfig.OCIBinary, download.TarballPath(d.NodeConfig.KubernetesVersion, d.NodeConfig.ContainerRuntime), params.Name, d.NodeConfig.ImageDigest); err != nil {
			if strings.Contains(err.Error(), "No space left on device") {
				pErr = oci.ErrInsufficientDockerStorage
				return
			}
			klog.Infof("Unable to extract preloaded tarball to volume: %v", err)
		} else {
			klog.Infof("duration metric: took %f seconds to extract preloaded images to volume", time.Since(t).Seconds())
		}
	}()
	waitForPreload.Wait()
	if pErr == oci.ErrInsufficientDockerStorage {
		return pErr
	}

	if err := oci.CreateContainerNode(params); err != nil {
		return errors.Wrap(err, "create kic node")
	}

	if err := d.prepareSSH(); err != nil {
		return errors.Wrap(err, "prepare kic ssh")
	}

	return nil
}