Skip to content

Commit

Permalink
feat: Added bi-directional annotation and label syncing
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasK33 committed Oct 10, 2024
1 parent 10b84e2 commit 6276b26
Show file tree
Hide file tree
Showing 23 changed files with 139 additions and 98 deletions.
39 changes: 16 additions & 23 deletions pkg/controllers/resources/configmaps/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,8 @@ func (s *configMapSyncer) ModifyController(ctx *synccontext.RegisterContext, bui
}

func (s *configMapSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[*corev1.ConfigMap]) (ctrl.Result, error) {
createNeeded, err := s.isConfigMapUsed(ctx, event.Virtual)
if err != nil {
return ctrl.Result{}, err
} else if !createNeeded {
createNeeded := s.isConfigMapUsed(ctx, event.Virtual)
if !createNeeded {
return ctrl.Result{}, nil
}

Expand All @@ -72,7 +70,7 @@ func (s *configMapSyncer) SyncToHost(ctx *synccontext.SyncContext, event *syncco
}

pObj := translate.HostMetadata(event.Virtual, s.VirtualToHost(ctx, types.NamespacedName{Name: event.Virtual.Name, Namespace: event.Virtual.Namespace}, event.Virtual))
err = pro.ApplyPatchesHostObject(ctx, nil, pObj, event.Virtual, ctx.Config.Sync.ToHost.ConfigMaps.Patches)
err := pro.ApplyPatchesHostObject(ctx, nil, pObj, event.Virtual, ctx.Config.Sync.ToHost.ConfigMaps.Patches)
if err != nil {
return ctrl.Result{}, err
}
Expand All @@ -87,14 +85,12 @@ func (s *configMapSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *syn
}

vObj := translate.VirtualMetadata(event.Host, s.HostToVirtual(ctx, types.NamespacedName{Name: event.Host.Name, Namespace: event.Host.Namespace}, event.Host))
createNeeded, err := s.isConfigMapUsed(ctx, vObj)
if err != nil {
return ctrl.Result{}, err
} else if !createNeeded {
createNeeded := s.isConfigMapUsed(ctx, vObj)
if !createNeeded {
return ctrl.Result{}, nil
}

err = pro.ApplyPatchesVirtualObject(ctx, nil, vObj, event.Host, ctx.Config.Sync.ToHost.ConfigMaps.Patches)
err := pro.ApplyPatchesVirtualObject(ctx, nil, vObj, event.Host, ctx.Config.Sync.ToHost.ConfigMaps.Patches)
if err != nil {
return ctrl.Result{}, err
}
Expand All @@ -103,12 +99,10 @@ func (s *configMapSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *syn
}

func (s *configMapSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*corev1.ConfigMap]) (_ ctrl.Result, retErr error) {
used, err := s.isConfigMapUsed(ctx, event.Virtual)
if err != nil {
return ctrl.Result{}, err
} else if !used {
used := s.isConfigMapUsed(ctx, event.Virtual)
if !used {
ctx.Log.Infof("delete physical config map %s/%s, because it is not used anymore", event.Host.GetNamespace(), event.Host.GetName())
err = ctx.PhysicalClient.Delete(ctx, event.Host)
err := ctx.PhysicalClient.Delete(ctx, event.Host)
if err != nil {
ctx.Log.Infof("error deleting physical object %s/%s in physical cluster: %v", event.Host.GetNamespace(), event.Host.GetName(), err)
return ctrl.Result{}, err
Expand All @@ -131,13 +125,12 @@ func (s *configMapSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.
}
}()

// check annotations & labels
event.Host.Annotations = translate.HostAnnotations(event.Virtual, event.Host)

// check labels
// bi-directional sync of annotations and labels
if event.Source == synccontext.SyncEventSourceHost {
event.Virtual.Annotations = translate.VirtualAnnotations(event.Host, event.Virtual)
event.Virtual.Labels = translate.VirtualLabels(event.Host, event.Virtual)
} else {
event.Host.Annotations = translate.HostAnnotations(event.Virtual, event.Host)
event.Host.Labels = translate.HostLabels(event.Virtual, event.Host)
}

Expand All @@ -147,11 +140,11 @@ func (s *configMapSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.
return ctrl.Result{}, nil
}

func (s *configMapSyncer) isConfigMapUsed(ctx *synccontext.SyncContext, vObj *corev1.ConfigMap) (bool, error) {
func (s *configMapSyncer) isConfigMapUsed(ctx *synccontext.SyncContext, vObj *corev1.ConfigMap) bool {
if vObj.Annotations[constants.SyncResourceAnnotation] == "true" {
return true, nil
return true
} else if ctx.Config.Sync.ToHost.ConfigMaps.All {
return true, nil
return true
}

// retrieve references for config map
Expand All @@ -163,5 +156,5 @@ func (s *configMapSyncer) isConfigMapUsed(ctx *synccontext.SyncContext, vObj *co
},
})

return len(references) > 0, nil
return len(references) > 0
}
2 changes: 1 addition & 1 deletion pkg/controllers/resources/csistoragecapacities/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func (s *csistoragecapacitySyncer) enqueuePhysical(ctx *synccontext.SyncContext,
return
}

name := s.Mapper.HostToVirtual(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj)
name := s.HostToVirtual(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj)
if name.Name != "" && name.Namespace != "" {
q.Add(reconcile.Request{NamespacedName: name})
}
Expand Down
8 changes: 8 additions & 0 deletions pkg/controllers/resources/endpoints/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ func (s *endpointsSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.
return ctrl.Result{}, err
}

if event.Source == synccontext.SyncEventSourceHost {
event.Virtual.Annotations = translate.VirtualAnnotations(event.Host, event.Virtual, s.excludedAnnotations...)
event.Virtual.Labels = translate.VirtualLabels(event.Host, event.Virtual)
} else {
event.Host.Annotations = translate.HostAnnotations(event.Virtual, event.Host, s.excludedAnnotations...)
event.Host.Labels = translate.HostLabels(event.Virtual, event.Host)
}

return ctrl.Result{}, nil
}

Expand Down
3 changes: 0 additions & 3 deletions pkg/controllers/resources/endpoints/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,5 @@ func (s *endpointsSyncer) translateUpdate(ctx *synccontext.SyncContext, pObj, vO
s.translateSpec(ctx, translated)
pObj.Subsets = translated.Subsets

// check annotations & labels
pObj.Annotations = translate.HostAnnotations(vObj, pObj, s.excludedAnnotations...)
pObj.Labels = translate.HostLabels(vObj, pObj)
return nil
}
2 changes: 1 addition & 1 deletion pkg/controllers/resources/ingresses/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (s *ingressSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.Sy

event.TargetObject().Spec.IngressClassName = event.SourceObject().Spec.IngressClassName
event.Virtual.Status = event.Host.Status
s.translateUpdate(ctx, event.Host, event.Virtual)
s.translateUpdate(ctx, event.Source, event.Host, event.Virtual)
return ctrl.Result{}, nil
}

Expand Down
15 changes: 10 additions & 5 deletions pkg/controllers/resources/ingresses/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,18 @@ func (s *ingressSyncer) TranslateMetadataUpdate(ctx *synccontext.SyncContext, vO
return translate.HostAnnotations(vIngress, pObj), translate.HostLabels(vIngress, pObj)
}

func (s *ingressSyncer) translateUpdate(ctx *synccontext.SyncContext, pObj, vObj *networkingv1.Ingress) {
func (s *ingressSyncer) translateUpdate(ctx *synccontext.SyncContext, source synccontext.SyncEventSource, pObj, vObj *networkingv1.Ingress) {
pObj.Spec = *translateSpec(ctx, vObj.Namespace, &vObj.Spec)

var translatedAnnotations map[string]string
translatedAnnotations, pObj.Labels = s.TranslateMetadataUpdate(ctx, vObj, pObj)
translatedAnnotations, _ = resources.TranslateIngressAnnotations(ctx, translatedAnnotations, vObj.Namespace)
pObj.Annotations = translatedAnnotations
if source == synccontext.SyncEventSourceHost {
vObj.Annotations = translate.VirtualAnnotations(pObj, vObj)
vObj.Labels = translate.VirtualLabels(pObj, vObj)
} else {
var translatedAnnotations map[string]string
translatedAnnotations, pObj.Labels = s.TranslateMetadataUpdate(ctx, vObj, pObj)
translatedAnnotations, _ = resources.TranslateIngressAnnotations(ctx, translatedAnnotations, vObj.Namespace)
pObj.Annotations = translatedAnnotations
}
}

func translateSpec(ctx *synccontext.SyncContext, namespace string, vIngressSpec *networkingv1.IngressSpec) *networkingv1.IngressSpec {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/resources/namespaces/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ type namespaceSyncer struct {
var _ syncertypes.Syncer = &namespaceSyncer{}

func (s *namespaceSyncer) Syncer() syncertypes.Sync[client.Object] {
return syncer.ToGenericSyncer[*corev1.Namespace](s)
return syncer.ToGenericSyncer(s)
}

func (s *namespaceSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[*corev1.Namespace]) (ctrl.Result, error) {
Expand Down
9 changes: 9 additions & 0 deletions pkg/controllers/resources/networkpolicies/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ func (s *networkPolicySyncer) Sync(ctx *synccontext.SyncContext, event *synccont
}()

s.translateUpdate(event.Host, event.Virtual)

if event.Source == synccontext.SyncEventSourceHost {
event.Virtual.Annotations = translate.VirtualAnnotations(event.Host, event.Virtual)
event.Virtual.Labels = translate.VirtualLabels(event.Host, event.Virtual)
} else {
event.Host.Annotations = translate.HostAnnotations(event.Virtual, event.Host)
event.Host.Labels = translate.HostLabels(event.Virtual, event.Host)
}

return ctrl.Result{}, nil
}

Expand Down
3 changes: 0 additions & 3 deletions pkg/controllers/resources/networkpolicies/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ func (s *networkPolicySyncer) translateUpdate(pObj, vObj *networkingv1.NetworkPo
if translatedSpec := translateSpec(&vObj.Spec, vObj.GetNamespace()); translatedSpec != nil {
pObj.Spec = *translatedSpec
}

pObj.Annotations = translate.HostAnnotations(vObj, pObj)
pObj.Labels = translate.HostLabels(vObj, pObj)
}

func translateSpec(spec *networkingv1.NetworkPolicySpec, namespace string) *networkingv1.NetworkPolicySpec {
Expand Down
9 changes: 2 additions & 7 deletions pkg/controllers/resources/persistentvolumeclaims/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,17 +171,12 @@ func (s *persistentVolumeClaimSyncer) Sync(ctx *synccontext.SyncContext, event *
// allow storage size to be increased
event.Host.Spec.Resources.Requests = event.Virtual.Spec.Resources.Requests

// change annotations
// bi-directional sync of annotations and labels
if event.Source == synccontext.SyncEventSourceHost {
event.Virtual.Annotations = translate.VirtualAnnotations(event.Host, event.Virtual, s.excludedAnnotations...)
} else {
event.Host.Annotations = translate.HostAnnotations(event.Virtual, event.Host, s.excludedAnnotations...)
}

// check labels
if event.Source == synccontext.SyncEventSourceHost {
event.Virtual.Labels = translate.VirtualLabels(event.Host, event.Virtual)
} else {
event.Host.Annotations = translate.HostAnnotations(event.Virtual, event.Host, s.excludedAnnotations...)
event.Host.Labels = translate.HostLabels(event.Virtual, event.Host)
}

Expand Down
14 changes: 7 additions & 7 deletions pkg/controllers/resources/persistentvolumeclaims/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,18 @@ import (
"k8s.io/apimachinery/pkg/types"
)

var (
deprecatedStorageClassAnnotation = "volume.beta.kubernetes.io/storage-class"
)
var deprecatedStorageClassAnnotation = "volume.beta.kubernetes.io/storage-class"

func (s *persistentVolumeClaimSyncer) translate(ctx *synccontext.SyncContext, vPvc *corev1.PersistentVolumeClaim) (*corev1.PersistentVolumeClaim, error) {
pPVC := translate.HostMetadata(vPvc, s.VirtualToHost(ctx, types.NamespacedName{Name: vPvc.GetName(), Namespace: vPvc.GetNamespace()}, vPvc), s.excludedAnnotations...)
s.translateSelector(ctx, pPVC)

if vPvc.Annotations[constants.SkipTranslationAnnotation] != "true" {
if pPVC.Spec.DataSource != nil {
if pPVC.Spec.DataSource.Kind == "VolumeSnapshot" {
switch pPVC.Spec.DataSource.Kind {
case "VolumeSnapshot":
pPVC.Spec.DataSource.Name = mappings.VirtualToHostName(ctx, pPVC.Spec.DataSource.Name, vPvc.Namespace, mappings.VolumeSnapshots())
} else if pPVC.Spec.DataSource.Kind == "PersistentVolumeClaim" {
case "PersistentVolumeClaim":
pPVC.Spec.DataSource.Name = mappings.VirtualToHostName(ctx, pPVC.Spec.DataSource.Name, vPvc.Namespace, mappings.PersistentVolumeClaims())
}
}
Expand All @@ -34,9 +33,10 @@ func (s *persistentVolumeClaimSyncer) translate(ctx *synccontext.SyncContext, vP
namespace = *pPVC.Spec.DataSourceRef.Namespace
}

if pPVC.Spec.DataSourceRef.Kind == "VolumeSnapshot" {
switch pPVC.Spec.DataSourceRef.Kind {
case "VolumeSnapshot":
pPVC.Spec.DataSourceRef.Name = mappings.VirtualToHostName(ctx, pPVC.Spec.DataSourceRef.Name, namespace, mappings.VolumeSnapshots())
} else if pPVC.Spec.DataSourceRef.Kind == "PersistentVolumeClaim" {
case "PersistentVolumeClaim":
pPVC.Spec.DataSourceRef.Name = mappings.VirtualToHostName(ctx, pPVC.Spec.DataSourceRef.Name, namespace, mappings.PersistentVolumeClaims())
}
}
Expand Down
9 changes: 8 additions & 1 deletion pkg/controllers/resources/persistentvolumes/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (s *persistentVolumeSyncer) Sync(ctx *synccontext.SyncContext, event *syncc
if event.Virtual.GetDeletionTimestamp() != nil {
if event.Host.GetDeletionTimestamp() == nil {
// check if the PV is dynamically provisioned and the reclaim policy is Delete
if !(event.Virtual.Spec.ClaimRef != nil && event.Virtual.Spec.PersistentVolumeReclaimPolicy == corev1.PersistentVolumeReclaimDelete) {
if event.Virtual.Spec.ClaimRef == nil || event.Virtual.Spec.PersistentVolumeReclaimPolicy != corev1.PersistentVolumeReclaimDelete {
ctx.Log.Infof("delete physical persistent volume %s, because virtual persistent volume is deleted", event.Host.GetName())
err := ctx.PhysicalClient.Delete(ctx, event.Host)
if err != nil {
Expand Down Expand Up @@ -212,6 +212,13 @@ func (s *persistentVolumeSyncer) Sync(ctx *synccontext.SyncContext, event *syncc
if event.Virtual.Annotations[constants.HostClusterPersistentVolumeAnnotation] == "" {
// TODO: translate the storage secrets
event.Host.Spec.StorageClassName = mappings.VirtualToHostName(ctx, event.Virtual.Spec.StorageClassName, "", mappings.StorageClasses())
}

// bi-directional sync of annotations and labels
if event.Source == synccontext.SyncEventSourceHost {
event.Virtual.Annotations = translate.VirtualAnnotations(event.Host, event.Virtual, s.excludedAnnotations...)
event.Virtual.Labels = translate.VirtualLabels(event.Host, event.Virtual)
} else {
event.Host.Annotations = translate.HostAnnotations(event.Virtual, event.Host, s.excludedAnnotations...)
event.Host.Labels = translate.HostLabels(event.Virtual, event.Host)
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/controllers/resources/poddisruptionbudgets/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,15 @@ func (s *pdbSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEv
}()

s.translateUpdate(event.Host, event.Virtual)

if event.Source == synccontext.SyncEventSourceHost {
event.Virtual.Annotations = translate.VirtualAnnotations(event.Host, event.Virtual)
event.Virtual.Labels = translate.VirtualLabels(event.Host, event.Virtual)
} else {
event.Host.Annotations = translate.HostAnnotations(event.Virtual, event.Host)
event.Host.Labels = translate.HostLabels(event.Virtual, event.Host)
}

return ctrl.Result{}, nil
}

Expand Down
2 changes: 0 additions & 2 deletions pkg/controllers/resources/poddisruptionbudgets/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ func (s *pdbSyncer) translate(ctx *synccontext.SyncContext, vObj *policyv1.PodDi
}

func (s *pdbSyncer) translateUpdate(pObj, vObj *policyv1.PodDisruptionBudget) {
pObj.Annotations = translate.HostAnnotations(vObj, pObj)
pObj.Labels = translate.HostLabels(vObj, pObj)
pObj.Spec.MaxUnavailable = vObj.Spec.MaxUnavailable
pObj.Spec.MinAvailable = vObj.Spec.MinAvailable
pObj.Spec.Selector = translate.HostLabelSelector(vObj.Spec.Selector)
Expand Down
48 changes: 25 additions & 23 deletions pkg/controllers/resources/pods/translate/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,19 @@ func (t *translator) Diff(ctx *synccontext.SyncContext, event *synccontext.SyncE

// get Namespace resource in order to have access to its labels
vNamespace := &corev1.Namespace{}
err := t.vClient.Get(ctx, client.ObjectKey{Name: vPod.ObjectMeta.GetNamespace()}, vNamespace)
err := t.vClient.Get(ctx, client.ObjectKey{Name: vPod.GetNamespace()}, vNamespace)
if err != nil {
return err
}

// spec diff
t.calcSpecDiff(pPod, vPod)

// check pod and namespace labels
if event.Source == synccontext.SyncEventSourceHost {
switch event.Source {
case synccontext.SyncEventSourceHost:
vPod.Labels = translate.VirtualLabels(pPod, vPod)
} else {
vPod.Annotations = translate.VirtualAnnotations(pPod, vPod, GetExcludedAnnotations(pPod)...)
case synccontext.SyncEventSourceVirtual:
updatedLabels := translate.HostLabels(vPod, pPod)
if updatedLabels == nil {
updatedLabels = map[string]string{}
Expand All @@ -43,31 +44,32 @@ func (t *translator) Diff(ctx *synccontext.SyncContext, event *synccontext.SyncE
updatedLabels[translate.HostLabelNamespace(k)] = v
}
pPod.Labels = updatedLabels
}

// check annotations
updatedAnnotations := translate.HostAnnotations(vPod, pPod, GetExcludedAnnotations(pPod)...)
if updatedAnnotations == nil {
updatedAnnotations = map[string]string{}
}
// check annotations
updatedAnnotations := translate.HostAnnotations(vPod, pPod, GetExcludedAnnotations(pPod)...)
if updatedAnnotations == nil {
updatedAnnotations = map[string]string{}
}

// set owner references
updatedAnnotations[VClusterLabelsAnnotation] = LabelsAnnotation(vPod)
if len(vPod.OwnerReferences) > 0 {
ownerReferencesData, _ := json.Marshal(vPod.OwnerReferences)
updatedAnnotations[OwnerReferences] = string(ownerReferencesData)
for _, ownerReference := range vPod.OwnerReferences {
if ownerReference.APIVersion == appsv1.SchemeGroupVersion.String() && canAnnotateOwnerSetKind(ownerReference.Kind) {
updatedAnnotations[OwnerSetKind] = ownerReference.Kind
break
// set owner references
updatedAnnotations[VClusterLabelsAnnotation] = LabelsAnnotation(vPod)
if len(vPod.OwnerReferences) > 0 {
ownerReferencesData, _ := json.Marshal(vPod.OwnerReferences)
updatedAnnotations[OwnerReferences] = string(ownerReferencesData)
for _, ownerReference := range vPod.OwnerReferences {
if ownerReference.APIVersion == appsv1.SchemeGroupVersion.String() && canAnnotateOwnerSetKind(ownerReference.Kind) {
updatedAnnotations[OwnerSetKind] = ownerReference.Kind
break
}
}
} else {
delete(updatedAnnotations, OwnerReferences)
delete(updatedAnnotations, OwnerSetKind)
}
} else {
delete(updatedAnnotations, OwnerReferences)
delete(updatedAnnotations, OwnerSetKind)

pPod.Annotations = updatedAnnotations
}

pPod.Annotations = updatedAnnotations
return nil
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/controllers/resources/runtimeclasses/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ func (i *runtimeClassSyncer) Sync(ctx *synccontext.SyncContext, event *syncconte
}
}()

event.Virtual.Annotations = event.Host.Annotations
event.Virtual.Labels = event.Host.Labels
event.Virtual.Annotations = translate.VirtualAnnotations(event.Host, event.Virtual)
event.Virtual.Labels = translate.VirtualLabels(event.Host, event.Virtual)
event.Virtual.Handler = event.Host.Handler
event.Virtual.Overhead = event.Host.Overhead
event.Virtual.Scheduling = event.Host.Scheduling
Expand Down
Loading

0 comments on commit 6276b26

Please sign in to comment.