diff --git a/lib/resourceapply/core.go b/lib/resourceapply/core.go index fb482296a7..4ef14aa10a 100644 --- a/lib/resourceapply/core.go +++ b/lib/resourceapply/core.go @@ -46,3 +46,94 @@ func ApplySecret(client coreclientv1.SecretsGetter, required *corev1.Secret) (*c actual, err := client.Secrets(required.Namespace).Update(existing) return actual, true, err } + +// ApplyConfigMap merges objectmeta, requires data +func ApplyConfigMap(client coreclientv1.ConfigMapsGetter, required *corev1.ConfigMap) (*corev1.ConfigMap, bool, error) { + existing, err := client.ConfigMaps(required.Namespace).Get(required.Name, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + actual, err := client.ConfigMaps(required.Namespace).Create(required) + return actual, true, err + } + if err != nil { + return nil, false, err + } + + modified := resourcemerge.BoolPtr(false) + existingCopy := existing.DeepCopy() + + resourcemerge.EnsureObjectMeta(modified, &existingCopy.ObjectMeta, required.ObjectMeta) + + var modifiedKeys []string + for existingCopyKey, existingCopyValue := range existingCopy.Data { + if requiredValue, ok := required.Data[existingCopyKey]; !ok || (existingCopyValue != requiredValue) { + modifiedKeys = append(modifiedKeys, "data."+existingCopyKey) + } + } + for requiredKey := range required.Data { + if _, ok := existingCopy.Data[requiredKey]; !ok { + modifiedKeys = append(modifiedKeys, "data."+requiredKey) + } + } + + dataSame := len(modifiedKeys) == 0 + if dataSame && !*modified { + return existingCopy, false, nil + } + existingCopy.Data = required.Data + + actual, err := client.ConfigMaps(required.Namespace).Update(existingCopy) + + return actual, true, err +} + +// SyncConfigMap syncs ConfigMap opjectmeta from source namespace to destination +func SyncConfigMap(client coreclientv1.ConfigMapsGetter, sourceNamespace, sourceName, targetNamespace, targetName string, ownerRefs []metav1.OwnerReference) (*corev1.ConfigMap, bool, error) { + source, err := client.ConfigMaps(sourceNamespace).Get(sourceName, metav1.GetOptions{}) + sourceCopy := source.DeepCopy() + + switch { + case apierrors.IsNotFound(err): + deleteErr := client.ConfigMaps(targetNamespace).Delete(targetName, nil) + if apierrors.IsNotFound(deleteErr) { + return nil, false, nil + } + if deleteErr == nil { + return nil, true, nil + } + return nil, false, deleteErr + case err != nil: + return nil, false, err + default: + sourceCopy.Namespace = targetNamespace + sourceCopy.Name = targetName + sourceCopy.ResourceVersion = "" + sourceCopy.OwnerReferences = ownerRefs + return ApplyConfigMap(client, sourceCopy) + } +} + +// SyncConfigMap syncs Secret opjectmeta from source namespace to destination +func SyncSecret(client coreclientv1.SecretsGetter, sourceNamespace, sourceName, targetNamespace, targetName string, ownerRefs []metav1.OwnerReference) (*corev1.Secret, bool, error) { + source, err := client.Secrets(sourceNamespace).Get(sourceName, metav1.GetOptions{}) + sourceCopy := source.DeepCopy() + + switch { + case apierrors.IsNotFound(err): + deleteErr := client.Secrets(targetNamespace).Delete(targetName, nil) + if apierrors.IsNotFound(deleteErr) { + return nil, false, nil + } + if deleteErr == nil { + return nil, true, nil + } + return nil, false, deleteErr + case err != nil: + return nil, false, err + default: + sourceCopy.Namespace = targetNamespace + sourceCopy.Name = targetName + sourceCopy.ResourceVersion = "" + sourceCopy.OwnerReferences = ownerRefs + return ApplySecret(client, sourceCopy) + } +} diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go index fb6a65504e..c65ddecc87 100644 --- a/pkg/operator/operator.go +++ b/pkg/operator/operator.go @@ -337,6 +337,7 @@ func (optr *Operator) sync(key string) error { {"mcs", optr.syncMachineConfigServer}, {"mcd", optr.syncMachineConfigDaemon}, {"required-pools", optr.syncRequiredMachineConfigPools}, + {"required-resources", optr.syncRequiredMachineConfigResources}, } return optr.syncAll(rc, syncFuncs) } diff --git a/pkg/operator/sync.go b/pkg/operator/sync.go index f02e5c9c32..c884809116 100644 --- a/pkg/operator/sync.go +++ b/pkg/operator/sync.go @@ -334,6 +334,35 @@ func (optr *Operator) syncRequiredMachineConfigPools(config renderConfig) error return nil } +// syncRequiredMachineConfigResources ensures that the ConfigMap and Secret resources are synced from source namespace to destination. +func (optr *Operator) syncRequiredMachineConfigResources(config renderConfig) error { + sourceNamespace := "openshift-config" + destinationNamespace := "kube-system" + + _, _, err := resourceapply.SyncConfigMap( + optr.kubeClient.CoreV1(), + sourceNamespace, + "etcd-metric-serving-ca", + destinationNamespace, + "etcd-metric-serving-ca", + []metav1.OwnerReference{}) + if err != nil { + return err + } + + _, _, errs := resourceapply.SyncSecret( + optr.kubeClient.CoreV1(), + sourceNamespace, + "etcd-metric-client", + destinationNamespace, + "etcd-metric-client", + []metav1.OwnerReference{}) + if errs != nil { + return errs + } + return nil +} + const ( deploymentRolloutPollInterval = time.Second deploymentRolloutTimeout = 10 * time.Minute