Repository: containous/maesh
Pull request #710 (2020-08-21 14:44:03)

Always update CoreDNS deployment in prepare phase
## What does this PR do?

This PR:
- Checks if the corefile has changed before updating the coredns deployment

### How to test it

* make test


Patch:
diff --git a/pkg/dns/dns.go b/pkg/dns/dns.go
index 7e9b9a4..f813a64 100644
--- a/pkg/dns/dns.go
+++ b/pkg/dns/dns.go
@@ -29,8 +29,9 @@ const (
 	CoreDNS
 	KubeDNS
 
-	coreFileHeader  = "#### Begin Maesh Block"
-	coreFileTrailer = "#### End Maesh Block"
+	maeshBlockHeader  = "#### Begin Maesh Block"
+	maeshBlockTrailer = "#### End Maesh Block"
+	maeshDomain       = "maesh"
 )
 
 var versionCoreDNS17 = goversion.Must(goversion.NewVersion("1.7"))
@@ -135,11 +136,15 @@ func (c *Client) ConfigureCoreDNS(ctx context.Context, coreDNSNamespace, cluster
 
 	c.logger.Debug("Patching CoreDNS ConfigMap")
 
-	patchedConfigMap, err := c.patchCoreDNSConfig(ctx, coreDNSDeployment, clusterDomain, maeshNamespace)
+	patchedConfigMap, changed, err := c.patchCoreDNSConfig(ctx, coreDNSDeployment, clusterDomain, maeshNamespace)
 	if err != nil {
 		return fmt.Errorf("unable to patch coredns config: %w", err)
 	}
 
+	if !changed {
+		return nil
+	}
+
 	if _, err = c.kubeClient.CoreV1().ConfigMaps(patchedConfigMap.Namespace).Update(ctx, patchedConfigMap, metav1.UpdateOptions{}); err != nil {
 		return err
 	}
@@ -151,10 +156,10 @@ func (c *Client) ConfigureCoreDNS(ctx context.Context, coreDNSNamespace, cluster
 	return nil
 }
 
-func (c *Client) patchCoreDNSConfig(ctx context.Context, deployment *appsv1.Deployment, clusterDomain, maeshNamespace string) (*corev1.ConfigMap, error) {
+func (c *Client) patchCoreDNSConfig(ctx context.Context, deployment *appsv1.Deployment, clusterDomain, maeshNamespace string) (*corev1.ConfigMap, bool, error) {
 	coreDNSVersion, err := c.getCoreDNSVersion(deployment)
 	if err != nil {
-		return nil, err
+		return nil, false, err
 	}
 
 	customConfigMap, err := c.getConfigMap(ctx, deployment, "coredns-custom")
@@ -162,74 +167,38 @@ func (c *Client) patchCoreDNSConfig(ctx context.Context, deployment *appsv1.Depl
 	// For AKS the CoreDNS config have to be added to the coredns-custom ConfigMap.
 	// See https://docs.microsoft.com/en-us/azure/aks/coredns-custom
 	if err == nil {
-		customConfigMap.Data["maesh.server"] = c.addMaeshStubDomain(
+		corefile, changed := addStubDomain(
+			customConfigMap.Data["maesh.server"],
+			maeshBlockHeader,
+			maeshBlockTrailer,
+			maeshDomain,
 			clusterDomain,
 			maeshNamespace,
-			"",
 			coreDNSVersion,
 		)
+		customConfigMap.Data["maesh.server"] = corefile
 
-		return customConfigMap, nil
+		return customConfigMap, changed, nil
 	}
 
 	coreDNSConfigMap, err := c.getConfigMap(ctx, deployment, "coredns")
 	if err != nil {
-		return nil, err
+		return nil, false, err
 	}
 
-	coreDNSConfigMap.Data["Corefile"] = c.addMaeshStubDomain(
+	corefile, changed := addStubDomain(
+		coreDNSConfigMap.Data["Corefile"],
+		maeshBlockHeader,
+		maeshBlockTrailer,
+		maeshDomain,
 		clusterDomain,
 		maeshNamespace,
-		coreDNSConfigMap.Data["Corefile"],
 		coreDNSVersion,
 	)
 
-	return coreDNSConfigMap, nil
-}
-
-func (c *Client) addMaeshStubDomain(clusterDomain, maeshNamespace, coreDNSConfig string, coreDNSVersion *goversion.Version) string {
-	// config already contains the maesh block.
-	if strings.Contains(coreDNSConfig, coreFileHeader) {
-		return coreDNSConfig
-	}
-
-	stubDomainFormat := `
-%[4]s
-maesh:53 {
-    errors
-    rewrite continue {
-        name regex ([a-zA-Z0-9-_]*)\.([a-zv0-9-_]*)\.maesh %[3]s-{1}-6d61657368-{2}.%[3]s.svc.%[1]s
-        answer name %[3]s-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\.%[3]s\.svc\.%[2]s {1}.{2}.maesh
-    }
-    kubernetes %[1]s in-addr.arpa ip6.arpa {
-        pods insecure
-        %[6]s
-        fallthrough in-addr.arpa ip6.arpa
-    }
-    forward . /etc/resolv.conf
-    cache 30
-    loop
-    reload
-    loadbalance
-}
-%[5]s
-`
-	upstream := ""
-
-	if coreDNSVersion.LessThan(versionCoreDNS17) {
-		upstream = "upstream"
-	}
+	coreDNSConfigMap.Data["Corefile"] = corefile
 
-	stubDomain := fmt.Sprintf(stubDomainFormat,
-		clusterDomain,
-		strings.Replace(clusterDomain, ".", "\\.", -1),
-		maeshNamespace,
-		coreFileHeader,
-		coreFileTrailer,
-		upstream,
-	)
-
-	return coreDNSConfig + stubDomain
+	return coreDNSConfigMap, changed, nil
 }
 
 func (c *Client) getCoreDNSVersion(deployment *appsv1.Deployment) (*goversion.Version, error) {
@@ -366,35 +335,26 @@ func (c *Client) RestoreCoreDNS(ctx context.Context) error {
 }
 
 func (c *Client) unpatchCoreDNSConfig(ctx context.Context, deployment *appsv1.Deployment) (*corev1.ConfigMap, error) {
-	customConfigMap, err := c.getConfigMap(ctx, deployment, "coredns-custom")
+	coreDNSConfigMap, err := c.getConfigMap(ctx, deployment, "coredns-custom")
 
 	// For AKS the CoreDNS config have to be removed from the coredns-custom ConfigMap.
 	// See https://docs.microsoft.com/en-us/azure/aks/coredns-custom
 	if err == nil {
-		delete(customConfigMap.Data, "maesh.server")
-		return customConfigMap, nil
+		delete(coreDNSConfigMap.Data, "maesh.server")
+
+		return coreDNSConfigMap, nil
 	}
 
-	coreDNSConfigMap, err := c.getConfigMap(ctx, deployment, "coredns")
+	coreDNSConfigMap, err = c.getConfigMap(ctx, deployment, "coredns")
 	if err != nil {
 		return nil, err
 	}
 
-	data := coreDNSConfigMap.Data["Corefile"]
-
-	// Split the data on the header, and save the pre-header data.
-	splitData := strings.SplitN(data, coreFileHeader+"\n", 2)
-	preData := splitData[0]
-
-	// Split the data on the trailer, and save the post-header data.
-	postData := ""
-	splitData = strings.SplitN(data, coreFileTrailer+"\n", 2)
-
-	if len(splitData) > 1 {
-		postData = splitData[1]
-	}
-
-	coreDNSConfigMap.Data["Corefile"] = preData + postData
+	coreDNSConfigMap.Data["Corefile"] = removeStubDomain(
+		coreDNSConfigMap.Data["Corefile"],
+		maeshBlockHeader,
+		maeshBlockTrailer,
+	)
 
 	return coreDNSConfigMap, nil
 }
@@ -511,3 +471,78 @@ func getConfigMapVolumeSource(deployment *appsv1.Deployment, name string) (*core
 
 	return nil, fmt.Errorf("configmap %q cannot be found", name)
 }
+
+func getStubDomain(config, blockHeader, blockTrailer string) string {
+	start := strings.Index(config, blockHeader)
+	end := strings.Index(config, blockTrailer)
+
+	if start == -1 || end == -1 {
+		return ""
+	}
+
+	return config[start : end+len(blockTrailer)]
+}
+
+func addStubDomain(config, blockHeader, blockTrailer, domain, clusterDomain, traefikMeshNamespace string, coreDNSVersion *goversion.Version) (string, bool) {
+	existingStubDomain := getStubDomain(config, blockHeader, blockTrailer)
+
+	if existingStubDomain != "" {
+		config = removeStubDomain(config, blockHeader, blockTrailer)
+	}
+
+	stubDomainFormat := `%[4]s
+%[7]s:53 {
+    errors
+    rewrite continue {
+        name regex ([a-zA-Z0-9-_]*)\.([a-zv0-9-_]*)\.%[7]s %[3]s-{1}-6d61657368-{2}.%[3]s.svc.%[1]s
+        answer name %[3]s-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\.%[3]s\.svc\.%[2]s {1}.{2}.%[7]s
+    }
+    kubernetes %[1]s in-addr.arpa ip6.arpa {
+        pods insecure
+        %[6]s
+        fallthrough in-addr.arpa ip6.arpa
+    }
+    forward . /etc/resolv.conf
+    cache 30
+    loop
+    reload
+    loadbalance
+}
+%[5]s`
+	upstream := ""
+
+	if coreDNSVersion.LessThan(versionCoreDNS17) {
+		upstream = "upstream"
+	}
+
+	stubDomain := fmt.Sprintf(stubDomainFormat,
+		clusterDomain,
+		strings.Replace(clusterDomain, ".", "\\.", -1),
+		traefikMeshNamespace,
+		blockHeader,
+		blockTrailer,
+		upstream,
+		domain,
+	)
+
+	return config + "\n" + stubDomain + "\n", existingStubDomain != stubDomain
+}
+
+func removeStubDomain(config, blockHeader, blockTrailer string) string {
+	if !strings.Contains(config, blockHeader) {
+		return config
+	}
+	// Split the data on the header, and save the pre-header data.
+	splitData := strings.SplitN(config, blockHeader+"\n", 2)
+	preData := splitData[0]
+
+	// Split the data on the trailer, and save the post-header data.
+	postData := ""
+
+	splitData = strings.SplitN(config, blockTrailer+"\n", 2)
+	if len(splitData) > 1 {
+		postData = splitData[1]
+	}
+
+	return preData + postData
+}


Test patch:
diff --git a/pkg/dns/dns_test.go b/pkg/dns/dns_test.go
index 6792309..fa80e9b 100644
--- a/pkg/dns/dns_test.go
+++ b/pkg/dns/dns_test.go
@@ -9,6 +9,7 @@ import (
 	"github.com/sirupsen/logrus"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
@@ -78,23 +79,27 @@ func TestConfigureCoreDNS(t *testing.T) {
 		expectedCorefile string
 		expectedCustom   string
 		expectedErr      bool
+		expectedRestart  bool
 	}{
 		{
 			desc:             "First time config of CoreDNS",
 			mockFile:         "configurecoredns_not_patched.yaml",
 			expectedErr:      false,
 			expectedCorefile: ".:53 {\n    errors\n    health {\n        lameduck 5s\n    }\n    ready\n    kubernetes {{ pillar['dns_domain'] }} in-addr.arpa ip6.arpa {\n        pods insecure\n        fallthrough in-addr.arpa ip6.arpa\n        ttl 30\n    }\n    prometheus :9153\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n\n#### Begin Maesh Block\nmaesh:53 {\n    errors\n    rewrite continue {\n        name regex ([a-zA-Z0-9-_]*)\\.([a-zv0-9-_]*)\\.maesh toto-{1}-6d61657368-{2}.toto.svc.titi\n        answer name toto-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\\.toto\\.svc\\.titi {1}.{2}.maesh\n    }\n    kubernetes titi in-addr.arpa ip6.arpa {\n        pods insecure\n        upstream\n        fallthrough in-addr.arpa ip6.arpa\n    }\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n#### End Maesh Block\n",
+			expectedRestart:  true,
 		},
 		{
 			desc:             "Already patched CoreDNS config",
 			mockFile:         "configurecoredns_already_patched.yaml",
 			expectedErr:      false,
 			expectedCorefile: ".:53 {\n        errors\n        health {\n            lameduck 5s\n        }\n        ready\n        kubernetes {{ pillar['dns_domain'] }} in-addr.arpa ip6.arpa {\n            pods insecure\n            fallthrough in-addr.arpa ip6.arpa\n            ttl 30\n        }\n        prometheus :9153\n        forward . /etc/resolv.conf\n        cache 30\n        loop\n        reload\n        loadbalance\n    }\n#### Begin Maesh Block\nmaesh:53 {\n    errors\n    rewrite continue {\n        name regex ([a-zA-Z0-9-_]*)\\.([a-zv0-9-_]*)\\.maesh toto-{1}-6d61657368-{2}.toto.svc.titi\n        answer name toto-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\\.toto\\.svc\\.titi {1}.{2}.maesh\n    }\n    kubernetes titi in-addr.arpa ip6.arpa {\n        pods insecure\n        upstream\n        fallthrough in-addr.arpa ip6.arpa\n    }\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n#### End Maesh Block\n",
+			expectedRestart:  false,
 		},
 		{
-			desc:        "Missing Corefile configmap",
-			mockFile:    "configurecoredns_missing_configmap.yaml",
-			expectedErr: true,
+			desc:            "Missing Corefile configmap",
+			mockFile:        "configurecoredns_missing_configmap.yaml",
+			expectedErr:     true,
+			expectedRestart: false,
 		},
 		{
 			desc:             "First time config of CoreDNS custom",
@@ -102,24 +107,43 @@ func TestConfigureCoreDNS(t *testing.T) {
 			expectedErr:      false,
 			expectedCorefile: ".:53 {\n    errors\n    health {\n        lameduck 5s\n    }\n    ready\n    kubernetes {{ pillar['dns_domain'] }} in-addr.arpa ip6.arpa {\n        pods insecure\n        fallthrough in-addr.arpa ip6.arpa\n        ttl 30\n    }\n    prometheus :9153\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n",
 			expectedCustom:   "\n#### Begin Maesh Block\nmaesh:53 {\n    errors\n    rewrite continue {\n        name regex ([a-zA-Z0-9-_]*)\\.([a-zv0-9-_]*)\\.maesh toto-{1}-6d61657368-{2}.toto.svc.titi\n        answer name toto-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\\.toto\\.svc\\.titi {1}.{2}.maesh\n    }\n    kubernetes titi in-addr.arpa ip6.arpa {\n        pods insecure\n        upstream\n        fallthrough in-addr.arpa ip6.arpa\n    }\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n#### End Maesh Block\n",
+			expectedRestart:  true,
 		},
 		{
 			desc:             "Already patched CoreDNS custom config",
 			mockFile:         "configurecoredns_custom_already_patched.yaml",
 			expectedErr:      false,
 			expectedCorefile: ".:53 {\n    errors\n    health {\n        lameduck 5s\n    }\n    ready\n    kubernetes {{ pillar['dns_domain'] }} in-addr.arpa ip6.arpa {\n        pods insecure\n        fallthrough in-addr.arpa ip6.arpa\n        ttl 30\n    }\n    prometheus :9153\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n",
-			expectedCustom:   "\n#### Begin Maesh Block\nmaesh:53 {\n    errors\n    rewrite continue {\n        name regex ([a-zA-Z0-9-_]*)\\.([a-zv0-9-_]*)\\.maesh toto-{1}-6d61657368-{2}.toto.svc.titi\n        answer name toto-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\\.toto\\.svc\\.titi {1}.{2}.maesh\n    }\n    kubernetes titi in-addr.arpa ip6.arpa {\n        pods insecure\n        upstream\n        fallthrough in-addr.arpa ip6.arpa\n    }\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n#### End Maesh Block\n",
+			expectedCustom:   "#### Begin Maesh Block\nmaesh:53 {\n    errors\n    rewrite continue {\n        name regex ([a-zA-Z0-9-_]*)\\.([a-zv0-9-_]*)\\.maesh toto-{1}-6d61657368-{2}.toto.svc.titi\n        answer name toto-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\\.toto\\.svc\\.titi {1}.{2}.maesh\n    }\n    kubernetes titi in-addr.arpa ip6.arpa {\n        pods insecure\n        upstream\n        fallthrough in-addr.arpa ip6.arpa\n    }\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n#### End Maesh Block\n",
+			expectedRestart:  false,
 		},
 		{
 			desc:             "Config of CoreDNS 1.7",
 			mockFile:         "configurecoredns_17.yaml",
 			expectedErr:      false,
 			expectedCorefile: ".:53 {\n    errors\n    health {\n        lameduck 5s\n    }\n    ready\n    kubernetes {{ pillar['dns_domain'] }} in-addr.arpa ip6.arpa {\n        pods insecure\n        fallthrough in-addr.arpa ip6.arpa\n        ttl 30\n    }\n    prometheus :9153\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n\n#### Begin Maesh Block\nmaesh:53 {\n    errors\n    rewrite continue {\n        name regex ([a-zA-Z0-9-_]*)\\.([a-zv0-9-_]*)\\.maesh toto-{1}-6d61657368-{2}.toto.svc.titi\n        answer name toto-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\\.toto\\.svc\\.titi {1}.{2}.maesh\n    }\n    kubernetes titi in-addr.arpa ip6.arpa {\n        pods insecure\n        \n        fallthrough in-addr.arpa ip6.arpa\n    }\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n#### End Maesh Block\n",
+			expectedRestart:  true,
 		},
 		{
-			desc:        "Missing CoreDNS deployment",
-			mockFile:    "configurecoredns_missing_deployment.yaml",
-			expectedErr: true,
+			desc:             "CoreDNS 1.7 already patched for an older version of CoreDNS",
+			mockFile:         "configurecoredns_17_already_patched.yaml",
+			expectedErr:      false,
+			expectedCorefile: ".:53 {\n    errors\n    health {\n        lameduck 5s\n    }\n    ready\n    kubernetes {{ pillar['dns_domain'] }} in-addr.arpa ip6.arpa {\n        pods insecure\n        fallthrough in-addr.arpa ip6.arpa\n        ttl 30\n    }\n    prometheus :9153\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n\n#### Begin Maesh Block\nmaesh:53 {\n    errors\n    rewrite continue {\n        name regex ([a-zA-Z0-9-_]*)\\.([a-zv0-9-_]*)\\.maesh toto-{1}-6d61657368-{2}.toto.svc.titi\n        answer name toto-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\\.toto\\.svc\\.titi {1}.{2}.maesh\n    }\n    kubernetes titi in-addr.arpa ip6.arpa {\n        pods insecure\n        \n        fallthrough in-addr.arpa ip6.arpa\n    }\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n#### End Maesh Block\n",
+			expectedRestart:  true,
+		},
+		{
+			desc:             "CoreDNS 1.7 custom config already patched for an older version of CoreDNS",
+			mockFile:         "configurecoredns_17_custom_already_patched.yaml",
+			expectedErr:      false,
+			expectedCorefile: ".:53 {\n    errors\n    health {\n        lameduck 5s\n    }\n    ready\n    kubernetes {{ pillar['dns_domain'] }} in-addr.arpa ip6.arpa {\n        pods insecure\n        fallthrough in-addr.arpa ip6.arpa\n        ttl 30\n    }\n    prometheus :9153\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n",
+			expectedCustom:   "\n#### Begin Maesh Block\nmaesh:53 {\n    errors\n    rewrite continue {\n        name regex ([a-zA-Z0-9-_]*)\\.([a-zv0-9-_]*)\\.maesh toto-{1}-6d61657368-{2}.toto.svc.titi\n        answer name toto-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\\.toto\\.svc\\.titi {1}.{2}.maesh\n    }\n    kubernetes titi in-addr.arpa ip6.arpa {\n        pods insecure\n        \n        fallthrough in-addr.arpa ip6.arpa\n    }\n    forward . /etc/resolv.conf\n    cache 30\n    loop\n    reload\n    loadbalance\n}\n#### End Maesh Block\n",
+			expectedRestart:  true,
+		},
+		{
+			desc:            "Missing CoreDNS deployment",
+			mockFile:        "configurecoredns_missing_deployment.yaml",
+			expectedErr:     true,
+			expectedRestart: false,
 		},
 	}
 
@@ -151,11 +175,19 @@ func TestConfigureCoreDNS(t *testing.T) {
 			assert.Equal(t, test.expectedCorefile, cfgMap.Data["Corefile"])
 
 			if len(test.expectedCustom) > 0 {
-				customCfgMap, err := k8sClient.KubernetesClient().CoreV1().ConfigMaps("kube-system").Get(ctx, "coredns-custom", metav1.GetOptions{})
+				var customCfgMap *corev1.ConfigMap
+
+				customCfgMap, err = k8sClient.KubernetesClient().CoreV1().ConfigMaps("kube-system").Get(ctx, "coredns-custom", metav1.GetOptions{})
 				require.NoError(t, err)
 
 				assert.Equal(t, test.expectedCustom, customCfgMap.Data["maesh.server"])
 			}
+
+			coreDNSDeployment, err := k8sClient.KubernetesClient().AppsV1().Deployments("kube-system").Get(ctx, "coredns", metav1.GetOptions{})
+			require.NoError(t, err)
+
+			restarted := coreDNSDeployment.Spec.Template.Annotations["maesh-hash"] != ""
+			assert.Equal(t, test.expectedRestart, restarted)
 		})
 	}
 }
@@ -229,8 +261,7 @@ func TestRestoreCoreDNS(t *testing.T) {
 		{
 			desc:             "CoreDNS config patched",
 			mockFile:         "restorecoredns_patched.yaml",
-			expectedCorefile: ".:53 {\n        errors\n        health {\n            lameduck 5s\n        }\n        ready\n        kubernetes {{ pillar['dns_domain'] }} in-addr.arpa ip6.arpa {\n            pods insecure\n            fallthrough in-addr.arpa ip6.arpa\n            ttl 30\n        }\n        prometheus :9153\n        forward . /etc/resolv.conf\n        cache 30\n        loop\n        reload\n        loadbalance\n    }\n# This is test data that must be present\n",
-		},
+			expectedCorefile: ".:53 {\n        errors\n        health {\n            lameduck 5s\n        }\n        ready\n        kubernetes {{ pillar['dns_domain'] }} in-addr.arpa ip6.arpa {\n            pods insecure\n            fallthrough in-addr.arpa ip6.arpa\n            ttl 30\n        }\n        prometheus :9153\n        forward . /etc/resolv.conf\n        cache 30\n        loop\n        reload\n        loadbalance\n    }\n\n# This is test data that must be present\n"},
 		{
 			desc:             "CoreDNS config not patched",
 			mockFile:         "restorecoredns_not_patched.yaml",
diff --git a/pkg/dns/testdata/configurecoredns_17_already_patched.yaml b/pkg/dns/testdata/configurecoredns_17_already_patched.yaml
new file mode 100644
index 0000000..cbad24f
--- /dev/null
+++ b/pkg/dns/testdata/configurecoredns_17_already_patched.yaml
@@ -0,0 +1,67 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: coredns
+  namespace: kube-system
+spec:
+  template:
+    spec:
+      containers:
+        - name: coredns
+          image: coredns:1.7.0
+      volumes:
+        - configMap:
+            name: "other-cfgmap"
+        - configMap:
+            name: "coredns"
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: other-cfgmap
+  namespace: kube-system
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: coredns
+  namespace: kube-system
+data:
+  Corefile: |
+    .:53 {
+        errors
+        health {
+            lameduck 5s
+        }
+        ready
+        kubernetes {{ pillar['dns_domain'] }} in-addr.arpa ip6.arpa {
+            pods insecure
+            fallthrough in-addr.arpa ip6.arpa
+            ttl 30
+        }
+        prometheus :9153
+        forward . /etc/resolv.conf
+        cache 30
+        loop
+        reload
+        loadbalance
+    }
+    #### Begin Maesh Block
+    maesh:53 {
+        errors
+        rewrite continue {
+            name regex ([a-zA-Z0-9-_]*)\.([a-zv0-9-_]*)\.maesh toto-{1}-6d61657368-{2}.toto.svc.titi
+            answer name toto-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\.toto\.svc\.titi {1}.{2}.maesh
+        }
+        kubernetes titi in-addr.arpa ip6.arpa {
+            pods insecure
+            upstream
+            fallthrough in-addr.arpa ip6.arpa
+        }
+        forward . /etc/resolv.conf
+        cache 30
+        loop
+        reload
+        loadbalance
+    }
+    #### End Maesh Block
\ No newline at end of file
diff --git a/pkg/dns/testdata/configurecoredns_17_custom_already_patched.yaml b/pkg/dns/testdata/configurecoredns_17_custom_already_patched.yaml
new file mode 100644
index 0000000..2765168
--- /dev/null
+++ b/pkg/dns/testdata/configurecoredns_17_custom_already_patched.yaml
@@ -0,0 +1,69 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: coredns
+  namespace: kube-system
+spec:
+  template:
+    spec:
+      containers:
+        - name: coredns
+          image: coredns:1.7.0
+      volumes:
+        - configMap:
+            name: "coredns"
+        - configMap:
+            name: "coredns-custom"
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: coredns-custom
+  namespace: kube-system
+data:
+  maesh.server: |
+    #### Begin Maesh Block
+    maesh:53 {
+        errors
+        rewrite continue {
+            name regex ([a-zA-Z0-9-_]*)\.([a-zv0-9-_]*)\.maesh toto-{1}-6d61657368-{2}.toto.svc.titi
+            answer name toto-([a-zA-Z0-9-_]*)-6d61657368-([a-zA-Z0-9-_]*)\.toto\.svc\.titi {1}.{2}.maesh
+        }
+        kubernetes titi in-addr.arpa ip6.arpa {
+            pods insecure
+            upstream
+            fallthrough in-addr.arpa ip6.arpa
+        }
+        forward . /etc/resolv.conf
+        cache 30
+        loop
+        reload
+        loadbalance
+    }
+    #### End Maesh Block
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: coredns
+  namespace: kube-system
+data:
+  Corefile: |
+    .:53 {
+        errors
+        health {
+            lameduck 5s
+        }
+        ready
+        kubernetes {{ pillar['dns_domain'] }} in-addr.arpa ip6.arpa {
+            pods insecure
+            fallthrough in-addr.arpa ip6.arpa
+            ttl 30
+        }
+        prometheus :9153
+        forward . /etc/resolv.conf
+        cache 30
+        loop
+        reload
+        loadbalance
+    }
diff --git a/pkg/dns/testdata/restorecoredns_patched.yaml b/pkg/dns/testdata/restorecoredns_patched.yaml
index 29eb361..02034c6 100644
--- a/pkg/dns/testdata/restorecoredns_patched.yaml
+++ b/pkg/dns/testdata/restorecoredns_patched.yaml
@@ -43,6 +43,7 @@ data:
             reload
             loadbalance
         }
+
     #### Begin Maesh Block
     maesh:53 {
         errors