[pve-devel] [PATCH common v3 1/2] Document current handling of reading and updating resolv.conf

Emmanuel Kasper e.kasper at proxmox.com
Thu Apr 13 11:21:49 CEST 2017


also add unit tests for the two subroutines
---
 src/PVE/INotify.pm                                |  3 +
 test/inotify/resolv.conf_empty_search             |  5 ++
 test/inotify/resolv.conf_long_search              |  4 +
 test/inotify/resolv.conf_multiple_domain          |  5 ++
 test/inotify/resolv.conf_multiple_search          |  5 ++
 test/inotify/resolv.conf_search_with_domain_first |  6 ++
 test/inotify/resolv.conf_search_with_domain_last  |  6 ++
 test/inotify/resolv.conf_single_domain            |  5 ++
 test/inotify/resolv.conf_single_search            |  5 ++
 test/inotify/run_inotify_tests.pl                 | 97 +++++++++++++++++++++++
 10 files changed, 141 insertions(+)
 create mode 100644 test/inotify/resolv.conf_empty_search
 create mode 100644 test/inotify/resolv.conf_long_search
 create mode 100644 test/inotify/resolv.conf_multiple_domain
 create mode 100644 test/inotify/resolv.conf_multiple_search
 create mode 100644 test/inotify/resolv.conf_search_with_domain_first
 create mode 100644 test/inotify/resolv.conf_search_with_domain_last
 create mode 100644 test/inotify/resolv.conf_single_domain
 create mode 100644 test/inotify/resolv.conf_single_search
 create mode 100755 test/inotify/run_inotify_tests.pl

diff --git a/src/PVE/INotify.pm b/src/PVE/INotify.pm
index b2a5802..074f8b3 100644
--- a/src/PVE/INotify.pm
+++ b/src/PVE/INotify.pm
@@ -539,6 +539,8 @@ sub read_etc_resolv_conf {
     my $nscount = 0;
     while (my $line = <$fh>) {
 	chomp $line;
+	# resolv.conf should *either* have a search or domain, else behaviour is undefined
+	# see res_init.c in libc, havesearch is set to 0 when a domain entry is found
 	if ($line =~ m/^(search|domain)\s+(\S+)\s*/) {
 	    $res->{search} = $2;
 	} elsif ($line =~ m/^\s*nameserver\s+($PVE::Tools::IPRE)\s*/) {
@@ -557,6 +559,7 @@ sub update_etc_resolv_conf {
 
     my $data = "";
 
+    # when writing search domains always write to search, as this allows multiple entries
     $data = "search $resolv->{search}\n"
 	if $resolv->{search};
 
diff --git a/test/inotify/resolv.conf_empty_search b/test/inotify/resolv.conf_empty_search
new file mode 100644
index 0000000..342f5ea
--- /dev/null
+++ b/test/inotify/resolv.conf_empty_search
@@ -0,0 +1,5 @@
+# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
+#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
+nameserver 8.8.4.4
+nameserver 8.8.8.8
+search
diff --git a/test/inotify/resolv.conf_long_search b/test/inotify/resolv.conf_long_search
new file mode 100644
index 0000000..b51930b
--- /dev/null
+++ b/test/inotify/resolv.conf_long_search
@@ -0,0 +1,4 @@
+nameserver 192.168.2.121
+nameserver 192.168.2.122
+domain libera.cc proxmox.com
+search libera.cc.proxmox.com.libera.cc. proxmox.com.libera.cc.proxmox.com.libera.cc.proxmox.com.libera.cci.proxmox.com.libera.cc. proxmox.com.libera.cc.proxmox.com.libera.cc.proxmox.com.libera.cci.proxmox.com.libera.cc.proxmox.com.libera.cc.proxmox       libera.cc
diff --git a/test/inotify/resolv.conf_multiple_domain b/test/inotify/resolv.conf_multiple_domain
new file mode 100644
index 0000000..f6e8c01
--- /dev/null
+++ b/test/inotify/resolv.conf_multiple_domain
@@ -0,0 +1,5 @@
+# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
+#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
+nameserver 8.8.4.4
+nameserver 8.8.8.8
+domain proxmox.com proxmox.at
diff --git a/test/inotify/resolv.conf_multiple_search b/test/inotify/resolv.conf_multiple_search
new file mode 100644
index 0000000..bda26e9
--- /dev/null
+++ b/test/inotify/resolv.conf_multiple_search
@@ -0,0 +1,5 @@
+# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
+#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
+nameserver 8.8.4.4
+nameserver 8.8.8.8
+search proxmox.com proxmox.org proxmox.at    
diff --git a/test/inotify/resolv.conf_search_with_domain_first b/test/inotify/resolv.conf_search_with_domain_first
new file mode 100644
index 0000000..de8ec9a
--- /dev/null
+++ b/test/inotify/resolv.conf_search_with_domain_first
@@ -0,0 +1,6 @@
+# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
+#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
+nameserver 8.8.4.4
+nameserver 8.8.8.8
+domain libera.cc
+search proxmox.com
diff --git a/test/inotify/resolv.conf_search_with_domain_last b/test/inotify/resolv.conf_search_with_domain_last
new file mode 100644
index 0000000..3c65392
--- /dev/null
+++ b/test/inotify/resolv.conf_search_with_domain_last
@@ -0,0 +1,6 @@
+# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
+#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
+nameserver 8.8.4.4
+nameserver 8.8.8.8
+search proxmox.com proxmox.org
+domain libera.cc
diff --git a/test/inotify/resolv.conf_single_domain b/test/inotify/resolv.conf_single_domain
new file mode 100644
index 0000000..aaa2b64
--- /dev/null
+++ b/test/inotify/resolv.conf_single_domain
@@ -0,0 +1,5 @@
+# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
+#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
+nameserver 8.8.4.4
+nameserver 8.8.8.8
+domain proxmox.com
diff --git a/test/inotify/resolv.conf_single_search b/test/inotify/resolv.conf_single_search
new file mode 100644
index 0000000..1900906
--- /dev/null
+++ b/test/inotify/resolv.conf_single_search
@@ -0,0 +1,5 @@
+# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
+#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
+nameserver 8.8.4.4
+nameserver 8.8.8.8
+search proxmox.com
diff --git a/test/inotify/run_inotify_tests.pl b/test/inotify/run_inotify_tests.pl
new file mode 100755
index 0000000..4dbfb54
--- /dev/null
+++ b/test/inotify/run_inotify_tests.pl
@@ -0,0 +1,97 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use FindBin '$Bin'; # $Bin is path to current script. Yes, name is strange.
+use Test::More tests => 15;
+use IO::Handle;
+use Data::Dumper;
+
+use PVE::INotify;
+use PVE::Tools;
+
+# tests for PVE::INotify::read_etc_resolv_conf and PVE::INotify::update_etc_resolv_conf
+
+# reading a resolv.conf with a single entry
+my $single_domain = join('/', $Bin, 'resolv.conf_single_domain');
+my $fh = IO::File->new("< $single_domain");
+my $data = PVE::INotify::read_etc_resolv_conf($single_domain, $fh);
+
+is($data->{search}, 'proxmox.com', 'single domain parameter was correctly read');
+is($data->{dns1}, '8.8.4.4', 'ns1 parameter was correctly read');
+is($data->{dns2}, '8.8.8.8', 'ns2 parameter was correctly read');
+
+$fh->seek(0,0);
+my @args = ();
+
+my $data_to_write = PVE::INotify::update_etc_resolv_conf($single_domain, $fh, $data, @args);
+
+is(($data_to_write =~ m/^search proxmox.com\n/), 1, 'single entry was correctly added as search');
+is(($data_to_write =~ m/\nnameserver 8.8.8.8\n/), 1, 'ns1 parameter was correctly added');
+is(($data_to_write =~ m/\nnameserver 8.8.4.4\n/), 1, 'ns2 parameter was correctly added');
+
+$fh->close();
+
+# reading a resolv.conf with a single search entry
+# we don't retest for nameservers as the test data is the same for those
+my $single_search = join('/', $Bin, 'resolv.conf_single_search');
+$fh = IO::File->new("< $single_search");
+$data = PVE::INotify::read_etc_resolv_conf($single_search, $fh);
+
+is($data->{search}, 'proxmox.com', 'single entry search was correctly read');
+
+$fh->seek(0,0);
+$data_to_write = PVE::INotify::update_etc_resolv_conf($single_search, $fh, $data, @args);
+
+is(($data_to_write =~ m/^search proxmox.com\n/), 1, 'single entry search was correctly added');
+
+$fh->close();
+
+# reading a resolv.conf with a search entry containing multiple domains
+# we don't retest for nameservers as the test data is the same for those
+my $multiple_search = join('/', $Bin, 'resolv.conf_multiple_search');
+$fh = IO::File->new("< $multiple_search");
+$data = PVE::INotify::read_etc_resolv_conf($multiple_search, $fh);
+
+is($data->{search}, 'proxmox.com proxmox.org proxmox.at', 'multiple search domains were correctly read');
+
+$fh->seek(0,0);
+$data_to_write = PVE::INotify::update_etc_resolv_conf($multiple_search, $fh, $data, @args);
+
+is(($data_to_write =~ m/^search proxmox.com proxmox.org proxmox.at\n/), 1, 'multiple search domains were correctly added');
+
+#glic resolver res_init.c will only consider only the last entry
+#make sure we do the same
+my $domain_first = join('/', $Bin, 'resolv.conf_search_with_domain_first');
+$fh = IO::File->new("< $domain_first");
+$data = PVE::INotify::read_etc_resolv_conf($domain_first, $fh);
+is($data->{search}, 'proxmox.com', 'read entries when domain is first correct');
+$fh->seek(0,0);
+
+my $domain_last = join('/', $Bin, 'resolv.conf_search_with_domain_last');
+$fh = IO::File->new("< $domain_last");
+$data = PVE::INotify::read_etc_resolv_conf($domain_last, $fh);
+is($data->{search}, 'libera.cc', 'search entries when domain is last');
+$fh->seek(0,0);
+
+my $long_search = join('/', $Bin, 'resolv.conf_long_search');
+$fh = IO::File->new("< $long_search");
+$data = PVE::INotify::read_etc_resolv_conf($long_search, $fh);
+is(defined($data->{search}), '', 'no search entries when search line is more than 255 chars');
+$fh->seek(0,0);
+
+my $empty_search = join('/', $Bin, 'resolv.conf_empty_search');
+$fh = IO::File->new("< $empty_search");
+$data = PVE::INotify::read_etc_resolv_conf($empty_search, $fh);
+is(defined($data->{search}), '', 'no search entries when search line is empty');
+$fh->seek(0,0);
+
+my $multiple_domain = join('/', $Bin, 'resolv.conf_multiple_domain');
+$fh = IO::File->new("< $multiple_domain");
+$data = PVE::INotify::read_etc_resolv_conf($multiple_domain, $fh);
+is($data->{search}, 'proxmox.com', 'first entry of multiple domains in domain correct');
+$fh->seek(0,0);
+
+$fh->close();
+done_testing();
-- 
2.1.4





More information about the pve-devel mailing list