dns: Fix purging DNS config

When user desires:

```yml
---
dns-resolver:
  config:
    search: []
```

It means user want to remove all search but preserve servers and
options, current nmstate incorrectly treat this as purge also.

This patch only treat these two as purge.

```yml
dns-resolver:
  config: {}
```

and

```yml
dns-resolver:
  config:
    server: []
    search: []
    options: []
```

Unit and integration test case included.

Signed-off-by: Gris Ge <fge@redhat.com>
This commit is contained in:
Gris Ge 2023-11-14 16:15:04 +08:00 committed by Fernando Fernández Mancera
parent 75e2f04296
commit ab07783b17
4 changed files with 98 additions and 11 deletions

View File

@ -54,6 +54,12 @@ const SUPPORTED_DNS_OPTS_WITH_VALUE: [&str; 3] =
/// - trust-ad
/// - rotate
/// ```
/// To purge all static DNS configuration:
/// ```yml
/// ---
/// dns-resolver:
/// config: {}
/// ```
pub struct DnsState {
#[serde(skip_serializing_if = "Option::is_none")]
/// The running effective state. The DNS server might be from DHCP(IPv6
@ -120,11 +126,15 @@ impl DnsClientState {
self.server.is_none() && self.search.is_none() && self.options.is_none()
}
// Whether user want to purge all DNS settings
// Any of these conditions means purge full DNS config:
// * `server`, `search` and `options` are None. Equal to desire state
// `config: {}`
// * `server`, `search` and `options` are `Some<Vec::new()>`.
pub(crate) fn is_purge(&self) -> bool {
self.server.as_deref().unwrap_or_default().is_empty()
&& self.search.as_deref().unwrap_or_default().is_empty()
&& self.options.as_deref().unwrap_or_default().is_empty()
self.server.is_none() && self.search.is_none() & self.options.is_none()
|| self.server.as_deref() == Some(&[])
&& self.search.as_deref() == Some(&[])
&& self.options.as_deref() == Some(&[])
}
pub(crate) fn is_null(&self) -> bool {

View File

@ -83,3 +83,40 @@ fn test_invalid_dns_option_with_value() {
assert_eq!(e.kind(), ErrorKind::InvalidArgument);
}
}
#[test]
fn test_is_purge_dns_empty_dict() {
let desired: DnsState = serde_yaml::from_str(
r"---
config: {}
",
)
.unwrap();
assert!(desired.config.unwrap().is_purge());
}
#[test]
fn test_is_purge_dns_full_empty_dict() {
let desired: DnsState = serde_yaml::from_str(
r"---
config:
server: []
search: []
options: []
",
)
.unwrap();
assert!(desired.config.unwrap().is_purge());
}
#[test]
fn test_not_purge() {
let desired: DnsState = serde_yaml::from_str(
r"---
config:
search: []
",
)
.unwrap();
assert!(!desired.config.unwrap().is_purge());
}

View File

@ -147,9 +147,9 @@ def test_dns_edit_3_more_nameservers(dns_servers):
@pytest.mark.tier1
@pytest.mark.parametrize(
"empty_dns_config",
[{DNS.SERVER: [], DNS.SEARCH: []}, {}],
[{DNS.SERVER: [], DNS.SEARCH: [], DNS.OPTIONS: []}, {}],
ids=[
"empty_server_and_search",
"empty_server_search_and_opt",
"empty_dict",
],
)
@ -573,3 +573,47 @@ def test_invalid_dns_option_with_value(static_dns):
)
with pytest.raises(NmstateValueError):
libnmstate.apply(desired_state)
@pytest.fixture
def static_dns_with_options(static_dns):
desired_state = {
DNS.KEY: {
DNS.CONFIG: {
DNS.OPTIONS: ["debug", "rotate"],
}
},
}
libnmstate.apply(desired_state)
def test_remove_all_dns_options(static_dns_with_options):
pre_apply_state = libnmstate.show()
desired_state = {
DNS.KEY: {
DNS.CONFIG: {
DNS.OPTIONS: [],
}
},
}
libnmstate.apply(desired_state)
current_state = libnmstate.show()
assert DNS.OPTIONS not in current_state[DNS.KEY][DNS.CONFIG]
assert (
current_state[DNS.KEY][DNS.CONFIG][DNS.SERVER]
== pre_apply_state[DNS.KEY][DNS.CONFIG][DNS.SERVER]
)
assert (
current_state[DNS.KEY][DNS.CONFIG][DNS.SEARCH]
== pre_apply_state[DNS.KEY][DNS.CONFIG][DNS.SEARCH]
)
def test_purge_dns_full_config(static_dns_with_options):
desired_state = {DNS.KEY: {DNS.CONFIG: {}}}
libnmstate.apply(desired_state)
current_state = libnmstate.show()
assert not current_state[DNS.KEY][DNS.CONFIG]

View File

@ -171,11 +171,7 @@ def auto_eth1(eth1_up):
}
)
yield
libnmstate.apply(
{
DNS.KEY: {DNS.CONFIG: {DNS.SERVER: [], DNS.SEARCH: []}},
}
)
libnmstate.apply({DNS.KEY: {DNS.CONFIG: {}}})
def test_static_dns_search_with_auto_dns(auto_eth1):