Skip to content
Merged
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
21 changes: 20 additions & 1 deletion hypershift-operator/controllers/nodepool/nto.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ func (r *NodePoolReconciler) reconcileMirroredConfigs(ctx context.Context, logr
Name: supportutil.ShortenName(mirroredConfig.Name, nodePool.Name, validation.LabelValueMaxLength),
Namespace: controlPlaneNamespace},
}
if err := r.deleteImmutableConfigMapIfNeeded(ctx, logr, cm, nodePool.Name); err != nil {
return err
}
cm.SetResourceVersion("")
if result, err := r.CreateOrUpdate(ctx, r.Client, cm, func() error {
return mutateMirroredConfig(cm, mirroredConfig, nodePool)
}); err != nil {
Expand Down Expand Up @@ -190,7 +194,7 @@ func reconcilePerformanceProfileConfigMap(performanceProfileConfigMap *corev1.Co
}

func mutateMirroredConfig(cm *corev1.ConfigMap, mirroredConfig *MirrorConfig, nodePool *hyperv1.NodePool) error {
cm.Immutable = ptr.To(true)
cm.Immutable = ptr.To(false)
if cm.Annotations == nil {
cm.Annotations = make(map[string]string)
}
Expand All @@ -204,6 +208,21 @@ func mutateMirroredConfig(cm *corev1.ConfigMap, mirroredConfig *MirrorConfig, no
return nil
}

func (r *NodePoolReconciler) deleteImmutableConfigMapIfNeeded(ctx context.Context, log logr.Logger, cm *corev1.ConfigMap, nodePoolName string) error {
_, err := supportutil.DeleteIfNeededWithPredicate(ctx, r.Client, cm, func(existing *corev1.ConfigMap) bool {
if existing.Labels[NTOMirroredConfigLabel] != "true" || existing.Labels[hyperv1.NodePoolLabel] != nodePoolName {
return false
}
if existing.Immutable != nil && *existing.Immutable {
log.Info("deleting immutable mirrored ConfigMap to recreate as mutable",
"configMap", client.ObjectKeyFromObject(existing).String())
return true
}
return false
})
return err
}

func (r *NodePoolReconciler) getTuningConfig(ctx context.Context,
nodePool *hyperv1.NodePool,
) (string, string, string, error) {
Expand Down
169 changes: 167 additions & 2 deletions hypershift-operator/controllers/nodepool/nto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ func TestReconcileMirroredConfigs(t *testing.T) {
existingConfigsInHcpNs: nil,
expectedMirroredConfigs: []corev1.ConfigMap{
{
Immutable: ptr.To(true),
Immutable: ptr.To(false),
ObjectMeta: metav1.ObjectMeta{
Name: supportutil.ShortenName("foo", npName, validation.LabelValueMaxLength),
Namespace: hcpNamespace,
Expand Down Expand Up @@ -602,7 +602,7 @@ func TestReconcileMirroredConfigs(t *testing.T) {
},
expectedMirroredConfigs: []corev1.ConfigMap{
{
Immutable: ptr.To(true),
Immutable: ptr.To(false),
ObjectMeta: metav1.ObjectMeta{
Name: supportutil.ShortenName("foo", npName, validation.LabelValueMaxLength),
Namespace: hcpNamespace,
Expand Down Expand Up @@ -652,6 +652,44 @@ func TestReconcileMirroredConfigs(t *testing.T) {
existingConfigsInHcpNs: nil,
expectedMirroredConfigs: []corev1.ConfigMap{
{
Immutable: ptr.To(false),
ObjectMeta: metav1.ObjectMeta{
Name: supportutil.ShortenName("bar", npName, validation.LabelValueMaxLength),
Namespace: hcpNamespace,
Labels: map[string]string{
NTOMirroredConfigLabel: "true",
nodePoolAnnotation: npName,
KubeletConfigConfigMapLabel: "true",
},
},
Data: map[string]string{
TokenSecretConfigKey: kubeletConfig1,
},
},
},
},
{
name: "When an immutable mirrored ConfigMap exists and data changes, it should delete and recreate as mutable",
nodePool: np,
controlPlaneNamespace: hcpNamespace,
configsToBeMirrored: []*MirrorConfig{
{
ConfigMap: &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Namespace: npNamespace,
},
Data: map[string]string{
TokenSecretConfigKey: kubeletConfig1,
},
},
Labels: map[string]string{
KubeletConfigConfigMapLabel: "true",
},
},
},
existingConfigsInHcpNs: []client.Object{
&corev1.ConfigMap{
Immutable: ptr.To(true),
ObjectMeta: metav1.ObjectMeta{
Name: supportutil.ShortenName("bar", npName, validation.LabelValueMaxLength),
Expand All @@ -662,6 +700,133 @@ func TestReconcileMirroredConfigs(t *testing.T) {
KubeletConfigConfigMapLabel: "true",
},
},
Data: map[string]string{
TokenSecretConfigKey: "old-data",
},
},
},
expectedMirroredConfigs: []corev1.ConfigMap{
{
Immutable: ptr.To(false),
ObjectMeta: metav1.ObjectMeta{
Name: supportutil.ShortenName("bar", npName, validation.LabelValueMaxLength),
Namespace: hcpNamespace,
Labels: map[string]string{
NTOMirroredConfigLabel: "true",
nodePoolAnnotation: npName,
KubeletConfigConfigMapLabel: "true",
},
},
Data: map[string]string{
TokenSecretConfigKey: kubeletConfig1,
},
},
},
},
{
name: "When an immutable mirrored ConfigMap belongs to a different NodePool, it should not be deleted",
nodePool: np,
controlPlaneNamespace: hcpNamespace,
configsToBeMirrored: []*MirrorConfig{
{
ConfigMap: &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Namespace: npNamespace,
},
Data: map[string]string{
TokenSecretConfigKey: kubeletConfig1,
},
},
Labels: map[string]string{
KubeletConfigConfigMapLabel: "true",
},
},
},
existingConfigsInHcpNs: []client.Object{
&corev1.ConfigMap{
Immutable: ptr.To(true),
ObjectMeta: metav1.ObjectMeta{
Name: supportutil.ShortenName("bar", npName, validation.LabelValueMaxLength),
Namespace: hcpNamespace,
Labels: map[string]string{
NTOMirroredConfigLabel: "true",
nodePoolAnnotation: "other-nodepool",
KubeletConfigConfigMapLabel: "true",
},
},
Data: map[string]string{
TokenSecretConfigKey: "old-data",
},
},
},
expectedMirroredConfigs: []corev1.ConfigMap{
{
Immutable: ptr.To(false),
ObjectMeta: metav1.ObjectMeta{
Name: supportutil.ShortenName("bar", npName, validation.LabelValueMaxLength),
Namespace: hcpNamespace,
Labels: map[string]string{
NTOMirroredConfigLabel: "true",
nodePoolAnnotation: npName,
KubeletConfigConfigMapLabel: "true",
},
},
Data: map[string]string{
TokenSecretConfigKey: kubeletConfig1,
},
},
},
},
{
name: "When an existing mirrored ConfigMap is already mutable, it should not be deleted",
nodePool: np,
controlPlaneNamespace: hcpNamespace,
configsToBeMirrored: []*MirrorConfig{
{
ConfigMap: &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Namespace: npNamespace,
},
Data: map[string]string{
TokenSecretConfigKey: kubeletConfig1,
},
},
Labels: map[string]string{
KubeletConfigConfigMapLabel: "true",
},
},
},
existingConfigsInHcpNs: []client.Object{
&corev1.ConfigMap{
Immutable: ptr.To(false),
ObjectMeta: metav1.ObjectMeta{
Name: supportutil.ShortenName("bar", npName, validation.LabelValueMaxLength),
Namespace: hcpNamespace,
Labels: map[string]string{
NTOMirroredConfigLabel: "true",
nodePoolAnnotation: npName,
KubeletConfigConfigMapLabel: "true",
},
},
Data: map[string]string{
TokenSecretConfigKey: "old-data",
},
},
},
expectedMirroredConfigs: []corev1.ConfigMap{
{
Immutable: ptr.To(false),
ObjectMeta: metav1.ObjectMeta{
Name: supportutil.ShortenName("bar", npName, validation.LabelValueMaxLength),
Namespace: hcpNamespace,
Labels: map[string]string{
NTOMirroredConfigLabel: "true",
nodePoolAnnotation: npName,
KubeletConfigConfigMapLabel: "true",
},
},
Data: map[string]string{
TokenSecretConfigKey: kubeletConfig1,
},
Expand Down