diff --git a/cmd/vcluster/cmd/start.go b/cmd/vcluster/cmd/start.go index 9919464959..36137e62fb 100644 --- a/cmd/vcluster/cmd/start.go +++ b/cmd/vcluster/cmd/start.go @@ -10,7 +10,9 @@ import ( "github.com/loft-sh/vcluster/pkg/setup" "github.com/loft-sh/vcluster/pkg/setup/options" "github.com/loft-sh/vcluster/pkg/telemetry" + "github.com/loft-sh/vcluster/pkg/util/blockingcacheclient" "github.com/loft-sh/vcluster/pkg/util/clienthelper" + "github.com/loft-sh/vcluster/pkg/util/pluginhookclient" "github.com/loft-sh/vcluster/pkg/util/translate" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -103,6 +105,8 @@ func ExecuteStart(ctx context.Context, options *options.VirtualClusterOptions) e currentNamespace, inClusterConfig, scheme.Scheme, + pluginhookclient.NewPhysicalPluginClientFactory(blockingcacheclient.NewCacheClient), + pluginhookclient.NewVirtualPluginClientFactory(blockingcacheclient.NewCacheClient), ) if err != nil { return err diff --git a/pkg/plugin/plugin.go b/pkg/plugin/plugin.go index b07f0c30ec..34de609ed6 100644 --- a/pkg/plugin/plugin.go +++ b/pkg/plugin/plugin.go @@ -41,7 +41,7 @@ func (m *manager) Start( return fmt.Errorf("start legacy plugins: %w", err) } - err = m.pluginManager.Start(ctx, currentNamespace, targetNamespace, virtualKubeConfig, physicalKubeConfig, syncerConfig, options) + err = m.pluginManager.Start(ctx, currentNamespace, physicalKubeConfig, syncerConfig, options) if err != nil { return fmt.Errorf("start plugins: %w", err) } diff --git a/pkg/plugin/v2/config.go b/pkg/plugin/v2/config.go index f67d962073..f5430b4a71 100644 --- a/pkg/plugin/v2/config.go +++ b/pkg/plugin/v2/config.go @@ -4,10 +4,8 @@ import "encoding/json" // InitConfig is the config the syncer sends to the plugin type InitConfig struct { - VirtualClusterConfig []byte `json:"virtualClusterConfig,omitempty"` PhysicalClusterConfig []byte `json:"physicalClusterConfig,omitempty"` SyncerConfig []byte `json:"syncerConfig,omitempty"` - TargetNamespace string `json:"targetNamespace,omitempty"` CurrentNamespace string `json:"currentNamespace,omitempty"` Options []byte `json:"options,omitempty"` WorkingDir string `json:"workingDir,omitempty"` diff --git a/pkg/plugin/v2/plugin.go b/pkg/plugin/v2/plugin.go index 2900c86fa7..6fb7d3579b 100644 --- a/pkg/plugin/v2/plugin.go +++ b/pkg/plugin/v2/plugin.go @@ -64,8 +64,7 @@ type vClusterPlugin struct { func (m *Manager) Start( ctx context.Context, - currentNamespace, targetNamespace string, - virtualKubeConfig *rest.Config, + currentNamespace string, physicalKubeConfig *rest.Config, syncerConfig *clientcmdapi.Config, options *options.VirtualClusterOptions, @@ -89,7 +88,7 @@ func (m *Manager) Start( // after loading all plugins we start them for _, vClusterPlugin := range m.Plugins { // build the start request - initRequest, err := m.buildInitRequest(filepath.Dir(vClusterPlugin.Path), currentNamespace, targetNamespace, virtualKubeConfig, physicalKubeConfig, syncerConfig, options) + initRequest, err := m.buildInitRequest(filepath.Dir(vClusterPlugin.Path), currentNamespace, physicalKubeConfig, syncerConfig, options) if err != nil { return fmt.Errorf("build start request: %w", err) } @@ -233,9 +232,7 @@ func (m *Manager) registerClientHooks(vClusterPlugin *vClusterPlugin, clientHook func (m *Manager) buildInitRequest( workingDir, - currentNamespace, - targetNamespace string, - virtualKubeConfig *rest.Config, + currentNamespace string, physicalKubeConfig *rest.Config, syncerConfig *clientcmdapi.Config, options *options.VirtualClusterOptions, @@ -246,20 +243,6 @@ func (m *Manager) buildInitRequest( return nil, fmt.Errorf("marshal options: %w", err) } - // Virtual client config - convertedVirtualConfig, err := kubeconfig.ConvertRestConfigToClientConfig(virtualKubeConfig) - if err != nil { - return nil, fmt.Errorf("convert virtual client config: %w", err) - } - rawVirtualConfig, err := convertedVirtualConfig.RawConfig() - if err != nil { - return nil, fmt.Errorf("convert virtual client config: %w", err) - } - virtualConfigBytes, err := clientcmd.Write(rawVirtualConfig) - if err != nil { - return nil, fmt.Errorf("marshal virtual client config: %w", err) - } - // Physical client config convertedPhysicalConfig, err := kubeconfig.ConvertRestConfigToClientConfig(physicalKubeConfig) if err != nil { @@ -282,10 +265,8 @@ func (m *Manager) buildInitRequest( // marshal init config initConfig, err := json.Marshal(&InitConfig{ - VirtualClusterConfig: virtualConfigBytes, PhysicalClusterConfig: phyisicalConfigBytes, SyncerConfig: syncerConfigBytes, - TargetNamespace: targetNamespace, CurrentNamespace: currentNamespace, Options: encodedOptions, WorkingDir: workingDir, diff --git a/pkg/setup/controller_context.go b/pkg/setup/controller_context.go index 72c37e38e6..429858be96 100644 --- a/pkg/setup/controller_context.go +++ b/pkg/setup/controller_context.go @@ -11,8 +11,6 @@ import ( "github.com/loft-sh/vcluster/pkg/setup/options" "github.com/loft-sh/vcluster/pkg/telemetry" "github.com/loft-sh/vcluster/pkg/util/blockingcacheclient" - "github.com/loft-sh/vcluster/pkg/util/kubeconfig" - "github.com/loft-sh/vcluster/pkg/util/pluginhookclient" "github.com/loft-sh/vcluster/pkg/util/toleration" "github.com/loft-sh/vcluster/pkg/util/translate" "github.com/pkg/errors" @@ -44,6 +42,8 @@ func NewControllerContext( currentNamespace string, inClusterConfig *rest.Config, scheme *runtime.Scheme, + newPhysicalClient client.NewClientFunc, + newVirtualClient client.NewClientFunc, ) (*options.ControllerContext, error) { // validate options err := ValidateOptions(options) @@ -51,22 +51,16 @@ func NewControllerContext( return nil, err } - // init managers - localManager, virtualClusterManager, virtualRawConfig, err := InitManagers( + // create controller context + return InitManagers( ctx, options, currentNamespace, inClusterConfig, scheme, - pluginhookclient.NewPhysicalPluginClientFactory(blockingcacheclient.NewCacheClient), - pluginhookclient.NewVirtualPluginClientFactory(blockingcacheclient.NewCacheClient), + newPhysicalClient, + newVirtualClient, ) - if err != nil { - return nil, err - } - - // create controller context - return InitControllerContext(ctx, currentNamespace, localManager, virtualClusterManager, virtualRawConfig, options) } func InitManagers( @@ -77,11 +71,11 @@ func InitManagers( scheme *runtime.Scheme, newPhysicalClient client.NewClientFunc, newVirtualClient client.NewClientFunc, -) (ctrl.Manager, ctrl.Manager, *clientcmdapi.Config, error) { +) (*options.ControllerContext, error) { // load virtual config virtualConfig, virtualRawConfig, err := LoadVirtualConfig(ctx, options) if err != nil { - return nil, nil, nil, err + return nil, err } // is multi namespace mode? @@ -102,7 +96,7 @@ func InitManagers( // start plugins err = StartPlugins(ctx, currentNamespace, inClusterConfig, virtualConfig, virtualRawConfig, options) if err != nil { - return nil, nil, nil, err + return nil, err } // create physical manager @@ -115,7 +109,7 @@ func InitManagers( NewClient: newPhysicalClient, }) if err != nil { - return nil, nil, nil, err + return nil, err } // create virtual manager @@ -126,10 +120,11 @@ func InitManagers( NewClient: newVirtualClient, }) if err != nil { - return nil, nil, nil, err + return nil, err } - return localManager, virtualClusterManager, virtualRawConfig, nil + // init controller context + return InitControllerContext(ctx, currentNamespace, localManager, virtualClusterManager, virtualRawConfig, options) } func StartPlugins( @@ -140,6 +135,7 @@ func StartPlugins( virtualRawConfig *clientcmdapi.Config, options *options.VirtualClusterOptions, ) error { + // start plugins only if they are not disabled if !options.DisablePlugins { klog.Infof("Start Plugins Manager...") syncerConfig, err := CreateVClusterKubeConfig(virtualRawConfig, options) @@ -309,64 +305,6 @@ func CreateVClusterKubeConfig(config *clientcmdapi.Config, options *options.Virt return config, nil } -func WriteKubeConfigToSecret(ctx context.Context, currentNamespace string, currentNamespaceClient client.Client, options *options.VirtualClusterOptions, config *clientcmdapi.Config, isRemote bool) error { - config, err := CreateVClusterKubeConfig(config, options) - if err != nil { - return err - } - - if options.KubeConfigContextName != "" { - config.CurrentContext = options.KubeConfigContextName - // update authInfo - for k := range config.AuthInfos { - config.AuthInfos[options.KubeConfigContextName] = config.AuthInfos[k] - if k != options.KubeConfigContextName { - delete(config.AuthInfos, k) - } - break - } - - // update cluster - for k := range config.Clusters { - config.Clusters[options.KubeConfigContextName] = config.Clusters[k] - if k != options.KubeConfigContextName { - delete(config.Clusters, k) - } - break - } - - // update context - for k := range config.Contexts { - tmpCtx := config.Contexts[k] - tmpCtx.Cluster = options.KubeConfigContextName - tmpCtx.AuthInfo = options.KubeConfigContextName - config.Contexts[options.KubeConfigContextName] = tmpCtx - if k != options.KubeConfigContextName { - delete(config.Contexts, k) - } - break - } - } - - // check if we need to write the kubeconfig secrete to the default location as well - if options.KubeConfigSecret != "" { - // which namespace should we create the additional secret in? - secretNamespace := options.KubeConfigSecretNamespace - if secretNamespace == "" { - secretNamespace = currentNamespace - } - - // write the extra secret - err = kubeconfig.WriteKubeConfig(ctx, currentNamespaceClient, options.KubeConfigSecret, secretNamespace, config, isRemote) - if err != nil { - return fmt.Errorf("creating %s secret in the %s ns failed: %w", options.KubeConfigSecret, secretNamespace, err) - } - } - - // write the default Secret - return kubeconfig.WriteKubeConfig(ctx, currentNamespaceClient, kubeconfig.GetDefaultSecretName(translate.VClusterName), currentNamespace, config, isRemote) -} - func InitControllerContext( ctx context.Context, currentNamespace string, diff --git a/pkg/setup/controllers.go b/pkg/setup/controllers.go index 8c08298cd7..4bb9684893 100644 --- a/pkg/setup/controllers.go +++ b/pkg/setup/controllers.go @@ -15,6 +15,7 @@ import ( "github.com/loft-sh/vcluster/pkg/setup/options" "github.com/loft-sh/vcluster/pkg/specialservices" syncertypes "github.com/loft-sh/vcluster/pkg/types" + "github.com/loft-sh/vcluster/pkg/util/kubeconfig" "github.com/loft-sh/vcluster/pkg/util/loghelper" "github.com/loft-sh/vcluster/pkg/util/translate" "github.com/pkg/errors" @@ -22,6 +23,7 @@ import ( kerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -203,3 +205,61 @@ func RegisterOrDeregisterAPIService(ctx *options.ControllerContext) { klog.Errorf("Error registering metrics apiservice: %v", err) } } + +func WriteKubeConfigToSecret(ctx context.Context, currentNamespace string, currentNamespaceClient client.Client, options *options.VirtualClusterOptions, config *clientcmdapi.Config, isRemote bool) error { + config, err := CreateVClusterKubeConfig(config, options) + if err != nil { + return err + } + + if options.KubeConfigContextName != "" { + config.CurrentContext = options.KubeConfigContextName + // update authInfo + for k := range config.AuthInfos { + config.AuthInfos[options.KubeConfigContextName] = config.AuthInfos[k] + if k != options.KubeConfigContextName { + delete(config.AuthInfos, k) + } + break + } + + // update cluster + for k := range config.Clusters { + config.Clusters[options.KubeConfigContextName] = config.Clusters[k] + if k != options.KubeConfigContextName { + delete(config.Clusters, k) + } + break + } + + // update context + for k := range config.Contexts { + tmpCtx := config.Contexts[k] + tmpCtx.Cluster = options.KubeConfigContextName + tmpCtx.AuthInfo = options.KubeConfigContextName + config.Contexts[options.KubeConfigContextName] = tmpCtx + if k != options.KubeConfigContextName { + delete(config.Contexts, k) + } + break + } + } + + // check if we need to write the kubeconfig secrete to the default location as well + if options.KubeConfigSecret != "" { + // which namespace should we create the additional secret in? + secretNamespace := options.KubeConfigSecretNamespace + if secretNamespace == "" { + secretNamespace = currentNamespace + } + + // write the extra secret + err = kubeconfig.WriteKubeConfig(ctx, currentNamespaceClient, options.KubeConfigSecret, secretNamespace, config, isRemote) + if err != nil { + return fmt.Errorf("creating %s secret in the %s ns failed: %w", options.KubeConfigSecret, secretNamespace, err) + } + } + + // write the default Secret + return kubeconfig.WriteKubeConfig(ctx, currentNamespaceClient, kubeconfig.GetDefaultSecretName(translate.VClusterName), currentNamespace, config, isRemote) +} diff --git a/pkg/setup/initialize.go b/pkg/setup/initialize.go index 4a45adbd91..e1a7c41b2e 100644 --- a/pkg/setup/initialize.go +++ b/pkg/setup/initialize.go @@ -78,23 +78,27 @@ func initialize( options *options.VirtualClusterOptions, certificatesDir string, ) error { - var err error distro := constants.GetVClusterDistro() - var serviceCIDR, warning string + // retrieve service cidr + var serviceCIDR string if distro != constants.K0SDistro { + var warning string serviceCIDR, warning = servicecidr.GetServiceCIDR(ctx, currentNamespaceClient, currentNamespace) if warning != "" { klog.Warning(warning) } } + // check what distro are we running switch distro { case constants.K0SDistro: - serviceCIDR, err = servicecidr.EnsureServiceCIDRInK0sSecret(ctx, workspaceNamespaceClient, currentNamespaceClient, workspaceNamespace, currentNamespace, vClusterName) + // ensure service cidr + _, err := servicecidr.EnsureServiceCIDRInK0sSecret(ctx, workspaceNamespaceClient, currentNamespaceClient, workspaceNamespace, currentNamespace, vClusterName) if err != nil { return err } + // start k0s go func() { // we need to run this with the parent ctx as otherwise this context will be cancelled by the wait @@ -123,17 +127,14 @@ func initialize( case constants.K8SDistro, constants.EKSDistro: if certificatesDir != "" { // generate k8s certificates - err = GenerateK8sCerts(ctx, currentNamespaceClient, vClusterName, currentNamespace, serviceCIDR, certificatesDir, options.ClusterDomain) + err := GenerateK8sCerts(ctx, currentNamespaceClient, vClusterName, currentNamespace, serviceCIDR, certificatesDir, options.ClusterDomain) if err != nil { return err } } - serviceCIDR, warning := servicecidr.GetServiceCIDR(ctx, currentNamespaceClient, currentNamespace) - if warning != "" { - klog.Warning(warning) - } - apiUp := make(chan struct{}) + // start k8s + apiUp := make(chan struct{}) go func() { // we need to run this with the parent ctx as otherwise this context will be cancelled by the wait // loop in Initialize @@ -147,7 +148,7 @@ func initialize( case constants.Unknown: if certificatesDir != "" { // generate k8s certificates - err = GenerateK8sCerts(ctx, currentNamespaceClient, vClusterName, currentNamespace, serviceCIDR, certificatesDir, options.ClusterDomain) + err := GenerateK8sCerts(ctx, currentNamespaceClient, vClusterName, currentNamespace, serviceCIDR, certificatesDir, options.ClusterDomain) if err != nil { return err }