Skip to content

Commit

Permalink
fix: configmap & multi-namespace mode
Browse files Browse the repository at this point in the history
  • Loading branch information
FabianKramm committed Apr 5, 2024
1 parent 6e911b8 commit ca602d6
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 41 deletions.
46 changes: 34 additions & 12 deletions pkg/controllers/resources/configmaps/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,40 +23,62 @@ import (

func New(ctx *synccontext.RegisterContext) (syncer.Object, error) {
t := translator.NewNamespacedTranslator(ctx, "configmap", &corev1.ConfigMap{})
t.SetNameTranslator(ConfigMapNameTranslator)

return &configMapSyncer{
NamespacedTranslator: t,

syncAllConfigMaps: ctx.Config.Sync.ToHost.ConfigMaps.All,
syncAllConfigMaps: ctx.Config.Sync.ToHost.ConfigMaps.All,
multiNamespaceMode: ctx.Config.Experimental.MultiNamespaceMode.Enabled,
}, nil
}

type configMapSyncer struct {
translator.NamespacedTranslator

syncAllConfigMaps bool
syncAllConfigMaps bool
multiNamespaceMode bool
}

func ConfigMapNameTranslator(vNN types.NamespacedName, _ client.Object) string {
name := translate.Default.PhysicalName(vNN.Name, vNN.Namespace)
if name == "kube-root-ca.crt" {
name = translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName)
var _ syncer.IndicesRegisterer = &configMapSyncer{}

func (s *configMapSyncer) VirtualToHost(ctx context.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName {
if s.multiNamespaceMode && req.Name == "kube-root-ca.crt" {
return types.NamespacedName{
Name: translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName),
Namespace: s.NamespacedTranslator.VirtualToHost(ctx, req, vObj).Namespace,
}
}
return name

return s.NamespacedTranslator.VirtualToHost(ctx, req, vObj)
}

var _ syncer.IndicesRegisterer = &configMapSyncer{}
func (s *configMapSyncer) HostToVirtual(ctx context.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName {
if s.multiNamespaceMode && req.Name == translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName) {
return types.NamespacedName{
Name: "kube-root-ca.crt",
Namespace: s.NamespacedTranslator.HostToVirtual(ctx, req, pObj).Namespace,
}
}

return s.NamespacedTranslator.HostToVirtual(ctx, req, pObj)
}

func (s *configMapSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error {
err := s.NamespacedTranslator.RegisterIndices(ctx)
err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.ConfigMap{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string {
if s.multiNamespaceMode && rawObj.GetName() == "kube-root-ca.crt" {
return []string{translate.Default.PhysicalNamespace(rawObj.GetNamespace()) + "/" + translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName)}
}

return []string{translate.Default.PhysicalNamespace(rawObj.GetNamespace()) + "/" + translate.Default.PhysicalName(rawObj.GetName(), rawObj.GetNamespace())}
})
if err != nil {
return err
}

// index pods by their used config maps
return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Pod{}, constants.IndexByConfigMap, func(rawObj client.Object) []string {
pod := rawObj.(*corev1.Pod)
return ConfigNamesFromPod(pod)
return configNamesFromPod(pod)
})
}

Expand Down Expand Up @@ -128,7 +150,7 @@ func mapPods(_ context.Context, obj client.Object) []reconcile.Request {
}

requests := []reconcile.Request{}
names := ConfigNamesFromPod(pod)
names := configNamesFromPod(pod)
for _, name := range names {
splitted := strings.Split(name, "/")
if len(splitted) == 2 {
Expand Down
5 changes: 4 additions & 1 deletion pkg/controllers/resources/configmaps/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import (
"github.com/loft-sh/vcluster/pkg/controllers/syncer/translator"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func (s *configMapSyncer) translate(ctx context.Context, vObj client.Object) *corev1.ConfigMap {
return s.TranslateMetadata(ctx, vObj).(*corev1.ConfigMap)
pObj := s.TranslateMetadata(ctx, vObj).(*corev1.ConfigMap)
pObj.SetName(s.VirtualToHost(ctx, types.NamespacedName{Name: vObj.GetName(), Namespace: vObj.GetNamespace()}, vObj).Name)
return pObj
}

func (s *configMapSyncer) translateUpdate(ctx context.Context, pObj, vObj *corev1.ConfigMap) *corev1.ConfigMap {
Expand Down
12 changes: 6 additions & 6 deletions pkg/controllers/resources/configmaps/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import (
corev1 "k8s.io/api/core/v1"
)

func ConfigNamesFromPod(pod *corev1.Pod) []string {
func configNamesFromPod(pod *corev1.Pod) []string {
configMaps := []string{}
for _, c := range pod.Spec.Containers {
configMaps = append(configMaps, ConfigNamesFromContainer(pod.Namespace, &c)...)
configMaps = append(configMaps, configNamesFromContainer(pod.Namespace, &c)...)
}
for _, c := range pod.Spec.InitContainers {
configMaps = append(configMaps, ConfigNamesFromContainer(pod.Namespace, &c)...)
configMaps = append(configMaps, configNamesFromContainer(pod.Namespace, &c)...)
}
for _, c := range pod.Spec.EphemeralContainers {
configMaps = append(configMaps, ConfigNamesFromEphemeralContainer(pod.Namespace, &c)...)
configMaps = append(configMaps, configNamesFromEphemeralContainer(pod.Namespace, &c)...)
}
for i := range pod.Spec.Volumes {
if pod.Spec.Volumes[i].ConfigMap != nil {
Expand All @@ -31,7 +31,7 @@ func ConfigNamesFromPod(pod *corev1.Pod) []string {
return translate.UniqueSlice(configMaps)
}

func ConfigNamesFromContainer(namespace string, container *corev1.Container) []string {
func configNamesFromContainer(namespace string, container *corev1.Container) []string {
configNames := []string{}
for _, env := range container.Env {
if env.ValueFrom != nil && env.ValueFrom.ConfigMapKeyRef != nil && env.ValueFrom.ConfigMapKeyRef.Name != "" {
Expand All @@ -46,7 +46,7 @@ func ConfigNamesFromContainer(namespace string, container *corev1.Container) []s
return configNames
}

func ConfigNamesFromEphemeralContainer(namespace string, container *corev1.EphemeralContainer) []string {
func configNamesFromEphemeralContainer(namespace string, container *corev1.EphemeralContainer) []string {
configNames := []string{}
for _, env := range container.Env {
if env.ValueFrom != nil && env.ValueFrom.ConfigMapKeyRef != nil && env.ValueFrom.ConfigMapKeyRef.Name != "" {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/resources/pods/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ func (s *podSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj
// translate services to environment variables
serviceEnv := translatepods.ServicesToEnvironmentVariables(vPod.Spec.EnableServiceLinks, ptrServiceList, kubeIP)
for i := range vPod.Spec.EphemeralContainers {
envVar, envFrom := translatepods.ContainerEnv(vPod.Spec.EphemeralContainers[i].Env, vPod.Spec.EphemeralContainers[i].EnvFrom, vPod, serviceEnv)
envVar, envFrom := s.podTranslator.TranslateContainerEnv(vPod.Spec.EphemeralContainers[i].Env, vPod.Spec.EphemeralContainers[i].EnvFrom, vPod, serviceEnv)
vPod.Spec.EphemeralContainers[i].Env = envVar
vPod.Spec.EphemeralContainers[i].EnvFrom = envFrom
}
Expand Down
28 changes: 20 additions & 8 deletions pkg/controllers/resources/pods/translate/translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"strconv"
"strings"

"github.com/loft-sh/vcluster/pkg/controllers/resources/configmaps"
"github.com/loft-sh/vcluster/pkg/controllers/resources/priorityclasses"
synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context"
"github.com/loft-sh/vcluster/pkg/util/loghelper"
Expand All @@ -22,7 +21,6 @@ import (
authenticationv1 "k8s.io/api/authentication/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/record"
Expand Down Expand Up @@ -55,6 +53,8 @@ var (
type Translator interface {
Translate(ctx context.Context, vPod *corev1.Pod, services []*corev1.Service, dnsIP string, kubeIP string) (*corev1.Pod, error)
Diff(ctx context.Context, vPod, pPod *corev1.Pod) (*corev1.Pod, error)

TranslateContainerEnv(envVar []corev1.EnvVar, envFrom []corev1.EnvFromSource, vPod *corev1.Pod, serviceEnvMap map[string]string) ([]corev1.EnvVar, []corev1.EnvFromSource)
}

func NewTranslator(ctx *synccontext.RegisterContext, eventRecorder record.EventRecorder) (Translator, error) {
Expand All @@ -79,6 +79,8 @@ func NewTranslator(ctx *synccontext.RegisterContext, eventRecorder record.EventR

defaultImageRegistry: ctx.Config.ControlPlane.Advanced.DefaultImageRegistry,

multiNamespaceMode: ctx.Config.Experimental.MultiNamespaceMode.Enabled,

serviceAccountSecretsEnabled: ctx.Config.Sync.ToHost.Pods.UseSecretsForSATokens,
clusterDomain: ctx.Config.Networking.Advanced.ClusterDomain,
serviceAccount: ctx.Config.ControlPlane.Advanced.WorkloadServiceAccount.Name,
Expand Down Expand Up @@ -107,6 +109,8 @@ type translator struct {

defaultImageRegistry string

multiNamespaceMode bool

// this is needed for host path mapper (legacy)
mountPhysicalHostPaths bool

Expand Down Expand Up @@ -268,23 +272,23 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [

// translate containers
for i := range pPod.Spec.Containers {
envVar, envFrom := ContainerEnv(pPod.Spec.Containers[i].Env, pPod.Spec.Containers[i].EnvFrom, vPod, serviceEnv)
envVar, envFrom := t.TranslateContainerEnv(pPod.Spec.Containers[i].Env, pPod.Spec.Containers[i].EnvFrom, vPod, serviceEnv)
pPod.Spec.Containers[i].Env = envVar
pPod.Spec.Containers[i].EnvFrom = envFrom
pPod.Spec.Containers[i].Image = t.imageTranslator.Translate(pPod.Spec.Containers[i].Image)
}

// translate init containers
for i := range pPod.Spec.InitContainers {
envVar, envFrom := ContainerEnv(pPod.Spec.InitContainers[i].Env, pPod.Spec.InitContainers[i].EnvFrom, vPod, serviceEnv)
envVar, envFrom := t.TranslateContainerEnv(pPod.Spec.InitContainers[i].Env, pPod.Spec.InitContainers[i].EnvFrom, vPod, serviceEnv)
pPod.Spec.InitContainers[i].Env = envVar
pPod.Spec.InitContainers[i].EnvFrom = envFrom
pPod.Spec.InitContainers[i].Image = t.imageTranslator.Translate(pPod.Spec.InitContainers[i].Image)
}

// translate ephemeral containers
for i := range pPod.Spec.EphemeralContainers {
envVar, envFrom := ContainerEnv(pPod.Spec.EphemeralContainers[i].Env, pPod.Spec.EphemeralContainers[i].EnvFrom, vPod, serviceEnv)
envVar, envFrom := t.TranslateContainerEnv(pPod.Spec.EphemeralContainers[i].Env, pPod.Spec.EphemeralContainers[i].EnvFrom, vPod, serviceEnv)
pPod.Spec.EphemeralContainers[i].Env = envVar
pPod.Spec.EphemeralContainers[i].EnvFrom = envFrom
pPod.Spec.EphemeralContainers[i].Image = t.imageTranslator.Translate(pPod.Spec.EphemeralContainers[i].Image)
Expand Down Expand Up @@ -352,7 +356,11 @@ func (t *translator) translateVolumes(ctx context.Context, pPod *corev1.Pod, vPo

for i := range pPod.Spec.Volumes {
if pPod.Spec.Volumes[i].ConfigMap != nil {
pPod.Spec.Volumes[i].ConfigMap.Name = configmaps.ConfigMapNameTranslator(types.NamespacedName{Name: pPod.Spec.Volumes[i].ConfigMap.Name, Namespace: vPod.Namespace}, nil)
if t.multiNamespaceMode && pPod.Spec.Volumes[i].ConfigMap.Name == "kube-root-ca.crt" {
pPod.Spec.Volumes[i].ConfigMap.Name = translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName)
} else {
pPod.Spec.Volumes[i].ConfigMap.Name = translate.Default.PhysicalName(pPod.Spec.Volumes[i].ConfigMap.Name, vPod.Namespace)
}
}
if pPod.Spec.Volumes[i].Secret != nil {
pPod.Spec.Volumes[i].Secret.SecretName = translate.Default.PhysicalName(pPod.Spec.Volumes[i].Secret.SecretName, vPod.Namespace)
Expand Down Expand Up @@ -575,7 +583,7 @@ func translateFieldRef(fieldSelector *corev1.ObjectFieldSelector) {
}
}

func ContainerEnv(envVar []corev1.EnvVar, envFrom []corev1.EnvFromSource, vPod *corev1.Pod, serviceEnvMap map[string]string) ([]corev1.EnvVar, []corev1.EnvFromSource) {
func (t *translator) TranslateContainerEnv(envVar []corev1.EnvVar, envFrom []corev1.EnvFromSource, vPod *corev1.Pod, serviceEnvMap map[string]string) ([]corev1.EnvVar, []corev1.EnvFromSource) {
envNameMap := make(map[string]struct{})
for j, env := range envVar {
translateDownwardAPI(&envVar[j])
Expand All @@ -590,7 +598,11 @@ func ContainerEnv(envVar []corev1.EnvVar, envFrom []corev1.EnvFromSource, vPod *
}
for j, from := range envFrom {
if from.ConfigMapRef != nil && from.ConfigMapRef.Name != "" {
envFrom[j].ConfigMapRef.Name = translate.Default.PhysicalName(from.ConfigMapRef.Name, vPod.Namespace)
if t.multiNamespaceMode && envFrom[j].ConfigMapRef.Name == "kube-root-ca.crt" {
envFrom[j].ConfigMapRef.Name = translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName)
} else {
envFrom[j].ConfigMapRef.Name = translate.Default.PhysicalName(from.ConfigMapRef.Name, vPod.Namespace)
}
}
if from.SecretRef != nil && from.SecretRef.Name != "" {
envFrom[j].SecretRef.Name = translate.Default.PhysicalName(from.SecretRef.Name, vPod.Namespace)
Expand Down
10 changes: 1 addition & 9 deletions pkg/controllers/syncer/translator/namespaced_translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ func NewNamespacedTranslator(ctx *context.RegisterContext, name string, obj clie
type namespacedTranslator struct {
name string

nameTranslator translate.PhysicalNamespacedNameTranslator
excludedAnnotations []string
syncedLabels []string

Expand All @@ -44,10 +43,6 @@ type namespacedTranslator struct {
eventRecorder record.EventRecorder
}

func (n *namespacedTranslator) SetNameTranslator(nameTranslator translate.PhysicalNamespacedNameTranslator) {
n.nameTranslator = nameTranslator
}

func (n *namespacedTranslator) EventRecorder() record.EventRecorder {
return n.eventRecorder
}
Expand Down Expand Up @@ -103,11 +98,8 @@ func (n *namespacedTranslator) IsManaged(_ context2.Context, pObj client.Object)
return translate.Default.IsManaged(pObj), nil
}

func (n *namespacedTranslator) VirtualToHost(_ context2.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName {
func (n *namespacedTranslator) VirtualToHost(_ context2.Context, req types.NamespacedName, _ client.Object) types.NamespacedName {
name := translate.Default.PhysicalName(req.Name, req.Namespace)
if n.nameTranslator != nil {
name = n.nameTranslator(req, vObj)
}

return types.NamespacedName{
Namespace: translate.Default.PhysicalNamespace(req.Namespace),
Expand Down
4 changes: 0 additions & 4 deletions pkg/controllers/syncer/translator/translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"

syncercontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context"
"github.com/loft-sh/vcluster/pkg/util/translate"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -56,7 +55,4 @@ type NamespacedTranslator interface {

// SyncToHostUpdate updates the given pObj (if not nil) in the target namespace
SyncToHostUpdate(ctx *syncercontext.SyncContext, vObj, pObj client.Object) (ctrl.Result, error)

// SetNameTranslator is a function to override default VirtualToHost name translation
SetNameTranslator(nameTranslator translate.PhysicalNamespacedNameTranslator)
}

0 comments on commit ca602d6

Please sign in to comment.