func Cluster(logger log.Logger, p providers.Provider, opts *ClusterOptions) error {
	if err := validateProvider(p); err != nil {
		return err
	}
	if err := fixupOptions(opts); err != nil {
		return err
	}
	if err := alreadyExists(p, opts.Config.Name); err != nil {
		return err
	}
	if len(opts.Config.Name) > clusterNameMax {
		logger.Warnf("cluster name %q is probably too long, this might not work properly on some systems", opts.Config.Name)
	}
	if err := opts.Config.Validate(); err != nil {
		return err
	}
	status := cli.StatusForLogger(logger)
	logger.V(0).Infof("Creating cluster %q ...\n", opts.Config.Name)
	if err := p.Provision(status, opts.Config); err != nil {
		if !opts.Retain {
			_ = delete.Cluster(logger, p, opts.Config.Name, opts.KubeconfigPath)
		}
		return err
	}
	actionsToRun := []actions.Action{
		loadbalancer.NewAction(),  
		configaction.NewAction(),  
	}
	if !opts.StopBeforeSettingUpKubernetes {
		actionsToRun = append(actionsToRun,
			kubeadminit.NewAction(opts.Config),  
		)
		if !opts.Config.Networking.DisableDefaultCNI {
			actionsToRun = append(actionsToRun,
				installcni.NewAction(),  
			)
		}
		actionsToRun = append(actionsToRun,
			installstorage.NewAction(),                 
			kubeadmjoin.NewAction(),                    
			waitforready.NewAction(opts.WaitForReady),  
		)
	}
	actionsContext := actions.NewActionContext(logger, status, p, opts.Config)
	for _, action := range actionsToRun {
		if err := action.Execute(actionsContext); err != nil {
			if !opts.Retain {
				_ = delete.Cluster(logger, p, opts.Config.Name, opts.KubeconfigPath)
			}
			return err
		}
	}
	if opts.StopBeforeSettingUpKubernetes {
		return nil
	}
	var err error
	for _, b := range []time.Duration{0, time.Millisecond, time.Millisecond * 50, time.Millisecond * 100} {
		time.Sleep(b)
		if err = kubeconfig.Export(p, opts.Config.Name, opts.KubeconfigPath); err == nil {
			break
		}
	}
	if err != nil {
		return err
	}
	if opts.DisplayUsage {
		logUsage(logger, opts.Config.Name, opts.KubeconfigPath)
	}
	if opts.DisplaySalutation {
		logger.V(0).Info("")
		logSalutation(logger)
	}
	return nil
}
Cluster creates a cluster
package create
import (
	"fmt"
	"math/rand"
	"time"
	"github.com/alessio/shellescape"
	"sigs.k8s.io/kind/pkg/cluster/internal/delete"
	"sigs.k8s.io/kind/pkg/cluster/internal/providers"
	"sigs.k8s.io/kind/pkg/errors"
	"sigs.k8s.io/kind/pkg/internal/apis/config"
	"sigs.k8s.io/kind/pkg/internal/apis/config/encoding"
	"sigs.k8s.io/kind/pkg/internal/cli"
	"sigs.k8s.io/kind/pkg/log"
	"sigs.k8s.io/kind/pkg/cluster/internal/create/actions"
	configaction "sigs.k8s.io/kind/pkg/cluster/internal/create/actions/config"
	"sigs.k8s.io/kind/pkg/cluster/internal/create/actions/installcni"
	"sigs.k8s.io/kind/pkg/cluster/internal/create/actions/installstorage"
	"sigs.k8s.io/kind/pkg/cluster/internal/create/actions/kubeadminit"
	"sigs.k8s.io/kind/pkg/cluster/internal/create/actions/kubeadmjoin"
	"sigs.k8s.io/kind/pkg/cluster/internal/create/actions/loadbalancer"
	"sigs.k8s.io/kind/pkg/cluster/internal/create/actions/waitforready"
	"sigs.k8s.io/kind/pkg/cluster/internal/kubeconfig"
)
const (
	clusterNameMax = 50
)
type ClusterOptions struct {
	Config       *config.Cluster
	NameOverride string  
	NodeImage      string
	Retain         bool
	WaitForReady   time.Duration
	KubeconfigPath string
	StopBeforeSettingUpKubernetes bool  
	DisplayUsage      bool
	DisplaySalutation bool
}