From cc03ca62be9d64ea4d210fb7b4fee0ae356029c2 Mon Sep 17 00:00:00 2001
From: Slavi Pantaleev <slavi@devture.com>
Date: Tue, 6 Aug 2024 13:38:51 +0300
Subject: [PATCH] Avoid empty "supersede domain-name-servers" directives for
 dhclient.conf (#10948)

Fixes https://github.com/kubernetes-sigs/kubespray/issues/10947

This patch aims to be minimal and intentionally:

- does not change the generation logic for `supersede_domain` and `supersede_search`
- does not change how `nameserverentries` (for NetworkManager) is built

It seems like `nameserverentries` in the "Generate nameservers for resolvconf, including cluster DNS"
task is built the same way as `dhclient_supersede_nameserver_entries_list`.
However, `nameserverentries` in the "Generate nameservers for resolvconf, not including cluster DNS"
task (below) is built differently for some reason. It includes `configured_nameservers` as well.
Due to these differences, I have refrained from reusing the same building logic
(`dhclient_supersede_nameserver_entries_list`) for both.

If the `configured_nameservers` addition can be removed or made to apply
to dhclient as well, we could potentially build a single list and then
generate the `nameserverentries` and `supersede_nameserver` strings from it.
---
 .../preinstall/tasks/0020-set_facts.yml           | 15 +++++++++++----
 .../preinstall/tasks/0100-dhclient-hooks.yml      |  2 +-
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/roles/kubernetes/preinstall/tasks/0020-set_facts.yml b/roles/kubernetes/preinstall/tasks/0020-set_facts.yml
index 4541c14c5..ea0b8849f 100644
--- a/roles/kubernetes/preinstall/tasks/0020-set_facts.yml
+++ b/roles/kubernetes/preinstall/tasks/0020-set_facts.yml
@@ -185,8 +185,8 @@
   set_fact:
     nameserverentries: |-
       {{ (([nodelocaldns_ip] if enable_nodelocaldns else []) + (coredns_server | d([]) if not enable_nodelocaldns else []) + nameservers | d([]) + cloud_resolver | d([]) + (configured_nameservers | d([]) if not disable_host_nameservers | d() | bool else [])) | unique | join(',') }}
-    supersede_nameserver:
-      supersede domain-name-servers {{ (([nodelocaldns_ip] if enable_nodelocaldns else []) + (coredns_server | d([]) if not enable_nodelocaldns else []) + nameservers | d([]) + cloud_resolver | d([]) + (configured_nameservers | d([]) if not disable_host_nameservers | d() | bool else [])) | unique | join(', ') }};
+    dhclient_supersede_nameserver_entries_list: |-
+      {{ (([nodelocaldns_ip] if enable_nodelocaldns else []) + (coredns_server | d([]) if not enable_nodelocaldns else []) + nameservers | d([]) + cloud_resolver | d([]) + (configured_nameservers | d([]) if not disable_host_nameservers | d() | bool else [])) | unique }}
   when: not dns_early or dns_late
 
 # This task should run instead of the above task when cluster/nodelocal DNS hasn't
@@ -195,10 +195,17 @@
   set_fact:
     nameserverentries: |-
       {{ (nameservers | d([]) + cloud_resolver | d([]) + configured_nameservers | d([])) | unique | join(',') }}
-    supersede_nameserver:
-      supersede domain-name-servers {{ (nameservers | d([]) + cloud_resolver | d([])) | unique | join(', ') }};
+    dhclient_supersede_nameserver_entries_list: |-
+      {{ (nameservers | d([]) + cloud_resolver | d([])) | unique }}
   when: dns_early and not dns_late
 
+- name: Generate supersede_nameserver from dhclient_supersede_nameserver_entries_list
+  set_fact:
+    supersede_nameserver: |-
+      {%- if dhclient_supersede_nameserver_entries_list | length > 0 -%}
+      supersede domain-name-servers {{ dhclient_supersede_nameserver_entries_list | join(', ') }};
+      {%- endif -%}
+
 - name: Set etcd vars if using kubeadm mode
   set_fact:
     etcd_cert_dir: "{{ kube_cert_dir }}"
diff --git a/roles/kubernetes/preinstall/tasks/0100-dhclient-hooks.yml b/roles/kubernetes/preinstall/tasks/0100-dhclient-hooks.yml
index 480edc86b..6276034d3 100644
--- a/roles/kubernetes/preinstall/tasks/0100-dhclient-hooks.yml
+++ b/roles/kubernetes/preinstall/tasks/0100-dhclient-hooks.yml
@@ -2,7 +2,7 @@
 - name: Configure dhclient to supersede search/domain/nameservers
   blockinfile:
     block: |-
-      {% for item in [supersede_domain, supersede_search, supersede_nameserver] -%}
+      {% for item in [supersede_domain, supersede_search, supersede_nameserver] | reject('equalto', '') -%}
       {{ item }}
       {% endfor %}
     path: "{{ dhclientconffile }}"
-- 
GitLab