code: func (w *KubeWaiter) WaitForKubeletAndFunc(f func() error) error {
  	errorChan := make(chan error)
  
  	go func(errC chan error, waiter Waiter) {
  		if err := waiter.WaitForHealthyKubelet(40*time.Second, fmt.Sprintf("http://localhost:%d/healthz", kubeadmconstants.KubeletHealthzPort)); err != nil {
  			errC <- err
  		}
  	}(errorChan, w)
  
  	go func(errC chan error, waiter Waiter) {
  		// This main goroutine sends whatever the f function returns (error or not) to the channel
  		// This in order to continue on success (nil error), or just fail if the function returns an error
  		errC <- f()
  	}(errorChan, w)
  
  	// This call is blocking until one of the goroutines sends to errorChan
  	return <-errorChan
  }
docs: // WaitForKubeletAndFunc waits primarily for the function f to execute, even though it might take some time. If that takes a long time, and the kubelet
  // /healthz continuously are unhealthy, kubeadm will error out after a period of exponential backoff