Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions chart/templates/config-configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{{- if not .Values.controlPlane.advanced.useConfigAsSecret }}
apiVersion: v1
kind: ConfigMap
metadata:
name: "vc-config-{{ .Release.Name }}"
namespace: {{ .Release.Namespace }}
labels:
app: vcluster
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
{{- if .Values.controlPlane.advanced.globalMetadata.annotations }}
annotations:
{{ toYaml .Values.controlPlane.advanced.globalMetadata.annotations | indent 4 }}
{{- end }}
data:
config.yaml: {{ .Values | toYaml | quote }}
{{- end }}
2 changes: 2 additions & 0 deletions chart/templates/config-secret.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{{- if .Values.controlPlane.advanced.useConfigAsSecret }}
apiVersion: v1
kind: Secret
metadata:
Expand All @@ -15,3 +16,4 @@ metadata:
type: Opaque
data:
config.yaml: {{ .Values | toYaml | b64enc | quote }}
{{- end }}
5 changes: 5 additions & 0 deletions chart/templates/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,13 @@ spec:
emptyDir: {}
{{- end }}
- name: vcluster-config
{{- if .Values.controlPlane.advanced.useConfigAsSecret }}
secret:
secretName: vc-config-{{ .Release.Name }}
{{- else }}
configMap:
name: vc-config-{{ .Release.Name }}
{{- end }}
{{- if .Values.controlPlane.statefulSet.persistence.dataVolume }}
{{ toYaml .Values.controlPlane.statefulSet.persistence.dataVolume | indent 8 }}
{{- else if not (include "vcluster.persistence.volumeClaim.enabled" .) }}
Expand Down
38 changes: 38 additions & 0 deletions chart/tests/config-configmap_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
suite: test config-configmap
templates:
- config-configmap.yaml
- config-secret.yaml
- statefulset.yaml
release:
name: release-name
namespace: test-namespace
tests:
- it: should create a ConfigMap and not a Secret when useConfigAsSecret is false
set:
controlPlane.advanced.useConfigAsSecret: false
asserts:
- hasDocuments:
count: 1
template: config-configmap.yaml
- hasDocuments:
count: 0
template: config-secret.yaml
- matchRegex:
path: spec.template.spec.volumes[?(@.name=="vcluster-config")].configMap.name
pattern: vc-config-release-name
template: statefulset.yaml

- it: should create a Secret and not a ConfigMap when useConfigAsSecret is true
set:
controlPlane.advanced.useConfigAsSecret: true
asserts:
- hasDocuments:
count: 0
template: config-configmap.yaml
- hasDocuments:
count: 1
template: config-secret.yaml
- matchRegex:
path: spec.template.spec.volumes[?(@.name=="vcluster-config")].secret.secretName
pattern: vc-config-release-name
template: statefulset.yaml
6 changes: 5 additions & 1 deletion chart/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,10 @@
"type": "string",
"description": "DefaultImageRegistry will be used as a prefix for all internal images deployed by vCluster or Helm. This makes it easy to\nupload all required vCluster images to a single private repository and set this value. Workload images are not affected by this."
},
"useConfigAsSecret": {
"type": "boolean",
"description": "useConfigAsSecret defines if a Secret should be used instead of a ConfigMap for storing the vCluster configuration."
},
"virtualScheduler": {
"$ref": "#/$defs/EnableSwitch",
"description": "VirtualScheduler defines if a scheduler should be used within the virtual cluster or the scheduling decision for workloads will be made by the host cluster.\nDeprecated: Use ControlPlane.Distro.K8S.Scheduler instead."
Expand Down Expand Up @@ -4882,4 +4886,4 @@
"additionalProperties": false,
"type": "object",
"description": "Config is the vCluster config."
}
}
2 changes: 2 additions & 0 deletions chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,8 @@ controlPlane:
# DefaultImageRegistry will be used as a prefix for all internal images deployed by vCluster or Helm. This makes it easy to
# upload all required vCluster images to a single private repository and set this value. Workload images are not affected by this.
defaultImageRegistry: ""
# UseConfigAsSecret defines if a Secret should be used instead of a ConfigMap for storing the vCluster configuration.
useConfigAsSecret: false
# VirtualScheduler defines if a scheduler should be used within the virtual cluster or the scheduling decision for workloads will be made by the host cluster.
# Deprecated: Use ControlPlane.Distro.K8S.Scheduler instead.
virtualScheduler:
Expand Down
3 changes: 3 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2096,6 +2096,9 @@ type ControlPlaneAdvanced struct {

// GlobalMetadata is metadata that will be added to all resources deployed by Helm.
GlobalMetadata ControlPlaneGlobalMetadata `json:"globalMetadata,omitempty"`

// UseConfigAsSecret defines if a Secret should be used instead of a ConfigMap for storing the vCluster configuration.
UseConfigAsSecret bool `json:"useConfigAsSecret,omitempty"`
}

type Registry struct {
Expand Down
39 changes: 4 additions & 35 deletions pkg/cli/create_helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/loft-sh/vcluster/pkg/helm"
"github.com/loft-sh/vcluster/pkg/platform"
platformclihelper "github.com/loft-sh/vcluster/pkg/platform/clihelper"
"github.com/loft-sh/vcluster/pkg/setup"
"github.com/loft-sh/vcluster/pkg/snapshot"
"github.com/loft-sh/vcluster/pkg/snapshot/pod"
"github.com/loft-sh/vcluster/pkg/telemetry"
Expand Down Expand Up @@ -240,8 +241,9 @@ func CreateHelm(ctx context.Context, options *CreateOptions, globalFlags *flags.
return err
}
} else {
// When a vCluster is not legacy, there should be a config secret and we will fetch the values from the secret
currentVClusterConfig, err = getConfigfileFromSecret(ctx, vClusterName, cmd.Namespace)
// When a vCluster is not legacy, there should be a config secret or configmap and we will fetch the values from the secret or configmap
kConf := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(clientcmd.NewDefaultClientConfigLoadingRules(), &clientcmd.ConfigOverrides{})
currentVClusterConfig, err = setup.GetVClusterConfig(ctx, kConf, vClusterName, cmd.Namespace)
if err != nil {
return err
}
Expand Down Expand Up @@ -962,36 +964,3 @@ func (cmd *createHelm) getVClusterConfigFromSnapshot(ctx context.Context) (strin

return "", nil
}

func getConfigfileFromSecret(ctx context.Context, name, namespace string) (*config.Config, error) {
secretName := "vc-config-" + name

kConf := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(clientcmd.NewDefaultClientConfigLoadingRules(), &clientcmd.ConfigOverrides{})
clientConfig, err := kConf.ClientConfig()
if err != nil {
return nil, err
}

clientset, err := kubernetes.NewForConfig(clientConfig)
if err != nil {
return nil, err
}

secret, err := clientset.CoreV1().Secrets(namespace).Get(ctx, secretName, metav1.GetOptions{})
if err != nil {
return nil, err
}

configBytes, ok := secret.Data["config.yaml"]
if !ok {
return nil, fmt.Errorf("secret %s in namespace %s does not contain the expected 'config.yaml' field", secretName, namespace)
}

config := config.Config{}
err = yaml.Unmarshal(configBytes, &config)
if err != nil {
return nil, err
}

return &config, nil
}
29 changes: 6 additions & 23 deletions pkg/cli/describe_helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package cli
import (
"context"
"encoding/json"
"fmt"
"io"
"strings"

Expand All @@ -12,8 +11,7 @@ import (
"github.com/loft-sh/vcluster/config"
"github.com/loft-sh/vcluster/pkg/cli/find"
"github.com/loft-sh/vcluster/pkg/cli/flags"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"github.com/loft-sh/vcluster/pkg/setup"
"k8s.io/client-go/tools/clientcmd"
)

Expand All @@ -35,33 +33,23 @@ func DescribeHelm(ctx context.Context, flags *flags.GlobalFlags, output io.Write
namespace = flags.Namespace
}

secretName := "vc-config-" + name

kConf := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(clientcmd.NewDefaultClientConfigLoadingRules(), &clientcmd.ConfigOverrides{})
rawConfig, err := kConf.RawConfig()
if err != nil {
return err
}
clientConfig, err := kConf.ClientConfig()
if err != nil {
return err
}

clientset, err := kubernetes.NewForConfig(clientConfig)
vclusterConfig, err := setup.GetVClusterConfig(ctx, kConf, name, namespace)
if err != nil {
return err
}

secret, err := clientset.CoreV1().Secrets(namespace).Get(ctx, secretName, v1.GetOptions{})
// Convert config to bytes for YAML/JSON output formats
configBytes, err := yaml.Marshal(vclusterConfig)
if err != nil {
return err
}

configBytes, ok := secret.Data["config.yaml"]
if !ok {
return fmt.Errorf("secret %s in namespace %s does not contain the expected 'config.yaml' field", secretName, namespace)
}

switch format {
case "yaml":
_, err = output.Write(configBytes)
Expand All @@ -80,7 +68,7 @@ func DescribeHelm(ctx context.Context, flags *flags.GlobalFlags, output io.Write
}

describeOutput := &DescribeOutput{}
err = extractFromValues(describeOutput, configBytes, format, fVcluster.Version, output)
err = extractFromValues(describeOutput, configBytes, vclusterConfig, format, fVcluster.Version, output)
if err != nil {
return err
}
Expand All @@ -96,12 +84,7 @@ func DescribeHelm(ctx context.Context, flags *flags.GlobalFlags, output io.Write
return err
}

func extractFromValues(d *DescribeOutput, configBytes []byte, format, version string, output io.Writer) error {
conf := &config.Config{}
err := yaml.Unmarshal(configBytes, conf)
if err != nil {
return err
}
func extractFromValues(d *DescribeOutput, configBytes []byte, conf *config.Config, format, version string, output io.Writer) error {

switch format {
case "yaml":
Expand Down
10 changes: 9 additions & 1 deletion pkg/cli/describe_platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/ghodss/yaml"
"github.com/loft-sh/log"
"github.com/loft-sh/vcluster/config"
"github.com/loft-sh/vcluster/pkg/cli/flags"
"github.com/loft-sh/vcluster/pkg/platform"
)
Expand Down Expand Up @@ -43,7 +44,14 @@ func DescribePlatform(ctx context.Context, globalFlags *flags.GlobalFlags, outpu

describeOutput.Version = version

err = extractFromValues(describeOutput, []byte(values), format, version, output)
// Parse config first
vclusterConfig := &config.Config{}
err = yaml.Unmarshal([]byte(values), vclusterConfig)
if err != nil {
return err
}

err = extractFromValues(describeOutput, []byte(values), vclusterConfig, format, version, output)
if err != nil {
return err
}
Expand Down
29 changes: 15 additions & 14 deletions pkg/cli/find/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/loft-sh/vcluster/pkg/platform"
"github.com/loft-sh/vcluster/pkg/platform/kube"
"github.com/loft-sh/vcluster/pkg/platform/sleepmode"
"github.com/loft-sh/vcluster/pkg/util/confighelper"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/discovery"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -469,10 +470,10 @@ func getVCluster(ctx context.Context, object client.Object, context, release str

if status == "" {
// Workload sleepmode cannot modify/annotate the VirtualClusterInstance, StatefulSet, or Deployment so it
// sets a sleep type on the config secret. Check that here.
sec, err := getConfigSecret(ctx, client, kubeClientConfig, namespace, release)
// sets a sleep type on the config secret or configmap. Check that here.
annotations, err := getConfigResource(ctx, client, kubeClientConfig, namespace, release)
if err == nil {
if _, ok := sec.Annotations[clusterv1.SleepModeSleepTypeAnnotation]; ok {
if _, ok := annotations[clusterv1.SleepModeSleepTypeAnnotation]; ok {
status = string(StatusWorkloadSleeping)
}
}
Expand Down Expand Up @@ -548,22 +549,22 @@ func getPods(ctx context.Context, client kube.Interface, kubeClientConfig client
return podList, nil
}

func getConfigSecret(ctx context.Context, client kube.Interface, kubeClientConfig clientcmd.ClientConfig, namespace, releaseName string) (*corev1.Secret, error) {
func getConfigResource(ctx context.Context, client kube.Interface, kubeClientConfig clientcmd.ClientConfig, namespace, releaseName string) (map[string]string, error) {
ctx, cancel := context.WithTimeout(ctx, time.Second*30)
defer cancel()

secret, err := client.CoreV1().Secrets(namespace).Get(ctx, "vc-config-"+releaseName, metav1.GetOptions{})
if err != nil {
if kerrors.IsForbidden(err) {
// try the current namespace instead
if namespace, err = getAccessibleNS(kubeClientConfig); err != nil {
return nil, err
}
return client.CoreV1().Secrets(namespace).Get(ctx, releaseName, metav1.GetOptions{})
ann, err := confighelper.GetResourceAnnotations(ctx, client, releaseName, namespace)
if err == nil {
return ann, nil
}

if kerrors.IsForbidden(err) {
// try the current namespace instead
if namespace, err = getAccessibleNS(kubeClientConfig); err == nil {
return confighelper.GetResourceAnnotations(ctx, client, releaseName, namespace)
}
return nil, err
}
return secret, nil
return nil, err
}

func getDeployments(ctx context.Context, client kube.Interface, namespace string, kubeClientConfig clientcmd.ClientConfig, timeout time.Duration) (*appsv1.DeploymentList, error) {
Expand Down
Loading