diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index a8ddfbec..ff6c51da 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -17,7 +17,7 @@ concurrency: cancel-in-progress: true env: - VCLUSTER_VERSION: v0.20.0 + VCLUSTER_VERSION: v0.20.1 VCLUSTER_SUFFIX: vcluster VCLUSTER_NAME: vcluster VCLUSTER_NAMESPACE: vcluster diff --git a/go.mod b/go.mod index 62b64e80..c44ff2d4 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/ghodss/yaml v1.0.0 github.com/hashicorp/go-plugin v1.6.0 github.com/loft-sh/log v0.0.0-20240219160058-26d83ffb46ac - github.com/loft-sh/vcluster v0.20.0 + github.com/loft-sh/vcluster v0.20.1 github.com/onsi/ginkgo/v2 v2.19.0 github.com/onsi/gomega v1.33.1 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index e6725b89..65a1ae48 100644 --- a/go.sum +++ b/go.sum @@ -323,8 +323,8 @@ github.com/loft-sh/log v0.0.0-20240219160058-26d83ffb46ac h1:Gz/7Lb7WgdgIv+KJz87 github.com/loft-sh/log v0.0.0-20240219160058-26d83ffb46ac/go.mod h1:YImeRjXH34Yf5E79T7UHBQpDZl9fIaaFRgyZ/bkY+UQ= github.com/loft-sh/utils v0.0.29 h1:P/MObccXToAZy2QoJSQDJ+OJx1qHitpFHEVj3QBSNJs= github.com/loft-sh/utils v0.0.29/go.mod h1:9hlX9cGpWHg3mNi/oBlv3X4ePGDMK66k8MbOZGFMDTI= -github.com/loft-sh/vcluster v0.20.0 h1:Tg7MCKI56LWHepMeTMn1RPBgHmPJu9KCkEyEHOBsGT4= -github.com/loft-sh/vcluster v0.20.0/go.mod h1:Xm+Y8EADJCix31Lvb9kIPO3CIoRRV6RJrL48/skB5qw= +github.com/loft-sh/vcluster v0.20.1 h1:EyKvUBh8eluZEM9HxO4wDh1B8JC1PpPNwE+Vqrq6oog= +github.com/loft-sh/vcluster v0.20.1/go.mod h1:q17XkrOcmJQXdwe8cLQkbeVUHRx1AyLKb/JDlR/wl5U= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= diff --git a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/create.go b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/create.go index bd2ccdfc..a6a358fc 100644 --- a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/create.go +++ b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/create.go @@ -66,6 +66,10 @@ vcluster create test --namespace test // Run executes the functionality func (cmd *CreateCmd) Run(ctx context.Context, args []string) error { + if !cmd.UpdateCurrent { + cmd.log.Warnf("%q has no effect anymore. Please consider using %q", "--update-current=false", "--connect=false") + } + cfg := cmd.LoadedConfig(cmd.log) // If driver has been passed as flag use it, otherwise read it from the config file diff --git a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/add/cluster.go b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/add/cluster.go index a5c76369..30848887 100644 --- a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/add/cluster.go +++ b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/add/cluster.go @@ -3,7 +3,6 @@ package add import ( "cmp" "context" - "errors" "fmt" "os" "os/exec" @@ -70,7 +69,7 @@ vcluster platform add cluster my-cluster }, } - c.Flags().StringVar(&cmd.Namespace, "namespace", "loft", "The namespace to generate the service account in. The namespace will be created if it does not exist") + c.Flags().StringVar(&cmd.Namespace, "namespace", clihelper.DefaultPlatformNamespace, "The namespace to generate the service account in. The namespace will be created if it does not exist") c.Flags().StringVar(&cmd.ServiceAccount, "service-account", "loft-admin", "The service account name to create") c.Flags().StringVar(&cmd.DisplayName, "display-name", "", "The display name to show in the UI for this cluster") c.Flags().BoolVar(&cmd.Wait, "wait", false, "If true, will wait until the cluster is initialized") @@ -87,7 +86,6 @@ vcluster platform add cluster my-cluster func (cmd *ClusterCmd) Run(ctx context.Context, args []string) error { // Get clusterName from command argument clusterName := args[0] - platformClient, err := platform.InitClientFromConfig(ctx, cmd.LoadedConfig(cmd.Log)) if err != nil { return fmt.Errorf("new client from path: %w", err) @@ -106,7 +104,7 @@ func (cmd *ClusterCmd) Run(ctx context.Context, args []string) error { loftVersion, err := platformClient.Version() if err != nil { - return fmt.Errorf("get loft version: %w", err) + return fmt.Errorf("get platform version: %w", err) } // TODO(ThomasK33): Eventually change this into an Apply instead of a Create call @@ -121,8 +119,9 @@ func (cmd *ClusterCmd) Run(ctx context.Context, args []string) error { User: user, Team: team, }, - NetworkPeer: true, - Access: getAccess(user, team), + NetworkPeer: true, + ManagementNamespace: cmd.Namespace, + Access: getAccess(user, team), }, }, }, metav1.CreateOptions{}) @@ -130,6 +129,21 @@ func (cmd *ClusterCmd) Run(ctx context.Context, args []string) error { return fmt.Errorf("create cluster: %w", err) } + // get namespace to install if cluster already exists + if kerrors.IsAlreadyExists(err) { + cluster, err := managementClient.Loft().ManagementV1().Clusters().Get(ctx, clusterName, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("get cluster: %w", err) + } + + cmd.Namespace = cluster.Spec.ManagementNamespace + if cmd.Namespace == "" { + cmd.Namespace = "loft" // since this is hardcoded in the platform at https://github.com/loft-sh/loft-enterprise/blob/b716f86a83d5f037ad993a0c3467b54393ef3b1f/pkg/util/agenthelper/helper.go#L9 + } + + cmd.Log.Infof("Using namespace %s because cluster already exists", cmd.Namespace) + } + accessKey, err := managementClient.Loft().ManagementV1().Clusters().GetAccessKey(ctx, clusterName, metav1.GetOptions{}) if err != nil { return fmt.Errorf("get cluster access key: %w", err) @@ -220,28 +234,22 @@ func (cmd *ClusterCmd) Run(ctx context.Context, args []string) error { return fmt.Errorf("create kube client: %w", err) } - errChan := make(chan error) + helmCmd := exec.CommandContext(ctx, "helm", helmArgs...) - go func() { - helmCmd := exec.CommandContext(ctx, "helm", helmArgs...) + helmCmd.Stdout = cmd.Log.Writer(logrus.DebugLevel, true) + helmCmd.Stderr = cmd.Log.Writer(logrus.DebugLevel, true) + helmCmd.Stdin = os.Stdin - helmCmd.Stdout = cmd.Log.Writer(logrus.DebugLevel, true) - helmCmd.Stderr = cmd.Log.Writer(logrus.DebugLevel, true) - helmCmd.Stdin = os.Stdin + cmd.Log.Info("Installing Loft agent...") + cmd.Log.Debugf("Running helm command: %v", helmCmd.Args) - cmd.Log.Info("Installing Loft agent...") - cmd.Log.Debugf("Running helm command: %v", helmCmd.Args) - - err = helmCmd.Run() - if err != nil { - errChan <- fmt.Errorf("failed to install loft chart: %w", err) - } - - close(errChan) - }() + err = helmCmd.Run() + if err != nil { + return fmt.Errorf("failed to install loft chart: %w", err) + } _, err = clihelper.WaitForReadyLoftPod(ctx, clientset, namespace, cmd.Log) - if err = errors.Join(err, <-errChan); err != nil { + if err != nil { return fmt.Errorf("wait for loft pod: %w", err) } @@ -260,7 +268,7 @@ func (cmd *ClusterCmd) Run(ctx context.Context, args []string) error { } } - cmd.Log.Donef("Successfully added cluster %s to Loft", clusterName) + cmd.Log.Donef("Successfully added cluster %s to the platform", clusterName) return nil } diff --git a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/add/vcluster.go b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/add/vcluster.go index 6fd63645..e8430b14 100644 --- a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/add/vcluster.go +++ b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/add/vcluster.go @@ -49,9 +49,6 @@ vcluster platform add vcluster my-vcluster --namespace vcluster-my-vcluster --pr addCmd.Flags().StringVar(&cmd.Host, "host", "", "The host where to reach the platform") addCmd.Flags().BoolVar(&cmd.Insecure, "insecure", false, "If the platform host is insecure") addCmd.Flags().BytesBase64Var(&cmd.CertificateAuthorityData, "ca-data", []byte{}, "additional, base64 encoded certificate authority data that will be passed to the platform secret") - // This is hidden until the platform side will be ready to use it - _ = addCmd.Flags().MarkHidden("ca-data") - return addCmd } diff --git a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/backup/management.go b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/backup/management.go index 25ed9add..cc7b6504 100644 --- a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/backup/management.go +++ b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/backup/management.go @@ -1,6 +1,7 @@ package backup import ( + "context" "fmt" "os" @@ -67,8 +68,10 @@ vcluster platform backup management }, } + platformNamespace, _ := clihelper.VClusterPlatformInstallationNamespace(context.Background()) + c.Flags().StringSliceVar(&cmd.Skip, "skip", []string{}, "What resources the backup should skip. Valid options are: users, teams, accesskeys, sharedsecrets, clusters and clusteraccounttemplates") - c.Flags().StringVar(&cmd.Namespace, "namespace", "vcluster-platform", product.Replace("The namespace vCluster platform was installed into")) + c.Flags().StringVar(&cmd.Namespace, "namespace", platformNamespace, product.Replace("The namespace vCluster platform was installed into")) c.Flags().StringVar(&cmd.Filename, "filename", "backup.yaml", "The filename to write the backup to") return c } diff --git a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/get/secret.go b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/get/secret.go index 8d623787..0384a910 100644 --- a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/get/secret.go +++ b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/get/secret.go @@ -14,6 +14,7 @@ import ( "github.com/loft-sh/vcluster/pkg/cli/flags" "github.com/loft-sh/vcluster/pkg/cli/util" "github.com/loft-sh/vcluster/pkg/platform" + "github.com/loft-sh/vcluster/pkg/platform/clihelper" pdefaults "github.com/loft-sh/vcluster/pkg/platform/defaults" "github.com/loft-sh/vcluster/pkg/projectutil" "github.com/pkg/errors" @@ -111,7 +112,7 @@ func (cmd *SecretCmd) Run(ctx context.Context, args []string) error { case set.ProjectSecret: namespace = projectutil.ProjectNamespace(cmd.Project) case set.SharedSecret: - namespace, err = set.GetSharedSecretNamespace(cmd.Namespace) + namespace, err = clihelper.VClusterPlatformInstallationNamespace(ctx) if err != nil { return errors.Wrap(err, "get shared secrets namespace") } diff --git a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/reset.go b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/reset.go index 370fbeb0..44947e61 100644 --- a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/reset.go +++ b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/reset.go @@ -10,6 +10,7 @@ import ( "github.com/loft-sh/log" "github.com/loft-sh/log/survey" "github.com/loft-sh/vcluster/pkg/cli/flags" + "github.com/loft-sh/vcluster/pkg/platform/clihelper" "github.com/loft-sh/vcluster/pkg/platform/kube" "github.com/loft-sh/vcluster/pkg/platform/random" "github.com/pkg/errors" @@ -22,13 +23,13 @@ import ( type PasswordCmd struct { *flags.GlobalFlags - - User string - Password string - Create bool - Force bool - Log log.Logger + + Namespace string + User string + Password string + Create bool + Force bool } func NewResetCmd(globalFlags *flags.GlobalFlags) *cobra.Command { @@ -79,6 +80,7 @@ vcluster platform reset password --user admin c.Flags().StringVar(&cmd.Password, "password", "", "The new password to use") c.Flags().BoolVar(&cmd.Create, "create", false, "Creates the user if it does not exist") c.Flags().BoolVar(&cmd.Force, "force", false, "If user had no password will create one") + c.Flags().StringVar(&cmd.Namespace, "namespace", clihelper.DefaultPlatformNamespace, "The namespace to use") return c } @@ -95,6 +97,22 @@ func (cmd *PasswordCmd) Run() error { return err } + // check if cluster has platform installed + apiResourceList, err := managementClient.Discovery().ServerResourcesForGroupVersion(storagev1.GroupVersion.String()) + if err != nil { + return fmt.Errorf("looks like the api group storage.loft.sh couldn't be found (%w). Please make sure you select the kube context the platform was installed in for this command to work", err) + } + found := false + for _, apiResource := range apiResourceList.APIResources { + if apiResource.Kind == "User" { + found = true + break + } + } + if !found { + return fmt.Errorf("resource User in api group storage.loft.sh couldn't be found. Please make sure you select the kube context the platform was installed in for this command to work") + } + // get user cmd.Log.Infof("Resetting password of user %s", cmd.User) user, err := managementClient.Loft().StorageV1().Users().Get(context.Background(), cmd.User, metav1.GetOptions{}) @@ -106,6 +124,15 @@ func (cmd *PasswordCmd) Run() error { return fmt.Errorf("user %s was not found, run with '--create' to create this user automatically", cmd.User) } + if cmd.Namespace == "" { + namespace, err := clihelper.VClusterPlatformInstallationNamespace(context.Background()) + if err != nil { + return fmt.Errorf("failed to find platform namespace: %w", err) + } + + cmd.Namespace = namespace + } + user, err = managementClient.Loft().StorageV1().Users().Create(context.Background(), &storagev1.User{ ObjectMeta: metav1.ObjectMeta{ Name: cmd.User, @@ -118,7 +145,7 @@ func (cmd *PasswordCmd) Run() error { }, PasswordRef: &storagev1.SecretRef{ SecretName: "loft-password-" + random.String(5), - SecretNamespace: "loft", + SecretNamespace: cmd.Namespace, Key: "password", }, }, @@ -136,7 +163,7 @@ func (cmd *PasswordCmd) Run() error { user.Spec.PasswordRef = &storagev1.SecretRef{ SecretName: "loft-password-" + random.String(5), - SecretNamespace: "loft", + SecretNamespace: cmd.Namespace, Key: "password", } user, err = managementClient.Loft().StorageV1().Users().Update(context.Background(), user, metav1.UpdateOptions{}) diff --git a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/set/secret.go b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/set/secret.go index 3f9b9c5c..ec34fb1e 100644 --- a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/set/secret.go +++ b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/set/secret.go @@ -13,6 +13,7 @@ import ( "github.com/loft-sh/vcluster/pkg/cli/flags" "github.com/loft-sh/vcluster/pkg/cli/util" "github.com/loft-sh/vcluster/pkg/platform" + "github.com/loft-sh/vcluster/pkg/platform/clihelper" pdefaults "github.com/loft-sh/vcluster/pkg/platform/defaults" "github.com/loft-sh/vcluster/pkg/platform/kube" "github.com/loft-sh/vcluster/pkg/projectutil" @@ -112,7 +113,7 @@ func (cmd *SecretCmd) Run(cobraCmd *cobra.Command, args []string) error { namespace := projectutil.ProjectNamespace(cmd.Project) return cmd.setProjectSecret(ctx, managementClient, args, namespace, secretName, keyName) case SharedSecret: - namespace, err := GetSharedSecretNamespace(cmd.Namespace) + namespace, err := clihelper.VClusterPlatformInstallationNamespace(ctx) if err != nil { return errors.Wrap(err, "get shared secrets namespace") } @@ -258,11 +259,3 @@ func (cmd *SecretCmd) setSharedSecret(ctx context.Context, managementClient kube cmd.log.Donef("Successfully set secret key %s.%s", secretName, keyName) return nil } - -func GetSharedSecretNamespace(namespace string) (string, error) { - if namespace == "" { - namespace = "loft" - } - - return namespace, nil -} diff --git a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/start.go b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/start.go index 40a9faa3..b3c4cf17 100644 --- a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/start.go +++ b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/platform/start.go @@ -3,7 +3,9 @@ package platform import ( "context" "fmt" + "strings" + "github.com/blang/semver" "github.com/loft-sh/log" "github.com/loft-sh/log/survey" "github.com/loft-sh/log/terminal" @@ -11,6 +13,7 @@ import ( "github.com/loft-sh/vcluster/pkg/cli/flags" "github.com/loft-sh/vcluster/pkg/cli/start" "github.com/loft-sh/vcluster/pkg/platform" + "github.com/loft-sh/vcluster/pkg/platform/clihelper" "github.com/spf13/cobra" "k8s.io/client-go/tools/clientcmd" ) @@ -53,7 +56,7 @@ before running this command: } startCmd.Flags().StringVar(&cmd.Context, "context", "", "The kube context to use for installation") - startCmd.Flags().StringVar(&cmd.Namespace, "namespace", "vcluster-platform", "The namespace to install vCluster platform into") + startCmd.Flags().StringVar(&cmd.Namespace, "namespace", clihelper.DefaultPlatformNamespace, "The namespace to install vCluster platform into") startCmd.Flags().StringVar(&cmd.LocalPort, "local-port", "", "The local port to bind to if using port-forwarding") startCmd.Flags().StringVar(&cmd.Host, "host", "", "Provide a hostname to enable ingress and configure its hostname") startCmd.Flags().StringVar(&cmd.Password, "password", "", "The password to use for the admin account. (If empty this will be the namespace UID)") @@ -62,7 +65,7 @@ before running this command: startCmd.Flags().BoolVar(&cmd.ReuseValues, "reuse-values", true, "Reuse previous vCluster platform helm values on upgrade") startCmd.Flags().BoolVar(&cmd.Upgrade, "upgrade", false, "If true, vCluster platform will try to upgrade the release") startCmd.Flags().StringVar(&cmd.Email, "email", "", "The email to use for the installation") - startCmd.Flags().BoolVar(&cmd.Reset, "reset", false, "If true, an existing vCluster platform instance will be deleted before installing vCluster platform") + startCmd.Flags().BoolVar(&cmd.Reset, "reset", false, "If true, existing vCluster Platform resources, including the deployment, will be deleted before installing vCluster platform") startCmd.Flags().BoolVar(&cmd.NoWait, "no-wait", false, "If true, vCluster platform will not wait after installing it") startCmd.Flags().BoolVar(&cmd.NoPortForwarding, "no-port-forwarding", false, "If true, vCluster platform will not do port forwarding after installing it") startCmd.Flags().BoolVar(&cmd.NoTunnel, "no-tunnel", false, "If true, vCluster platform will not create a loft.host tunnel for this installation") @@ -83,6 +86,15 @@ func (cmd *StartCmd) Run(ctx context.Context) error { cmd.Version = latestVersion } } + + // if < v4.0.0 then use ChartName loft + parsedVersion, err := semver.Parse(strings.TrimPrefix(cmd.Version, "v")) + if err != nil { + return fmt.Errorf("parse provided version %s: %w", cmd.Version, err) + } else if parsedVersion.LT(semver.MustParse("4.0.0-alpha.0")) && cmd.ChartName == "vcluster-platform" { + cmd.ChartName = "loft" + } + // make sure we are in the correct context // first load the kube config kubeClientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(clientcmd.NewDefaultClientConfigLoadingRules(), &clientcmd.ConfigOverrides{ diff --git a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/ui.go b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/ui.go index d09227b4..a85d3cfe 100644 --- a/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/ui.go +++ b/vendor/github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/ui.go @@ -2,8 +2,10 @@ package cmd import ( "context" + "errors" "fmt" "os" + "os/exec" "github.com/loft-sh/api/v4/pkg/product" "github.com/loft-sh/log" @@ -63,10 +65,15 @@ func (cmd *UICmd) Run(ctx context.Context) error { return fmt.Errorf("please login first using '%s' or start using '%s'", product.LoginCmd(), product.StartCmd()) } + // still open the UI err = open.Run(url) - if err != nil { - return fmt.Errorf("error opening url: %w", err) + if errors.Is(err, exec.ErrNotFound) { + cmd.Log.Warnf("Couldn't open the login page in a browser. No browser found: %v", err) + } else if err != nil { + return fmt.Errorf("couldn't open the login page in a browser: %w", err) } + cmd.Log.Infof("If the browser does not open automatically, please navigate to %s", url) + return nil } diff --git a/vendor/github.com/loft-sh/vcluster/pkg/cli/connect_platform.go b/vendor/github.com/loft-sh/vcluster/pkg/cli/connect_platform.go index 016213eb..0f1ccf09 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/cli/connect_platform.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/cli/connect_platform.go @@ -2,6 +2,7 @@ package cli import ( "context" + "errors" "fmt" "github.com/loft-sh/log" @@ -59,7 +60,7 @@ func ConnectPlatform(ctx context.Context, options *ConnectOptions, globalFlags * } // retrieve vCluster kube config - kubeConfig, err := cmd.getVClusterKubeConfig(ctx, platformClient, vCluster) + kubeConfig, err := cmd.getVClusterKubeConfig(ctx, platformClient, globalFlags, vCluster) if err != nil { return err } @@ -89,8 +90,12 @@ func (cmd *connectPlatform) validateProFlags() error { return nil } -func (cmd *connectPlatform) getVClusterKubeConfig(ctx context.Context, platformClient platform.Client, vCluster *platform.VirtualClusterInstanceProject) (*clientcmdapi.Config, error) { - contextOptions, err := platform.CreateVirtualClusterInstanceOptions(ctx, platformClient, "", vCluster.Project.Name, vCluster.VirtualCluster, false) +func (cmd *connectPlatform) getVClusterKubeConfig(ctx context.Context, platformClient platform.Client, globalFlags *flags.GlobalFlags, vCluster *platform.VirtualClusterInstanceProject) (*clientcmdapi.Config, error) { + if vCluster == nil || vCluster.Project == nil || vCluster.VirtualCluster == nil { + return nil, errors.New("invalid vcluster VirtualClusterInstanceProject object") + } + + contextOptions, err := platform.CreateVirtualClusterInstanceOptions(ctx, platformClient, globalFlags.Config, vCluster.Project.Name, vCluster.VirtualCluster, false) if err != nil { return nil, fmt.Errorf("prepare vCluster kube config: %w", err) } diff --git a/vendor/github.com/loft-sh/vcluster/pkg/cli/create_helm.go b/vendor/github.com/loft-sh/vcluster/pkg/cli/create_helm.go index f66e210a..f744b1cc 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/cli/create_helm.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/cli/create_helm.go @@ -61,8 +61,6 @@ type CreateOptions struct { UpdateCurrent bool BackgroundProxy bool Add bool - CreateContext bool - SwitchContext bool Expose bool ExposeLocal bool Connect bool @@ -159,7 +157,7 @@ func CreateHelm(ctx context.Context, options *CreateOptions, globalFlags *flags. if cmd.Connect { return ConnectHelm(ctx, &ConnectOptions{ BackgroundProxy: cmd.BackgroundProxy, - UpdateCurrent: cmd.UpdateCurrent, + UpdateCurrent: true, KubeConfigContextName: cmd.KubeConfigContextName, KubeConfig: "./kubeconfig.yaml", }, cmd.GlobalFlags, vClusterName, nil, cmd.log) @@ -320,7 +318,7 @@ func CreateHelm(ctx context.Context, options *CreateOptions, globalFlags *flags. cmd.log.Donef("Successfully %s virtual cluster %s in namespace %s", verb, vClusterName, cmd.Namespace) return ConnectHelm(ctx, &ConnectOptions{ BackgroundProxy: cmd.BackgroundProxy, - UpdateCurrent: cmd.UpdateCurrent, + UpdateCurrent: true, Print: cmd.Print, KubeConfigContextName: cmd.KubeConfigContextName, KubeConfig: "./kubeconfig.yaml", diff --git a/vendor/github.com/loft-sh/vcluster/pkg/cli/create_platform.go b/vendor/github.com/loft-sh/vcluster/pkg/cli/create_platform.go index 821d2898..d26abba3 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/cli/create_platform.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/cli/create_platform.go @@ -19,13 +19,11 @@ import ( "github.com/loft-sh/vcluster/pkg/kube" "github.com/loft-sh/vcluster/pkg/platform" "github.com/loft-sh/vcluster/pkg/platform/clihelper" - "github.com/loft-sh/vcluster/pkg/platform/kubeconfig" "github.com/loft-sh/vcluster/pkg/projectutil" "github.com/loft-sh/vcluster/pkg/strvals" "github.com/loft-sh/vcluster/pkg/telemetry" "github.com/loft-sh/vcluster/pkg/upgrade" "github.com/loft-sh/vcluster/pkg/util" - "github.com/mgutz/ansi" "golang.org/x/mod/semver" kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -145,26 +143,10 @@ func CreatePlatform(ctx context.Context, options *CreateOptions, globalFlags *fl } log.Donef("Successfully created the virtual cluster %s in project %s", virtualClusterName, options.Project) - if options.CreateContext { - // create kube context options - contextOptions, err := platform.CreateVirtualClusterInstanceOptions(ctx, platformClient, "", options.Project, virtualClusterInstance, options.SwitchContext) - if err != nil { - return err - } - - // update kube config - err = kubeconfig.UpdateKubeConfig(contextOptions, cfg) - if err != nil { - return err - } - - log.Donef("Successfully updated kube context to use virtual cluster %s in project %s", ansi.Color(virtualClusterName, "white+b"), ansi.Color(options.Project, "white+b")) - } - // check if we should connect to the vcluster or print the kubeconfig if options.Connect || options.Print { return ConnectPlatform(ctx, &ConnectOptions{ - UpdateCurrent: options.UpdateCurrent, + UpdateCurrent: true, Print: options.Print, KubeConfigContextName: options.KubeConfigContextName, KubeConfig: "./kubeconfig.yaml", diff --git a/vendor/github.com/loft-sh/vcluster/pkg/cli/delete_helm.go b/vendor/github.com/loft-sh/vcluster/pkg/cli/delete_helm.go index 051364ce..0bc95cbc 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/cli/delete_helm.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/cli/delete_helm.go @@ -7,6 +7,7 @@ import ( "os/exec" "time" + managementv1 "github.com/loft-sh/api/v4/pkg/apis/management/v1" "github.com/loft-sh/log" "github.com/loft-sh/vcluster/pkg/cli/find" "github.com/loft-sh/vcluster/pkg/cli/flags" @@ -25,8 +26,6 @@ import ( clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) -const VirtualClusterServiceUIDLabel = "vcluster.loft.sh/service-uid" - type DeleteOptions struct { Driver string @@ -122,10 +121,13 @@ func DeleteHelm(ctx context.Context, options *DeleteOptions, globalFlags *flags. // try to delete the vCluster in the platform if vClusterService != nil { + cmd.log.Debugf("deleting vcluster in platform") err = cmd.deleteVClusterInPlatform(ctx, vClusterService) if err != nil { return err } + } else { + cmd.log.Warn("vcluster service not found, could not delete in platform") } // try to delete the pvc @@ -242,15 +244,21 @@ func (cmd *deleteHelm) deleteVClusterInPlatform(ctx context.Context, vClusterSer return nil } - virtualClusterInstances, err := managementClient.Loft().ManagementV1().VirtualClusterInstances(corev1.NamespaceAll).List(ctx, metav1.ListOptions{ - LabelSelector: VirtualClusterServiceUIDLabel + "=" + string(vClusterService.UID), - }) + virtualClusterInstances, err := managementClient.Loft().ManagementV1().VirtualClusterInstances(corev1.NamespaceAll).List(ctx, metav1.ListOptions{}) if err != nil { cmd.log.Debugf("Error retrieving vcluster instances: %v", err) return nil } + toDelete := []managementv1.VirtualClusterInstance{} for _, virtualClusterInstance := range virtualClusterInstances.Items { + if virtualClusterInstance.Status.ServiceUID != "" && virtualClusterInstance.Status.ServiceUID == string(vClusterService.UID) { + toDelete = append(toDelete, virtualClusterInstance) + } + } + cmd.log.Debugf("found %d matching virtualclusterinstances", len(toDelete)) + + for _, virtualClusterInstance := range toDelete { cmd.log.Infof("Delete virtual cluster instance %s/%s in platform", virtualClusterInstance.Namespace, virtualClusterInstance.Name) err = managementClient.Loft().ManagementV1().VirtualClusterInstances(virtualClusterInstance.Namespace).Delete(ctx, virtualClusterInstance.Name, metav1.DeleteOptions{}) if err != nil { diff --git a/vendor/github.com/loft-sh/vcluster/pkg/cli/flags/create/create.go b/vendor/github.com/loft-sh/vcluster/pkg/cli/flags/create/create.go index 05b67ee7..2babb56a 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/cli/flags/create/create.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/cli/flags/create/create.go @@ -20,8 +20,6 @@ func AddCommonFlags(cmd *cobra.Command, options *cli.CreateOptions) { cmd.Flags().StringArrayVar(&options.SetValues, "set", []string{}, "Set values for helm. E.g. --set 'persistence.enabled=true'") cmd.Flags().BoolVar(&options.Print, "print", false, "If enabled, prints the context to the console") cmd.Flags().BoolVar(&options.UpdateCurrent, "update-current", true, "If true updates the current kube config") - cmd.Flags().BoolVar(&options.CreateContext, "create-context", true, "If the CLI should create a kube context for the space") - cmd.Flags().BoolVar(&options.SwitchContext, "switch-context", true, "If the CLI should switch the current context to the new context") cmd.Flags().BoolVar(&options.Expose, "expose", false, "If true will create a load balancer service to expose the vcluster endpoint") cmd.Flags().BoolVar(&options.Connect, "connect", true, "If true will run vcluster connect directly after the vcluster was created") cmd.Flags().BoolVar(&options.Upgrade, "upgrade", false, "If true will try to upgrade the vcluster instead of failing if it already exists") @@ -29,6 +27,8 @@ func AddCommonFlags(cmd *cobra.Command, options *cli.CreateOptions) { _ = cmd.Flags().MarkHidden("distro") _ = cmd.Flags().MarkDeprecated("distro", fmt.Sprintf("please specify the distro by setting %q accordingly via values.yaml file.", "controlPlane.distro")) + _ = cmd.Flags().MarkHidden("update-current") + _ = cmd.Flags().MarkDeprecated("update-current", fmt.Sprintf("please use %q.", "--connect")) } func AddHelmFlags(cmd *cobra.Command, options *cli.CreateOptions) { diff --git a/vendor/github.com/loft-sh/vcluster/pkg/cli/start/login.go b/vendor/github.com/loft-sh/vcluster/pkg/cli/start/login.go index da5bcf82..c49bf309 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/cli/start/login.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/cli/start/login.go @@ -4,10 +4,12 @@ import ( "bytes" "crypto/tls" "encoding/json" + "errors" "fmt" "io" "net/http" netUrl "net/url" + "os/exec" "strings" types "github.com/loft-sh/api/v4/pkg/auth" @@ -29,10 +31,14 @@ func (l *LoftStarter) login(url string) error { if l.isLoggedIn(url) { // still open the UI err := open.Run(url) - if err != nil { + if errors.Is(err, exec.ErrNotFound) { + l.Log.Warnf("Couldn't open the login page in a browser. No browser found: %v", err) + } else if err != nil { return fmt.Errorf("couldn't open the login page in a browser: %w", err) } + l.Log.Infof("If the browser does not open automatically, please navigate to %s", url) + return nil } @@ -107,11 +113,13 @@ func (l *LoftStarter) loginUI(url string) error { loginURL := fmt.Sprintf("%s/login#%s", url, queryString) err := open.Run(loginURL) - if err != nil { + if errors.Is(err, exec.ErrNotFound) { + l.Log.Warnf("Couldn't open the login page in a browser. No browser found: %v", err) + } else if err != nil { return fmt.Errorf("couldn't open the login page in a browser: %w", err) } - l.Log.Infof("If the browser does not open automatically, please navigate to %s", loginURL) + l.Log.Infof("If the browser does not open automatically, please navigate to %s", url) return nil } diff --git a/vendor/github.com/loft-sh/vcluster/pkg/cli/start/start.go b/vendor/github.com/loft-sh/vcluster/pkg/cli/start/start.go index 0d78c238..17c17bb6 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/cli/start/start.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/cli/start/start.go @@ -113,12 +113,6 @@ func (l *LoftStarter) Start(ctx context.Context) error { l.Log.Info(product.Replace("Welcome to Loft!")) l.Log.Info(product.Replace("This installer will help you configure and deploy Loft.")) - // make sure we are ready for installing - err = l.prepareInstall(ctx) - if err != nil { - return err - } - err = l.upgradeLoft() if err != nil { return err @@ -127,11 +121,6 @@ func (l *LoftStarter) Start(ctx context.Context) error { return l.success(ctx) } -func (l *LoftStarter) prepareInstall(ctx context.Context) error { - // delete admin user & secret - return clihelper.UninstallLoft(ctx, l.KubeClient, l.RestConfig, l.Context, l.Namespace, log.Discard) -} - func (l *LoftStarter) prepare() error { platformClient := platform.NewClientFromConfig(l.LoadedConfig(l.Log)) diff --git a/vendor/github.com/loft-sh/vcluster/pkg/cli/start/success.go b/vendor/github.com/loft-sh/vcluster/pkg/cli/start/success.go index a0285cb3..871f87c3 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/cli/start/success.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/cli/start/success.go @@ -231,7 +231,7 @@ func (l *LoftStarter) waitForLoft(ctx context.Context) (*corev1.Pod, error) { } // ensure user admin secret is there - isNewPassword, err := clihelper.EnsureAdminPassword(ctx, l.KubeClient, l.RestConfig, l.Password, l.Log) + isNewPassword, err := clihelper.EnsureAdminPassword(ctx, l.KubeClient, l.RestConfig, l.Namespace, l.Password, l.Log) if err != nil { return nil, err } diff --git a/vendor/github.com/loft-sh/vcluster/pkg/controllers/deploy/deploy.go b/vendor/github.com/loft-sh/vcluster/pkg/controllers/deploy/deploy.go index 9161431b..d1a689ec 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/controllers/deploy/deploy.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/controllers/deploy/deploy.go @@ -52,6 +52,9 @@ const ( VClusterDeployConfigMapNamespace = "kube-system" ) +// default name for base64 bundle names when chart is not provided +const defaultBundleName = "chart-bundle" + type Deployer struct { Log loghelper.Logger @@ -341,7 +344,7 @@ func (r *Deployer) initiateUpgrade(ctx context.Context, chart vclusterconfig.Exp if err != nil { return err } else if path == "" { - return fmt.Errorf("couldn't find chart") + return fmt.Errorf("couldn't find chart %q", chart.Chart.Name) } values := chart.Values @@ -376,51 +379,35 @@ func (r *Deployer) initiateUpgrade(ctx context.Context, chart vclusterconfig.Exp return nil } -func getTarballPath(helmWorkDir, repo, name, version string) (tarballPath, tarballDir string) { +// getTarballDir is the location the chart should be pulled to. Chart names can be unpredictable so the temporary directory should be unique +func getTarballDir(helmWorkDir, repo, name, version string) (tarballDir string) { var repoDir string // hashing the name so that slashes in url characters and other unaccounted-for characters - // don't fail making the directory - if repo != "" { - repoDigest := sha256.Sum256([]byte(repo)) - repoDir = hex.EncodeToString(repoDigest[0:])[0:10] - } - // empty repoDir is ignored + // don't fail when creating the directory + repoDigest := sha256.Sum256([]byte(repo + name + version)) + repoDir = hex.EncodeToString(repoDigest[0:])[0:10] tarballDir = filepath.Join(helmWorkDir, repoDir) - tarballPath = filepath.Join(tarballDir, fmt.Sprintf("%s-%s.tgz", name, version)) - return tarballPath, tarballDir + return tarballDir } func (r *Deployer) findChart(chart vclusterconfig.ExperimentalDeployHelm) (string, error) { - tarballPath, tarballDir := getTarballPath(HelmWorkDir, chart.Chart.Repo, chart.Chart.Name, chart.Chart.Version) + tarballDir := getTarballDir(HelmWorkDir, chart.Chart.Repo, chart.Chart.Name, chart.Chart.Version) + r.Log.Debugf("tarballdir for chart: %q", tarballDir) // if version specified, look for specific file - if chart.Chart.Version != "" { - pathsToTry := []string{tarballPath} - // try with alternate names as well - if chart.Chart.Version[0] != 'v' { - tarballPathWithV, _ := getTarballPath(HelmWorkDir, chart.Chart.Repo, chart.Chart.Name, fmt.Sprintf("v%s", chart.Chart.Version)) - pathsToTry = append(pathsToTry, tarballPathWithV) - } - for _, path := range pathsToTry { - _, err := os.Stat(path) - if err == nil { - return path, nil - } else if !os.IsNotExist(err) { - return "", err - } - } - // if version not specified, look for any version - } else { - files, err := os.ReadDir(tarballDir) - if os.IsNotExist(err) { - return "", nil - } else if err != nil { - return "", err - } - for _, f := range files { - if strings.HasPrefix(f.Name(), chart.Chart.Name+"-") { - return filepath.Join(tarballDir, f.Name()), nil - } + + files, err := os.ReadDir(tarballDir) + if os.IsNotExist(err) { + return "", nil + } else if err != nil { + return "", err + } + for _, f := range files { + name := f.Name() + r.Log.Debugf("checking %q is chart", name) + if strings.HasPrefix(f.Name(), chart.Chart.Name) || strings.HasPrefix(f.Name(), defaultBundleName) { + r.Log.Debugf("%q is chart", name) + return filepath.Join(tarballDir, f.Name()), nil } } @@ -434,7 +421,7 @@ func (r *Deployer) initiateInstall(ctx context.Context, chart vclusterconfig.Exp if err != nil { return err } else if path == "" { - return fmt.Errorf("couldn't find chart") + return fmt.Errorf("couldn't find chart: %q", chart.Chart.Name) } values := chart.Values @@ -500,7 +487,7 @@ func (r *Deployer) pullChartArchive(ctx context.Context, chart vclusterconfig.Ex // check if tarball exists if tarballPath == "" { - tarballPath, tarballDir := getTarballPath(HelmWorkDir, chart.Chart.Repo, chart.Chart.Name, chart.Chart.Version) + tarballDir := getTarballDir(HelmWorkDir, chart.Chart.Repo, chart.Chart.Name, chart.Chart.Version) err := os.MkdirAll(tarballDir, 0755) if err != nil { return err @@ -511,7 +498,14 @@ func (r *Deployer) pullChartArchive(ctx context.Context, chart vclusterconfig.Ex return err } - err = os.WriteFile(tarballPath, bytes, 0666) + bundleName := chart.Chart.Name + if bundleName == "" { + bundleName = defaultBundleName + } + + chartPath := filepath.Join(tarballDir, bundleName+".tar.gz") + r.Log.Debugf("writing bundle to tarball: %q", chartPath) + err = os.WriteFile(chartPath, bytes, 0666) if err != nil { return errors.Wrap(err, "write bundle to file") } diff --git a/vendor/github.com/loft-sh/vcluster/pkg/controllers/generic/export_syncer.go b/vendor/github.com/loft-sh/vcluster/pkg/controllers/generic/export_syncer.go index c00bc844..ae0129a6 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/controllers/generic/export_syncer.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/controllers/generic/export_syncer.go @@ -311,3 +311,22 @@ func (f *exporter) TranslateMetadata(ctx context.Context, vObj client.Object) cl func (f *exporter) objectMatches(obj client.Object) bool { return f.selector == nil || f.selector.Matches(labels.Set(obj.GetLabels())) } + +var _ syncertypes.ObjectExcluder = &exporter{} + +func (f *exporter) ExcludeVirtual(vObj client.Object) bool { + return f.excludeObject(vObj) +} + +func (f *exporter) ExcludePhysical(_ client.Object) bool { + return false +} + +func (f *exporter) excludeObject(obj client.Object) bool { + if f.selector == nil { + return false + } + + matches := f.selector.Matches(labels.Set(obj.GetLabels())) + return !matches +} diff --git a/vendor/github.com/loft-sh/vcluster/pkg/controllers/resources/nodes/translate.go b/vendor/github.com/loft-sh/vcluster/pkg/controllers/resources/nodes/translate.go index 6debccab..b5bc8eb4 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/controllers/resources/nodes/translate.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/controllers/resources/nodes/translate.go @@ -19,7 +19,9 @@ import ( ) var ( - TaintsAnnotation = "vcluster.loft.sh/original-taints" + TaintsAnnotation = "vcluster.loft.sh/original-taints" + RancherAgentPodRequestsAnnotation = "management.cattle.io/pod-requests" + RancherAgentPodLimitsAnnotation = "management.cattle.io/pod-limits" ) func (s *nodeSyncer) translateUpdateBackwards(pNode *corev1.Node, vNode *corev1.Node) *corev1.Node { @@ -27,7 +29,8 @@ func (s *nodeSyncer) translateUpdateBackwards(pNode *corev1.Node, vNode *corev1. // merge labels & taints translatedSpec := pNode.Spec.DeepCopy() - labels, annotations := translate.ApplyMetadata(pNode.Annotations, vNode.Annotations, pNode.Labels, vNode.Labels, TaintsAnnotation) + excludeAnnotations := []string{TaintsAnnotation, RancherAgentPodRequestsAnnotation, RancherAgentPodLimitsAnnotation} + labels, annotations := translate.ApplyMetadata(pNode.Annotations, vNode.Annotations, pNode.Labels, vNode.Labels, excludeAnnotations...) // merge taints together oldPhysical := []string{} diff --git a/vendor/github.com/loft-sh/vcluster/pkg/controllers/resources/pods/translate/hostpath.go b/vendor/github.com/loft-sh/vcluster/pkg/controllers/resources/pods/translate/hostpath.go index d39d3516..36e1acb6 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/controllers/resources/pods/translate/hostpath.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/controllers/resources/pods/translate/hostpath.go @@ -25,6 +25,9 @@ const ( func (t *translator) ensureMountPropagation(pPod *corev1.Pod) { for i, container := range pPod.Spec.Containers { for j, volumeMount := range container.VolumeMounts { + // handle scenarios where path ends with a / + volumeMount.MountPath = strings.TrimSuffix(volumeMount.MountPath, "/") + if volumeMount.MountPath == PodLoggingHostPath || volumeMount.MountPath == KubeletPodPath || volumeMount.MountPath == LogHostPath { diff --git a/vendor/github.com/loft-sh/vcluster/pkg/controllers/syncer/syncer.go b/vendor/github.com/loft-sh/vcluster/pkg/controllers/syncer/syncer.go index 68c85333..61697d3d 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/controllers/syncer/syncer.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/controllers/syncer/syncer.go @@ -2,6 +2,7 @@ package syncer import ( "context" + "errors" "fmt" "strings" "time" @@ -270,7 +271,7 @@ func (r *SyncController) excludePhysical(ctx context.Context, pObj, vObj client. if !excluderOk && vObj != nil { msg := fmt.Sprintf("conflict: cannot sync virtual object %s/%s as unmanaged physical object %s/%s exists with desired name", vObj.GetNamespace(), vObj.GetName(), pObj.GetNamespace(), pObj.GetName()) r.vEventRecorder.Eventf(vObj, "Warning", "SyncError", msg) - return false, fmt.Errorf(msg) + return false, errors.New(msg) } return true, nil diff --git a/vendor/github.com/loft-sh/vcluster/pkg/lifecycle/lifecycle.go b/vendor/github.com/loft-sh/vcluster/pkg/lifecycle/lifecycle.go index 140e8089..a2821fc6 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/lifecycle/lifecycle.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/lifecycle/lifecycle.go @@ -63,7 +63,7 @@ func DeletePods(ctx context.Context, kubeClient *kubernetes.Clientset, labelSele } if len(list.Items) > 0 { - log.Infof("Delete %d vcluster pods", len(list.Items)) + log.Infof("Relaunching %d vcluster pods", len(list.Items)) for _, item := range list.Items { err = kubeClient.CoreV1().Pods(namespace).Delete(ctx, item.Name, metav1.DeleteOptions{}) diff --git a/vendor/github.com/loft-sh/vcluster/pkg/platform/clihelper/clihelper.go b/vendor/github.com/loft-sh/vcluster/pkg/platform/clihelper/clihelper.go index 2074d318..888b5d46 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/platform/clihelper/clihelper.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/platform/clihelper/clihelper.go @@ -35,6 +35,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/transport/spdy" "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset" @@ -56,6 +57,8 @@ const defaultReleaseName = "loft" const LoftRouterDomainSecret = "loft-router-domain" +const DefaultPlatformNamespace = "vcluster-platform" + const defaultTimeout = 10 * time.Minute const timeoutEnvVariable = "LOFT_TIMEOUT" @@ -135,6 +138,10 @@ func GetProKubeConfig(options kubeconfig.ContextOptions) (*clientcmdapi.Config, } func GetLoftIngressHost(ctx context.Context, kubeClient kubernetes.Interface, namespace string) (string, error) { + if kubeClient == nil { + return "", errors.New("nil kubeClient") + } + ingress, err := kubeClient.NetworkingV1().Ingresses(namespace).Get(ctx, "loft-ingress", metav1.GetOptions{}) if err != nil { ingress, err := kubeClient.NetworkingV1beta1().Ingresses(namespace).Get(ctx, "loft-ingress", metav1.GetOptions{}) @@ -235,6 +242,16 @@ func WaitForReadyLoftPod(ctx context.Context, kubeClient kubernetes.Interface, n } func StartPortForwarding(ctx context.Context, config *rest.Config, client kubernetes.Interface, pod *corev1.Pod, localPort string, log log.Logger) (chan struct{}, error) { + if config == nil { + return nil, errors.New("nil config") + } + if client == nil { + return nil, errors.New("nil client") + } + if pod == nil { + return nil, errors.New("nil pod") + } + log.WriteString(logrus.InfoLevel, "\n") log.Infof("Starting port-forwarding to the %s pod", product.DisplayName()) execRequest := client.CoreV1().RESTClient().Post(). @@ -292,6 +309,10 @@ func StartPortForwarding(ctx context.Context, config *rest.Config, client kubern } func GetLoftDefaultPassword(ctx context.Context, kubeClient kubernetes.Interface, namespace string) (string, error) { + if kubeClient == nil { + return "", errors.New("nil kubeClient") + } + loftNamespace, err := kubeClient.CoreV1().Namespaces().Get(ctx, namespace, metav1.GetOptions{}) if err != nil { if kerrors.IsNotFound(err) { @@ -412,6 +433,19 @@ func EnterHostNameQuestion(log log.Logger) (string, error) { } func IsLoftAlreadyInstalled(ctx context.Context, kubeClient kubernetes.Interface, namespace string) (bool, error) { + if kubeClient == nil { + return false, errors.New("nil kubeClient") + } + + if namespace == "" { + var nsErr error + namespace, nsErr = VClusterPlatformInstallationNamespace(ctx) + + if nsErr != nil { + return false, nil + } + } + _, err := kubeClient.AppsV1().Deployments(namespace).Get(ctx, defaultDeploymentName, metav1.GetOptions{}) if err != nil { if kerrors.IsNotFound(err) { @@ -424,6 +458,39 @@ func IsLoftAlreadyInstalled(ctx context.Context, kubeClient kubernetes.Interface return true, nil } +func VClusterPlatformInstallationNamespace(ctx context.Context) (string, error) { + kubeClientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(clientcmd.NewDefaultClientConfigLoadingRules(), &clientcmd.ConfigOverrides{}) + + kubeConfig, err := kubeClientConfig.ClientConfig() + if err != nil { + return "", fmt.Errorf("there is an error loading your current kube config (%w), please make sure you have access to a kubernetes cluster and the command `kubectl get namespaces` is working", err) + } + + kubeClient, err := kubernetes.NewForConfig(kubeConfig) + if err != nil { + return "", fmt.Errorf("there is an error loading your current kube config (%w), please make sure you have access to a kubernetes cluster and the command `kubectl get namespaces` is working", err) + } + + deployments, err := kubeClient.AppsV1().Deployments(metav1.NamespaceAll).List(ctx, metav1.ListOptions{ + LabelSelector: "app=loft", + }) + if err != nil { + if kerrors.IsNotFound(err) { + return "", nil + } + + return "", fmt.Errorf("error accessing kubernetes cluster: %w", err) + } + + for _, deploy := range deployments.Items { + if deploy.Name == defaultDeploymentName { + return deploy.Namespace, nil + } + } + + return "", fmt.Errorf("failed to find the namespace loft is installed in") +} + func UninstallLoft(ctx context.Context, kubeClient kubernetes.Interface, restConfig *rest.Config, kubeContext, namespace string, log log.Logger) error { log.Infof("Uninstalling %s...", product.DisplayName()) releaseName := defaultReleaseName @@ -537,6 +604,10 @@ func deleteUser(ctx context.Context, restConfig *rest.Config, name string) error } func EnsureIngressController(ctx context.Context, kubeClient kubernetes.Interface, kubeContext string, log log.Logger) error { + if kubeClient == nil { + return errors.New("nil kubeClient") + } + // first create an ingress controller const ( YesOption = "Yes" @@ -591,6 +662,9 @@ func EnsureIngressController(ctx context.Context, kubeClient kubernetes.Interfac if len(list.Items) == 1 { secret := list.Items[0] originalSecret := secret.DeepCopy() + if secret.Labels == nil { + secret.Labels = map[string]string{} + } secret.Labels["loft.sh/app"] = "true" if secret.Annotations == nil { secret.Annotations = map[string]string{} @@ -719,7 +793,14 @@ func getHelmWorkdir(chartName string) (string, error) { // Makes sure that admin user and password secret exists // Returns (true, nil) if everything is correct but password is different from parameter `password` -func EnsureAdminPassword(ctx context.Context, kubeClient kubernetes.Interface, restConfig *rest.Config, password string, log log.Logger) (bool, error) { +func EnsureAdminPassword(ctx context.Context, kubeClient kubernetes.Interface, restConfig *rest.Config, namespace, password string, log log.Logger) (bool, error) { + if restConfig == nil { + return false, errors.New("nil kubeClient") + } + if kubeClient == nil { + return false, errors.New("nil kubeClient") + } + loftClient, err := loftclientset.NewForConfig(restConfig) if err != nil { return false, err @@ -740,7 +821,7 @@ func EnsureAdminPassword(ctx context.Context, kubeClient kubernetes.Interface, r Groups: []string{"system:masters"}, PasswordRef: &storagev1.SecretRef{ SecretName: "loft-user-secret-admin", - SecretNamespace: "loft", + SecretNamespace: namespace, Key: "password", }, }, diff --git a/vendor/github.com/loft-sh/vcluster/pkg/platform/helper.go b/vendor/github.com/loft-sh/vcluster/pkg/platform/helper.go index f4da8b49..27744848 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/platform/helper.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/platform/helper.go @@ -448,7 +448,7 @@ func SelectProjectCluster(ctx context.Context, client Client, project *managemen return "", err } - anyClusterOption := "Any Cluster [Loft Selects Cluster]" + anyClusterOption := "Any cluster [The platform will select a cluster for you]" clusterNames := []string{} for _, allowedCluster := range project.Spec.AllowedClusters { if allowedCluster.Name == "*" { diff --git a/vendor/github.com/loft-sh/vcluster/pkg/server/cert/cert.go b/vendor/github.com/loft-sh/vcluster/pkg/server/cert/cert.go index db318aa4..c6f3383c 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/server/cert/cert.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/server/cert/cert.go @@ -11,7 +11,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" ) -func GenServingCerts(caCertFile, caKeyFile string, currentCert, currentKey []byte, clusterDomain string, SANs []string) ([]byte, []byte, bool, error) { +func GenServingCerts(caCertFile, caKeyFile string, currentCert, currentKey []byte, clusterDomain, ingressHost string, SANs []string) ([]byte, []byte, bool, error) { regen := false commonName := "kube-apiserver" extKeyUsage := []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} @@ -23,6 +23,9 @@ func GenServingCerts(caCertFile, caKeyFile string, currentCert, currentKey []byt "kubernetes", "localhost", } + if ingressHost != "" { + dnsNames = append(dnsNames, ingressHost) + } altNames := &certhelper.AltNames{ DNSNames: dnsNames, diff --git a/vendor/github.com/loft-sh/vcluster/pkg/server/cert/syncer.go b/vendor/github.com/loft-sh/vcluster/pkg/server/cert/syncer.go index 65019789..f78b694f 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/server/cert/syncer.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/server/cert/syncer.go @@ -37,6 +37,8 @@ func NewSyncer(_ context.Context, currentNamespace string, currentNamespaceClien return &syncer{ clusterDomain: options.Networking.Advanced.ClusterDomain, + ingressHost: options.ControlPlane.Ingress.Host, + serverCaKey: options.VirtualClusterKubeConfig().ServerCAKey, serverCaCert: options.VirtualClusterKubeConfig().ServerCACert, @@ -54,6 +56,8 @@ func NewSyncer(_ context.Context, currentNamespace string, currentNamespaceClien type syncer struct { clusterDomain string + ingressHost string + serverCaCert string serverCaKey string @@ -210,7 +214,7 @@ func (s *syncer) regen(extraSANs []string) error { klog.Infof("Generating serving cert for service ips: %v", extraSANs) // GenServingCerts will write generated or updated cert/key to s.currentCert, s.currentKey - cert, key, _, err := GenServingCerts(s.serverCaCert, s.serverCaKey, s.currentCert, s.currentKey, s.clusterDomain, extraSANs) + cert, key, _, err := GenServingCerts(s.serverCaCert, s.serverCaKey, s.currentCert, s.currentKey, s.clusterDomain, s.ingressHost, extraSANs) if err != nil { return err } diff --git a/vendor/github.com/loft-sh/vcluster/pkg/setup/controller_context.go b/vendor/github.com/loft-sh/vcluster/pkg/setup/controller_context.go index cee6e84a..471f97c5 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/setup/controller_context.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/setup/controller_context.go @@ -280,7 +280,7 @@ func initControllerContext( return nil, errors.Wrap(err, "get virtual cluster version") } nodes.FakeNodesVersion = virtualClusterVersion.GitVersion - klog.Infof("Can connect to virtual cluster with version " + virtualClusterVersion.GitVersion) + klog.Info("Can connect to virtual cluster with version " + virtualClusterVersion.GitVersion) // create a new current namespace client currentNamespaceClient, err := newCurrentNamespaceClient(ctx, localManager, vClusterOptions) diff --git a/vendor/github.com/loft-sh/vcluster/pkg/upgrade/upgrade.go b/vendor/github.com/loft-sh/vcluster/pkg/upgrade/upgrade.go index 676162e5..5c3ee158 100644 --- a/vendor/github.com/loft-sh/vcluster/pkg/upgrade/upgrade.go +++ b/vendor/github.com/loft-sh/vcluster/pkg/upgrade/upgrade.go @@ -78,7 +78,8 @@ func CheckForNewerVersion() (string, error) { } v := semver.MustParse(version) - if !found || latest.Version.Equals(v) { + // if latest not found or latest version found is less than or equal to the current version, do not upgrade + if !found || latest.Version.Compare(v) != 1 { return } diff --git a/vendor/modules.txt b/vendor/modules.txt index 2e916530..7c79fa02 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -363,7 +363,7 @@ github.com/loft-sh/utils/pkg/command github.com/loft-sh/utils/pkg/downloader github.com/loft-sh/utils/pkg/downloader/commands github.com/loft-sh/utils/pkg/extract -# github.com/loft-sh/vcluster v0.20.0 +# github.com/loft-sh/vcluster v0.20.1 ## explicit; go 1.22.4 github.com/loft-sh/vcluster/cmd/vclusterctl/cmd github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/convert