diff --git a/test/case/containers/basic/test.py b/test/case/containers/basic/test.py index 3d969a597..f4a687c2d 100755 --- a/test/case/containers/basic/test.py +++ b/test/case/containers/basic/test.py @@ -30,29 +30,33 @@ def _verify(server, silent=False): test.skip() with test.step("Set hostname to 'container-host'"): - target.put_config_dict("ietf-system", { - "system": { - "hostname": "container-host" + target.put_config_dicts({ + "ietf-system": { + "system": { + "hostname": "container-host" + } } }) with test.step("Create container 'web' from bundled OCI image"): - target.put_config_dict("infix-containers", { - "containers": { - "container": [ - { - "name": f"{NAME}", - "image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}", - "command": "/usr/sbin/httpd -f -v -p 91", - "network": { - "host": True - }, - "resource-limit": { - "memory": 512, # 512 KiB - "cpu": 500 # 50% of one CPU (0.5 cores) + target.put_config_dicts({ + "infix-containers": { + "containers": { + "container": [ + { + "name": f"{NAME}", + "image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}", + "command": "/usr/sbin/httpd -f -v -p 91", + "network": { + "host": True + }, + "resource-limit": { + "memory": 512, # 512 KiB + "cpu": 500 # 50% of one CPU (0.5 cores) + } } - } - ] + ] + } } }) diff --git a/test/case/containers/enabled/test.py b/test/case/containers/enabled/test.py index 0832e97a3..42fb65e21 100755 --- a/test/case/containers/enabled/test.py +++ b/test/case/containers/enabled/test.py @@ -17,14 +17,16 @@ def set_container_enabled(target, name, enabled): """Helper function to set container enabled state and verify the change""" - target.put_config_dict("infix-containers", { - "containers": { - "container": [ - { - "name": name, - "enabled": enabled - } - ] + target.put_config_dicts({ + "infix-containers": { + "containers": { + "container": [ + { + "name": name, + "enabled": enabled + } + ] + } } }) @@ -39,27 +41,22 @@ def set_container_enabled(target, name, enabled): if not target.has_model("infix-containers"): test.skip() - with test.step("Set hostname to 'container-host'"): - target.put_config_dict("ietf-system", { - "system": { - "hostname": "container-host" - } - }) - with test.step("Create enabled container from bundled OCI image"): - target.put_config_dict("infix-containers", { - "containers": { - "container": [ - { - "name": f"{NAME}", - "enabled": True, - "image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}", - "command": "/usr/sbin/httpd -f -v -p 91", - "network": { - "host": True + target.put_config_dicts({ + "infix-containers": { + "containers": { + "container": [ + { + "name": f"{NAME}", + "enabled": True, + "image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}", + "command": "/usr/sbin/httpd -f -v -p 91", + "network": { + "host": True + } } - } - ] + ] + } } }) diff --git a/test/case/containers/environment/test.py b/test/case/containers/environment/test.py index 851d9e3ec..4476f18b6 100755 --- a/test/case/containers/environment/test.py +++ b/test/case/containers/environment/test.py @@ -37,17 +37,19 @@ with test.step("Configure data interface with static IPv4"): _, ifname = env.ltop.xlate("target", "data") - target.put_config_dict("ietf-interfaces", { - "interfaces": { - "interface": [{ - "name": f"{ifname}", - "ipv4": { - "address": [{ - "ip": f"{DUTIP}", - "prefix-length": 24 - }] - } - }] + target.put_config_dicts({ + "ietf-interfaces": { + "interfaces": { + "interface": [{ + "name": f"{ifname}", + "ipv4": { + "address": [{ + "ip": f"{DUTIP}", + "prefix-length": 24 + }] + } + }] + } } }) @@ -62,31 +64,33 @@ for var in ENV_VARS: cgi.append(f'echo "{var["key"]}=${var["key"]}"') - target.put_config_dict("infix-containers", { - "containers": { - "container": [ - { - "name": f"{NAME}", - "image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}", - "command": "/usr/sbin/httpd -f -v -p 8080", - "env": ENV_VARS, - "network": { - "host": True - }, - "mount": [ - { - "name": "env.cgi", - "content": to_binary('\n'.join(cgi) + '\n'), - "target": "/var/www/cgi-bin/env.cgi", - "mode": "0755" - } - ], - "volume": [{ - "name": "www", - "target": "/var/www" - }] - } - ] + target.put_config_dicts({ + "infix-containers": { + "containers": { + "container": [ + { + "name": f"{NAME}", + "image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}", + "command": "/usr/sbin/httpd -f -v -p 8080", + "env": ENV_VARS, + "network": { + "host": True + }, + "mount": [ + { + "name": "env.cgi", + "content": to_binary('\n'.join(cgi) + '\n'), + "target": "/var/www/cgi-bin/env.cgi", + "mode": "0755" + } + ], + "volume": [{ + "name": "www", + "target": "/var/www" + }] + } + ] + } } }) @@ -115,12 +119,14 @@ {"key": "PATH_WITH_SPACES", "value": "/path with spaces/test"} ] - target.put_config_dict("infix-containers", { - "containers": { - "container": [{ - "name": f"{NAME}", - "env": UPDATED_ENV_VARS, - }] + target.put_config_dicts({ + "infix-containers": { + "containers": { + "container": [{ + "name": f"{NAME}", + "env": UPDATED_ENV_VARS, + }] + } } }) diff --git a/test/case/containers/firewall_basic/test.py b/test/case/containers/firewall_basic/test.py index d5cd9c951..01e25b687 100755 --- a/test/case/containers/firewall_basic/test.py +++ b/test/case/containers/firewall_basic/test.py @@ -52,57 +52,61 @@ test.skip() with test.step("Set hostname to 'container-host'"): - target.put_config_dict("ietf-system", { - "system": { - "hostname": "container-host" + target.put_config_dicts({ + "ietf-system": { + "system": { + "hostname": "container-host" + } } }) with test.step("Create VETH pair for web server container"): - target.put_config_dict("ietf-interfaces", { - "interfaces": { - "interface": [ - { - "name": f"{ext0}", - "ipv4": { - "forwarding": True, - "address": [{ - "ip": f"{EXTIP}", - "prefix-length": 24 - }] - } - }, - { - "name": "int0", - "type": "infix-if-type:veth", - "enabled": True, - "infix-interfaces:veth": { - "peer": f"{WEBNM}" + target.put_config_dicts({ + "ietf-interfaces": { + "interfaces": { + "interface": [ + { + "name": f"{ext0}", + "ipv4": { + "forwarding": True, + "address": [{ + "ip": f"{EXTIP}", + "prefix-length": 24 + }] + } }, - "ipv4": { - "forwarding": True, - "address": [{ - "ip": f"{INTIP}", - "prefix-length": 24, - }] - } - }, - { - "name": f"{WEBNM}", - "type": "infix-if-type:veth", - "enabled": True, - "infix-interfaces:veth": { - "peer": "int0" + { + "name": "int0", + "type": "infix-if-type:veth", + "enabled": True, + "infix-interfaces:veth": { + "peer": f"{WEBNM}" + }, + "ipv4": { + "forwarding": True, + "address": [{ + "ip": f"{INTIP}", + "prefix-length": 24, + }] + } }, - "ipv4": { - "address": [{ - "ip": f"{WEBIP}", - "prefix-length": 24, - }] + { + "name": f"{WEBNM}", + "type": "infix-if-type:veth", + "enabled": True, + "infix-interfaces:veth": { + "peer": "int0" + }, + "ipv4": { + "address": [{ + "ip": f"{WEBIP}", + "prefix-length": 24, + }] + }, + "container-network": {} }, - "container-network": {} - }, - ] + ] + } } }) @@ -132,43 +136,47 @@ } """) - target.put_config_dict("infix-containers", { - "containers": { - "container": [ - { - "name": f"{NFTNM}", - "image": f"{NFTABLES}", - "network": { - "host": True - }, - "mount": [ - { - "name": "nftables.conf", - "content": config, - "target": "/etc/nftables.conf" - } - ], - "privileged": True - } - ] + target.put_config_dicts({ + "infix-containers": { + "containers": { + "container": [ + { + "name": f"{NFTNM}", + "image": f"{NFTABLES}", + "network": { + "host": True + }, + "mount": [ + { + "name": "nftables.conf", + "content": config, + "target": "/etc/nftables.conf" + } + ], + "privileged": True + } + ] + } } }) with test.step("Create web server container from bundled OCI image"): - target.put_config_dict("infix-containers", { - "containers": { - "container": [ - { - "name": f"{WEBNM}", - "image": f"{HTTPD}", - "command": "/usr/sbin/httpd -f -v -p 91", - "network": { - "interface": [ - {"name": f"{WEBNM}"} - ] + target.put_config_dicts({ + "infix-containers": { + "containers": { + "container": [ + { + "name": f"{WEBNM}", + "image": f"{HTTPD}", + "command": "/usr/sbin/httpd -f -v -p 91", + "network": { + "interface": [ + {"name": f"{WEBNM}"} + ] + } } - } - ] + ] + } } }) diff --git a/test/case/containers/host_commands/test.py b/test/case/containers/host_commands/test.py index 3cc766683..001bcb7c8 100755 --- a/test/case/containers/host_commands/test.py +++ b/test/case/containers/host_commands/test.py @@ -23,9 +23,11 @@ test.skip() with test.step("Set initial hostname"): - target.put_config_dict("ietf-system", { - "system": { - "hostname": hostname_init + target.put_config_dicts({ + "ietf-system": { + "system": { + "hostname": hostname_init + } } }) @@ -42,31 +44,33 @@ nsenter -m/1/ns/mnt -u/1/ns/uts -i/1/ns/ipc -n/1/ns/net hostname {hostname_new} """) - target.put_config_dict("infix-containers", { - "containers": { - "container": [ - { - "name": cont_name, - "image": cont_image, - "network": { - "host": True - }, - "mount": [ - { - "name": "rc.local", - "content": commands, - "target": "/etc/rc.local", - "mode": "0755" + target.put_config_dicts({ + "infix-containers": { + "containers": { + "container": [ + { + "name": cont_name, + "image": cont_image, + "network": { + "host": True }, - { - "name": "proc1ns", - "source": "/proc/1/ns", - "target": "/1/ns", - } - ], - "privileged": True - } - ] + "mount": [ + { + "name": "rc.local", + "content": commands, + "target": "/etc/rc.local", + "mode": "0755" + }, + { + "name": "proc1ns", + "source": "/proc/1/ns", + "target": "/1/ns", + } + ], + "privileged": True + } + ] + } } }) diff --git a/test/case/containers/phys/test.py b/test/case/containers/phys/test.py index 534ac232e..61b3b5d3a 100755 --- a/test/case/containers/phys/test.py +++ b/test/case/containers/phys/test.py @@ -27,32 +27,34 @@ with test.step("Create httpd container from bundled OCI image"): _, ifname = env.ltop.xlate("target", "data") - target.put_config_dict("ietf-interfaces", { - "interfaces": { - "interface": [{ - "name": f"{ifname}", - "ipv4": { - "address": [{ - "ip": f"{DUTIP}", - "prefix-length": 24 - }] - }, - "container-network": {} - }] - } - }) - target.put_config_dict("infix-containers", { - "containers": { - "container": [{ - "name": f"{NAME}", - "image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}", - "command": "/usr/sbin/httpd -f -v -p 91", - "network": { - "interface": [ - {"name": f"{ifname}"} - ] - } - }] + target.put_config_dicts({ + "ietf-interfaces": { + "interfaces": { + "interface": [{ + "name": f"{ifname}", + "ipv4": { + "address": [{ + "ip": f"{DUTIP}", + "prefix-length": 24 + }] + }, + "container-network": {} + }] + } + }, + "infix-containers": { + "containers": { + "container": [{ + "name": f"{NAME}", + "image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}", + "command": "/usr/sbin/httpd -f -v -p 91", + "network": { + "interface": [ + {"name": f"{ifname}"} + ] + } + }] + } } }) @@ -74,16 +76,18 @@ # Verify modifying a running container takes, issue #930 data = to_binary(BODY) - target.put_config_dict("infix-containers", { - "containers": { - "container": [{ - "name": f"{NAME}", - "mount": [{ - "name": "index.html", - "content": f"{data}", - "target": "/var/www/index.html" + target.put_config_dicts({ + "infix-containers": { + "containers": { + "container": [{ + "name": f"{NAME}", + "mount": [{ + "name": "index.html", + "content": f"{data}", + "target": "/var/www/index.html" + }] }] - }] + } } }) diff --git a/test/case/containers/upgrade/test.py b/test/case/containers/upgrade/test.py index 2e37f6978..5e13ba982 100755 --- a/test/case/containers/upgrade/test.py +++ b/test/case/containers/upgrade/test.py @@ -90,18 +90,20 @@ print(f"Created symlink: {latest_link} -> {old_img}") with test.step("Create container 'web' from curios-httpd:latest (24.05.0)"): - target.put_config_dict("infix-containers", { - "containers": { - "container": [ - { - "name": f"{NAME}", - "image": f"http://192.168.0.1:{SRVPORT}/curios-httpd-latest.tar.gz", - "command": "/usr/sbin/httpd -f -v -p 91", - "network": { - "host": True + target.put_config_dicts({ + "infix-containers": { + "containers": { + "container": [ + { + "name": f"{NAME}", + "image": f"http://192.168.0.1:{SRVPORT}/curios-httpd-latest.tar.gz", + "command": "/usr/sbin/httpd -f -v -p 91", + "network": { + "host": True + } } - } - ] + ] + } } }) diff --git a/test/case/containers/veth/test.py b/test/case/containers/veth/test.py index 028bf63fe..8d50ec9fc 100755 --- a/test/case/containers/veth/test.py +++ b/test/case/containers/veth/test.py @@ -36,60 +36,62 @@ with test.step("Create 'web-br0-veth' container from bundled OCI image"): _, ifname = env.ltop.xlate("target", "data") - target.put_config_dict("ietf-interfaces", { - "interfaces": { - "interface": [ - { - "name": f"{ifname}", - "infix-interfaces:bridge-port": { - "bridge": "br0" - } - }, - { - "name": "br0", - "type": "infix-if-type:bridge" - }, - { - "name": f"{NAME}", - "type": "infix-if-type:veth", - "infix-interfaces:veth": { - "peer": "veth0b" + target.put_config_dicts({ + "ietf-interfaces": { + "interfaces": { + "interface": [ + { + "name": f"{ifname}", + "infix-interfaces:bridge-port": { + "bridge": "br0" + } }, - "ipv4": { - "address": [{ - "ip": f"{DUTIP}", - "prefix-length": 24 - }] + { + "name": "br0", + "type": "infix-if-type:bridge" }, - "container-network": {} - }, - { - "name": "veth0b", - "type": "infix-if-type:veth", - "infix-interfaces:veth": { - "peer": f"{NAME}" + { + "name": f"{NAME}", + "type": "infix-if-type:veth", + "infix-interfaces:veth": { + "peer": "veth0b" + }, + "ipv4": { + "address": [{ + "ip": f"{DUTIP}", + "prefix-length": 24 + }] + }, + "container-network": {} }, - "infix-interfaces:bridge-port": { - "bridge": "br0" - } - }, - ] - } - }) - target.put_config_dict("infix-containers", { - "containers": { - "container": [ - { - "name": f"{NAME}", - "image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}", - "command": "/usr/sbin/httpd -f -v -p 91", - "network": { - "interface": [ - { "name": f"{NAME}" } - ] + { + "name": "veth0b", + "type": "infix-if-type:veth", + "infix-interfaces:veth": { + "peer": f"{NAME}" + }, + "infix-interfaces:bridge-port": { + "bridge": "br0" + } + }, + ] + } + }, + "infix-containers": { + "containers": { + "container": [ + { + "name": f"{NAME}", + "image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}", + "command": "/usr/sbin/httpd -f -v -p 91", + "network": { + "interface": [ + { "name": f"{NAME}" } + ] + } } - } - ] + ] + } } }) diff --git a/test/case/containers/volume/test.py b/test/case/containers/volume/test.py index 0be586097..b4c752f2e 100755 --- a/test/case/containers/volume/test.py +++ b/test/case/containers/volume/test.py @@ -25,22 +25,24 @@ test.skip() with test.step("Create container with volume from bundled OCI image"): - target.put_config_dict("infix-containers", { - "containers": { - "container": [ - { - "name": f"{NAME}", - "image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}", - "command": f"/usr/sbin/httpd -f -v -p {PORT}", - "network": { - "host": True - }, - "volume": [{ - "name": "www", - "target": "/var/www" - }] - } - ] + target.put_config_dicts({ + "infix-containers": { + "containers": { + "container": [ + { + "name": f"{NAME}", + "image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}", + "command": f"/usr/sbin/httpd -f -v -p {PORT}", + "network": { + "host": True + }, + "volume": [{ + "name": "www", + "target": "/var/www" + }] + } + ] + } } }) diff --git a/test/case/dhcp/client6_basic/test.py b/test/case/dhcp/client6_basic/test.py index 6a9a041a4..e06b011f1 100755 --- a/test/case/dhcp/client6_basic/test.py +++ b/test/case/dhcp/client6_basic/test.py @@ -64,7 +64,7 @@ def check_dns_resolution(): }] } } - client.put_config_dict("ietf-interfaces", config) + client.put_config_dicts({"ietf-interfaces": config}) with test.step("Verify DHCPv6 client is running"): until(checkrun, attempts=10) diff --git a/test/case/dhcp/client6_prefix_delegation/test.py b/test/case/dhcp/client6_prefix_delegation/test.py index 242adf0f3..3eb1d23d9 100755 --- a/test/case/dhcp/client6_prefix_delegation/test.py +++ b/test/case/dhcp/client6_prefix_delegation/test.py @@ -71,7 +71,7 @@ def checklog(dut): }] } } - client.put_config_dict("ietf-interfaces", config) + client.put_config_dicts({"ietf-interfaces": config}) with test.step("Verify DHCPv6 client is running"): until(lambda: checkrun(tgtssh), attempts=20) diff --git a/test/case/dhcp/client6_slaac_ra/test.py b/test/case/dhcp/client6_slaac_ra/test.py index b34d6dadf..09385d8a1 100755 --- a/test/case/dhcp/client6_slaac_ra/test.py +++ b/test/case/dhcp/client6_slaac_ra/test.py @@ -80,7 +80,7 @@ def check_slaac_address(): }] } } - client.put_config_dict("ietf-interfaces", config) + client.put_config_dicts({"ietf-interfaces": config}) with test.step("Verify DHCPv6 client is running"): until(lambda: checkrun(tgtssh), attempts=20) diff --git a/test/case/dhcp/client_basic/test.py b/test/case/dhcp/client_basic/test.py index 822b49fcd..706e0513d 100755 --- a/test/case/dhcp/client_basic/test.py +++ b/test/case/dhcp/client_basic/test.py @@ -33,7 +33,7 @@ }] } } - client.put_config_dict("ietf-interfaces", config) + client.put_config_dicts({"ietf-interfaces": config}) with test.step("Verify client lease for 10.0.0.42"): until(lambda: iface.address_exist(client, port, ADDRESS)) diff --git a/test/case/dhcp/client_default_gw/test.py b/test/case/dhcp/client_default_gw/test.py index 5173da2ac..c442edc3b 100755 --- a/test/case/dhcp/client_default_gw/test.py +++ b/test/case/dhcp/client_default_gw/test.py @@ -39,7 +39,7 @@ }] } } - client.put_config_dict("ietf-interfaces", config) + client.put_config_dicts({"ietf-interfaces": config}) with test.step("Verify DHCP client has default route via 192.168.0.254"): until(lambda: route.ipv4_route_exist(client, "0.0.0.0/0", ROUTER), attempts=30) diff --git a/test/case/dhcp/client_hostname/test.py b/test/case/dhcp/client_hostname/test.py index afdadee51..41751ae59 100755 --- a/test/case/dhcp/client_hostname/test.py +++ b/test/case/dhcp/client_hostname/test.py @@ -29,11 +29,11 @@ def verify_hostname(node, expected): _, port = env.ltop.xlate("client", "mgmt") with test.step("Configure static system hostname"): - client.put_config_dict("ietf-system", { + client.put_config_dicts({"ietf-system": { "system": { "hostname": CONF_HOSTNAME } - }) + }}) with test.step("Verify configured hostname is set"): until(lambda: verify_hostname(client, CONF_HOSTNAME)) @@ -42,7 +42,13 @@ def verify_hostname(node, expected): netns.addip("10.0.0.1") with infamy.dhcp.Server(netns, ip="10.0.0.42", hostname=DHCP_HOSTNAME): with test.step("Enable DHCP client requesting hostname option"): - client.put_config_dict("ietf-interfaces", { + client.put_config_dicts({ + "ietf-system": { + "system": { + "hostname": CONF_HOSTNAME + } + }, + "ietf-interfaces": { "interfaces": { "interface": [{ "name": port, @@ -58,7 +64,7 @@ def verify_hostname(node, expected): } }] } - }) + }}) with test.step("Verify DHCP hostname takes precedence"): until(lambda: verify_hostname(client, DHCP_HOSTNAME)) diff --git a/test/case/dhcp/client_hostname_resend/test.py b/test/case/dhcp/client_hostname_resend/test.py index b510a1f18..dceb89cc2 100755 --- a/test/case/dhcp/client_hostname_resend/test.py +++ b/test/case/dhcp/client_hostname_resend/test.py @@ -45,16 +45,22 @@ def running_hostname(ssh, ifname): _, port = env.ltop.xlate("client", "mgmt") with test.step(f"Configure initial hostname '{HOSTNM_A}'"): - client.put_config_dict("ietf-system", { + client.put_config_dicts({"ietf-system": { "system": { "hostname": HOSTNM_A } - }) + }}) until(lambda: client.get_data("/ietf-system:system") .get("system", {}).get("hostname") == HOSTNM_A) with test.step("Enable DHCP client sending hostname option"): - client.put_config_dict("ietf-interfaces", { + client.put_config_dicts({ + "ietf-system": { + "system": { + "hostname": HOSTNM_A + } + }, + "ietf-interfaces": { "interfaces": { "interface": [{ "name": port, @@ -70,17 +76,17 @@ def running_hostname(ssh, ifname): } }] } - }) + }}) with test.step(f"Verify running udhcpc announces hostname '{HOSTNM_A}'"): until(lambda: running_hostname(clissh, port) == HOSTNM_A) with test.step(f"Update system hostname to '{HOSTNM_B}'"): - client.put_config_dict("ietf-system", { + client.put_config_dicts({"ietf-system": { "system": { "hostname": HOSTNM_B } - }) + }}) until(lambda: client.get_data("/ietf-system:system") .get("system", {}).get("hostname") == HOSTNM_B) diff --git a/test/case/dhcp/client_routes/test.py b/test/case/dhcp/client_routes/test.py index 26736d6d8..ec3aef26a 100755 --- a/test/case/dhcp/client_routes/test.py +++ b/test/case/dhcp/client_routes/test.py @@ -34,7 +34,7 @@ # Install canary route to smoke out any regressions in # how the DHCP client installs routes in the kernel FIB - client.put_config_dict("ietf-routing", { + client.put_config_dicts({"ietf-routing": { "routing": { "control-plane-protocols": { "control-plane-protocol": [{ @@ -54,12 +54,12 @@ }] } } - }) + }}) with test.step("Enabling DHCP client, allow option 3 and 121"): _, port = env.ltop.xlate("client", "data") - client.put_config_dict("ietf-interfaces", { + client.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [{ "name": f"{port}", @@ -73,7 +73,7 @@ } }] } - }) + }}) with infamy.IsolatedMacVlan(host) as netns: netns.addip("192.168.0.1") diff --git a/test/case/firewall/basic/test.py b/test/case/firewall/basic/test.py index fa21fd186..eeb934dc1 100755 --- a/test/case/firewall/basic/test.py +++ b/test/case/firewall/basic/test.py @@ -28,55 +28,56 @@ HOST_IP = "192.168.1.42" with test.step("Configure basic end-device firewall"): - target.put_config_dict("ietf-interfaces", { - "interfaces": { - "interface": [ - { - "name": data_if, - "enabled": True, - "ipv4": { - "address": [{ - "ip": TARGET_IP, - "prefix-length": 24 - }] + target.put_config_dicts({ + "ietf-interfaces": { + "interfaces": { + "interface": [ + { + "name": data_if, + "enabled": True, + "ipv4": { + "address": [{ + "ip": TARGET_IP, + "prefix-length": 24 + }] + } } - } - ] - } - }) - - target.put_config_dict("infix-firewall", { - "firewall": { - "default": "public-untrusted-net", - "logging": "all", - "service": [{ - "name": "mySSH", - "port": [{ - "lower": 222, - "proto": "tcp" - }] - }, { - "name": "http", - "port": [{ - "lower": 8080, - "proto": "tcp" + ] + } + }, + "infix-firewall": { + "firewall": { + "default": "public-untrusted-net", + "logging": "all", + "service": [{ + "name": "mySSH", + "port": [{ + "lower": 222, + "proto": "tcp" + }] + }, { + "name": "http", + "port": [{ + "lower": 8080, + "proto": "tcp" + }] + }], + "zone": [{ + "name": "mgmt", + "description": "Management network - for test automation", + "action": "accept", + "interface": [mgmt_if], + "service": ["ssh", "netconf", "restconf"] + }, { + # 20-char name, exceeds old iptables-derived 17-char limit + # Verifies we allow long names with nftables, issue #1389 + "name": "public-untrusted-net", + "description": "Public untrusted network", + "action": "drop", + "interface": [data_if], + "service": ["ssh", "dhcpv6-client", "mySSH", "http"] }] - }], - "zone": [{ - "name": "mgmt", - "description": "Management network - for test automation", - "action": "accept", - "interface": [mgmt_if], - "service": ["ssh", "netconf", "restconf"] - }, { - # 20-char name, exceeds old iptables-derived 17-char limit - # Verifies we allow long names with nftables, issue #1389 - "name": "public-untrusted-net", - "description": "Public untrusted network", - "action": "drop", - "interface": [data_if], - "service": ["ssh", "dhcpv6-client", "mySSH", "http"] - }] + } } }) diff --git a/test/case/firewall/ipv6-zone-migration/test.py b/test/case/firewall/ipv6-zone-migration/test.py index 1fd2b2b4e..4e57664ee 100755 --- a/test/case/firewall/ipv6-zone-migration/test.py +++ b/test/case/firewall/ipv6-zone-migration/test.py @@ -192,12 +192,14 @@ with test.step("Perform dynamic zone migration"): target.delete_xpath(f"/infix-firewall:firewall/zone[name='untrusted']/interface[.='{data1_if}']") - target.put_config_dict("infix-firewall", { - "firewall": { - "zone": [{ - "name": "trusted", - "interface": [data1_if] - }] + target.put_config_dicts({ + "infix-firewall": { + "firewall": { + "zone": [{ + "name": "trusted", + "interface": [data1_if] + }] + } } }) diff --git a/test/case/firewall/lan-wan/test.py b/test/case/firewall/lan-wan/test.py index 17edf6fa5..3c1223f84 100755 --- a/test/case/firewall/lan-wan/test.py +++ b/test/case/firewall/lan-wan/test.py @@ -36,63 +36,64 @@ WAN_SERVER_IP = "203.0.113.100" # Server on WAN side with test.step("Configure gateway with firewall and SNAT"): - gateway.put_config_dict("ietf-interfaces", { - "interfaces": { - "interface": [ - { - "name": lan_if, - "enabled": True, - "ipv4": { - "forwarding": True, - "address": [{ - "ip": LAN_ROUTER_IP, - "prefix-length": 24 - }] + gateway.put_config_dicts({ + "ietf-interfaces": { + "interfaces": { + "interface": [ + { + "name": lan_if, + "enabled": True, + "ipv4": { + "forwarding": True, + "address": [{ + "ip": LAN_ROUTER_IP, + "prefix-length": 24 + }] + } + }, + { + "name": wan_if, + "enabled": True, + "ipv4": { + "forwarding": True, + "address": [{ + "ip": WAN_ROUTER_IP, + "prefix-length": 24 + }] + } } - }, - { - "name": wan_if, - "enabled": True, - "ipv4": { - "forwarding": True, - "address": [{ - "ip": WAN_ROUTER_IP, - "prefix-length": 24 - }] + ] + } + }, + "infix-firewall": { + "firewall": { + "default": "wan", + "logging": "all", + "zone": [ + { + "name": "lan", + "description": "Internal LAN network - trusted", + "action": "accept", + "interface": [lan_if, mgmt_if], + "service": ["ssh", "dhcp", "dns"] + }, { + "name": "wan", + "description": "External WAN interface - untrusted", + "action": "drop", + "interface": [wan_if] } - } - ] - } - }) - - gateway.put_config_dict("infix-firewall", { - "firewall": { - "default": "wan", - "logging": "all", - "zone": [ - { - "name": "lan", - "description": "Internal LAN network - trusted", - "action": "accept", - "interface": [lan_if, mgmt_if], - "service": ["ssh", "dhcp", "dns"] - }, { - "name": "wan", - "description": "External WAN interface - untrusted", - "action": "drop", - "interface": [wan_if] - } - ], - "policy": [ - { - "name": "lan-to-wan", - "description": "Allow LAN to WAN traffic with SNAT", - "ingress": ["lan"], - "egress": ["wan"], - "action": "accept", - "masquerade": True - } - ] + ], + "policy": [ + { + "name": "lan-to-wan", + "description": "Allow LAN to WAN traffic with SNAT", + "ingress": ["lan"], + "egress": ["wan"], + "action": "accept", + "masquerade": True + } + ] + } } }) diff --git a/test/case/firewall/wan-dmz-lan/test.py b/test/case/firewall/wan-dmz-lan/test.py index 5fcc02801..d9e6c1f2b 100755 --- a/test/case/firewall/wan-dmz-lan/test.py +++ b/test/case/firewall/wan-dmz-lan/test.py @@ -42,96 +42,97 @@ LAN_CLIENT_IP = "192.168.1.100" # Host LAN interface with test.step("Configure gateway with multi-zone firewall and NAT"): - gateway.put_config_dict("ietf-interfaces", { - "interfaces": { - "interface": [ - { - "name": wan_if, - "enabled": True, - "ipv4": { - "forwarding": True, - "address": [{ - "ip": WAN_ROUTER_IP, - "prefix-length": 24 - }] + gateway.put_config_dicts({ + "ietf-interfaces": { + "interfaces": { + "interface": [ + { + "name": wan_if, + "enabled": True, + "ipv4": { + "forwarding": True, + "address": [{ + "ip": WAN_ROUTER_IP, + "prefix-length": 24 + }] + } + }, + { + "name": dmz_if, + "enabled": True, + "ipv4": { + "forwarding": True, + "address": [{ + "ip": DMZ_ROUTER_IP, + "prefix-length": 24 + }] + } + }, + { + "name": lan_if, + "enabled": True, + "ipv4": { + "forwarding": True, + "address": [{ + "ip": LAN_ROUTER_IP, + "prefix-length": 24 + }] + } } - }, - { - "name": dmz_if, - "enabled": True, - "ipv4": { - "forwarding": True, - "address": [{ - "ip": DMZ_ROUTER_IP, - "prefix-length": 24 + ] + } + }, + "infix-firewall": { + "firewall": { + "default": "wan", + "logging": "all", + "zone": [ + { + "name": "wan", + "description": "External WAN interface - untrusted", + "action": "drop", + "interface": [wan_if], + "port-forward": [{ + "lower": 8080, + "proto": "tcp", + "to": { + "addr": DMZ_SERVER_IP, + "port": 80 + } }] + }, + { + "name": "dmz", + "description": "DMZ network - limited trust", + "action": "reject", + "network": [DMZ_NET], + "service": ["http"] + }, + { + "name": "lan", + "description": "Internal LAN network - trusted", + "action": "accept", + "interface": [lan_if, mgmt_if] } - }, - { - "name": lan_if, - "enabled": True, - "ipv4": { - "forwarding": True, - "address": [{ - "ip": LAN_ROUTER_IP, - "prefix-length": 24 - }] + ], + "policy": [ + { + "name": "loc-to-wan", + "description": "Allow local networks to WAN with SNAT", + "ingress": ["lan", "dmz"], + "egress": ["wan"], + "action": "accept", + "masquerade": True + }, { + "name": "lan-to-dmz", + "description": "Allow LAN access to DMZ services", + "ingress": ["lan"], + "egress": ["dmz"], + "action": "accept", + "service": ["ssh", "http"] } - } - ] - } - }) - - gateway.put_config_dict("infix-firewall", { - "firewall": { - "default": "wan", - "logging": "all", - "zone": [ - { - "name": "wan", - "description": "External WAN interface - untrusted", - "action": "drop", - "interface": [wan_if], - "port-forward": [{ - "lower": 8080, - "proto": "tcp", - "to": { - "addr": DMZ_SERVER_IP, - "port": 80 - } - }] - }, - { - "name": "dmz", - "description": "DMZ network - limited trust", - "action": "reject", - "network": [DMZ_NET], - "service": ["http"] - }, - { - "name": "lan", - "description": "Internal LAN network - trusted", - "action": "accept", - "interface": [lan_if, mgmt_if] - } - ], - "policy": [ - { - "name": "loc-to-wan", - "description": "Allow local networks to WAN with SNAT", - "ingress": ["lan", "dmz"], - "egress": ["wan"], - "action": "accept", - "masquerade": True - }, { - "name": "lan-to-dmz", - "description": "Allow LAN access to DMZ services", - "ingress": ["lan"], - "egress": ["dmz"], - "action": "accept", - "service": ["ssh", "http"] - } - ] + ] + } } }) diff --git a/test/case/hardware/usb/test.py b/test/case/hardware/usb/test.py index cd9d4312f..fba4755c0 100755 --- a/test/case/hardware/usb/test.py +++ b/test/case/hardware/usb/test.py @@ -39,9 +39,11 @@ } components.append(component) - target.put_config_dict("ietf-hardware", { - "hardware": { - "component": components + target.put_config_dicts({ + "ietf-hardware": { + "hardware": { + "component": components + } } }) @@ -61,9 +63,11 @@ } components.append(component) - target.put_config_dict("ietf-hardware", { - "hardware": { - "component": components + target.put_config_dicts({ + "ietf-hardware": { + "hardware": { + "component": components + } } }) @@ -91,9 +95,11 @@ } components.append(component) - target.put_config_dict("ietf-hardware", { - "hardware": { - "component": components + target.put_config_dicts({ + "ietf-hardware": { + "hardware": { + "component": components + } } }) diff --git a/test/case/hardware/usb_two_ports/test.py b/test/case/hardware/usb_two_ports/test.py index 1b815558a..c13085f69 100755 --- a/test/case/hardware/usb_two_ports/test.py +++ b/test/case/hardware/usb_two_ports/test.py @@ -40,9 +40,11 @@ } components.append(component) - target.put_config_dict("ietf-hardware", { - "hardware": { - "component": components + target.put_config_dicts({ + "ietf-hardware": { + "hardware": { + "component": components + } } }) with test.step("Verify that the correct port is locked and the correct one is unlocked"): @@ -68,9 +70,11 @@ } components.append(component) - target.put_config_dict("ietf-hardware", { - "hardware": { - "component": components + target.put_config_dicts({ + "ietf-hardware": { + "hardware": { + "component": components + } } }) with test.step("Verify that the correct port is locked and the correct one is unlocked"): diff --git a/test/case/interfaces/bridge_basic/test.py b/test/case/interfaces/bridge_basic/test.py index ab4b0f715..45fe84c4b 100755 --- a/test/case/interfaces/bridge_basic/test.py +++ b/test/case/interfaces/bridge_basic/test.py @@ -23,7 +23,7 @@ with test.step("Configure single bridge with a single physical port, bridge @ IP 10.0.0.2"): _, tport = env.ltop.xlate("target", "data") - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [{ "name": "br0", @@ -43,7 +43,7 @@ } }] } - }) + }}) with test.step("Verify ping 10.0.0.2 is possible from host:data"): _, hport = env.ltop.xlate("host", "data") diff --git a/test/case/interfaces/bridge_fwd_dual_dut/test.py b/test/case/interfaces/bridge_fwd_dual_dut/test.py index fa7e6fd87..2f0f82142 100755 --- a/test/case/interfaces/bridge_fwd_dual_dut/test.py +++ b/test/case/interfaces/bridge_fwd_dual_dut/test.py @@ -41,7 +41,7 @@ _, tport22 = env.ltop.xlate("dut2", "data2") _, tport2_link = env.ltop.xlate("dut2", "link") - dut1.put_config_dict("ietf-interfaces", { + dut1.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -77,9 +77,9 @@ } ] } - }) + }}) - dut2.put_config_dict("ietf-interfaces", { + dut2.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -123,7 +123,7 @@ } ] } - }) + }}) with test.step("Verify ping 10.0.0.3 and 10.0.0.4 from host:data11"): diff --git a/test/case/interfaces/bridge_fwd_sgl_dut/test.py b/test/case/interfaces/bridge_fwd_sgl_dut/test.py index e89285225..6f442f931 100755 --- a/test/case/interfaces/bridge_fwd_sgl_dut/test.py +++ b/test/case/interfaces/bridge_fwd_sgl_dut/test.py @@ -36,7 +36,7 @@ _, tport1 = env.ltop.xlate("target", "data1") _, tport2 = env.ltop.xlate("target", "data2") - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -60,7 +60,7 @@ } ] } - }) + }}) with test.step("Verify ping from host:data1 to 10.0.0.2"): _, hport1 = env.ltop.xlate("host", "data1") diff --git a/test/case/interfaces/bridge_veth/test.py b/test/case/interfaces/bridge_veth/test.py index dc97e63c4..5ab85e682 100755 --- a/test/case/interfaces/bridge_veth/test.py +++ b/test/case/interfaces/bridge_veth/test.py @@ -26,7 +26,7 @@ with test.step("Configure bridged eth port and veth pair with IP 10.0.0.2"): _, tport = env.ltop.xlate("target", "data") - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -70,7 +70,7 @@ }, ] } - }) + }}) with test.step("Verify ping from host:data to 10.0.0.2"): _, hport = env.ltop.xlate("host", "data") diff --git a/test/case/interfaces/bridge_vlan/test.py b/test/case/interfaces/bridge_vlan/test.py index d722ff0ee..2b325f5b4 100755 --- a/test/case/interfaces/bridge_vlan/test.py +++ b/test/case/interfaces/bridge_vlan/test.py @@ -18,7 +18,7 @@ dut2 = env.attach("dut2", "mgmt") with test.step("Configure DUTs"): - dut1.put_config_dict("ietf-interfaces", { + dut1.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -65,9 +65,9 @@ } ] } - }) + }}) - dut2.put_config_dict("ietf-interfaces", { + dut2.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -96,7 +96,7 @@ } ] } - }) + }}) with test.step("Verify ping from host:data to 10.0.0.2 and 10.0.0.3"): _, hport = env.ltop.xlate("host", "data") diff --git a/test/case/interfaces/bridge_vlan_separation/test.py b/test/case/interfaces/bridge_vlan_separation/test.py index 8f56c1557..fd7272c1e 100755 --- a/test/case/interfaces/bridge_vlan_separation/test.py +++ b/test/case/interfaces/bridge_vlan_separation/test.py @@ -40,7 +40,7 @@ _, tport21 = env.ltop.xlate("dut2", "data2") _, tport22 = env.ltop.xlate("dut2", "link") - dut1.put_config_dict("ietf-interfaces", { + dut1.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -89,9 +89,9 @@ } ] } - }) + }}) - dut2.put_config_dict("ietf-interfaces", { + dut2.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -140,7 +140,7 @@ } ] } - }) + }}) _, hport10 = env.ltop.xlate("host", "data10") diff --git a/test/case/interfaces/dual_bridge/test.py b/test/case/interfaces/dual_bridge/test.py index 49782c274..f444c665e 100755 --- a/test/case/interfaces/dual_bridge/test.py +++ b/test/case/interfaces/dual_bridge/test.py @@ -21,7 +21,7 @@ with test.step("Configure two bridges linked and a veth pair"): _, tport = env.ltop.xlate("target", "data") - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -73,7 +73,7 @@ }, ] } - }) + }}) with test.step("Verify ping from host:data to 10.0.0.2"): _, hport = env.ltop.xlate("host", "data") diff --git a/test/case/interfaces/iface_enable_disable/test.py b/test/case/interfaces/iface_enable_disable/test.py index 76e85d1d6..a1ea3d18d 100755 --- a/test/case/interfaces/iface_enable_disable/test.py +++ b/test/case/interfaces/iface_enable_disable/test.py @@ -56,11 +56,11 @@ def configure_interface(target, iface_name, iface_type=None, enabled=True, ip_ad "bridge": bridge } - target.put_config_dict( "ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ interface_config - ]}}) + ]}}}) with infamy.Test() as test: with test.step("Set up topology and attach to target DUTs"): @@ -102,4 +102,4 @@ def configure_interface(target, iface_name, iface_type=None, enabled=True, ip_ad send_ns.addip(host_address) send_ns.must_reach(target_address) - test.succeed() \ No newline at end of file + test.succeed() diff --git a/test/case/interfaces/iface_phys_address/test.py b/test/case/interfaces/iface_phys_address/test.py index 260e1f698..3d970c78c 100755 --- a/test/case/interfaces/iface_phys_address/test.py +++ b/test/case/interfaces/iface_phys_address/test.py @@ -61,7 +61,7 @@ def reset_mac(tgt, port): }] } } - target.put_config_dict("ietf-interfaces", config) + target.put_config_dicts({"ietf-interfaces": config}) with test.step("Verify target:data has MAC address '02:01:00:c0:ff:ee'"): mac = iface.get_phys_address(target, tport) @@ -85,7 +85,7 @@ def reset_mac(tgt, port): }] } } - target.put_config_dict("ietf-interfaces", config) + target.put_config_dicts({"ietf-interfaces": config}) with test.step("Verify target:data has chassis MAC"): until(lambda: iface.get_phys_address(target, tport) == cmac) @@ -104,7 +104,7 @@ def reset_mac(tgt, port): }] } } - target.put_config_dict("ietf-interfaces", config) + target.put_config_dicts({"ietf-interfaces": config}) with test.step("Verify target:data has chassis MAC + offset"): BMAC = calc_mac(cmac, OFFSET) diff --git a/test/case/interfaces/ifalias/test.py b/test/case/interfaces/ifalias/test.py index 83c12f425..e01e4bfdf 100755 --- a/test/case/interfaces/ifalias/test.py +++ b/test/case/interfaces/ifalias/test.py @@ -16,7 +16,7 @@ with test.step("Set up interface target:data with description"): _, tport = env.ltop.xlate("target", "data") - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -26,7 +26,7 @@ } ] } - }) + }}) with test.step("Verify description can be read back from operational"): text = iface.get_param(target, tport, "description") diff --git a/test/case/interfaces/igmp_basic/test.py b/test/case/interfaces/igmp_basic/test.py index 758a3105a..2ecc23054 100755 --- a/test/case/interfaces/igmp_basic/test.py +++ b/test/case/interfaces/igmp_basic/test.py @@ -46,7 +46,7 @@ _, nojoin = env.ltop.xlate("target", "data3") with test.step("Configure device"): - target.put_config_dict("ietf-interfaces", + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ @@ -95,7 +95,7 @@ ] } - }) + }}) _, hsend = env.ltop.xlate("host", "data1") _, hreceive = env.ltop.xlate("host", "data2") diff --git a/test/case/interfaces/ipv4_address/test.py b/test/case/interfaces/ipv4_address/test.py index 0b8af5502..b1401b406 100755 --- a/test/case/interfaces/ipv4_address/test.py +++ b/test/case/interfaces/ipv4_address/test.py @@ -37,7 +37,7 @@ } } - target.put_config_dict("ietf-interfaces", config) + target.put_config_dicts({"ietf-interfaces": config}) with test.step("Verify '10.10.10.20/24' exists on target:mgmt"): until(lambda: iface.address_exist(target, interface_name, new_ip_address, proto='static')) diff --git a/test/case/interfaces/ipv4_autoconf/test.py b/test/case/interfaces/ipv4_autoconf/test.py index 5555758ab..7d83bff1d 100755 --- a/test/case/interfaces/ipv4_autoconf/test.py +++ b/test/case/interfaces/ipv4_autoconf/test.py @@ -50,7 +50,7 @@ def no_linklocal(target, iface): with test.step("Configure interface target:data with IPv4 ZeroConf IP"): _, tport = env.ltop.xlate("target", "data") - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -62,7 +62,7 @@ def no_linklocal(target, iface): } ] } - }) + }}) with test.step("Verify link-local address exist on target:data"): until(lambda: has_linklocal(target, tport), attempts=30) @@ -70,7 +70,7 @@ def no_linklocal(target, iface): with test.step("Configure target:data with a specific IPv4 ZeroConf IP"): _, tport = env.ltop.xlate("target", "data") - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -84,7 +84,7 @@ def no_linklocal(target, iface): } ] } - }) + }}) with test.step("Verify target:data has link-local address 169.254.42.42"): until(lambda: has_linklocal(target, tport, request="169.254.42.42"), diff --git a/test/case/interfaces/ipv6_address/test.py b/test/case/interfaces/ipv6_address/test.py index dc47e2913..f3372e847 100755 --- a/test/case/interfaces/ipv6_address/test.py +++ b/test/case/interfaces/ipv6_address/test.py @@ -17,7 +17,7 @@ with test.step("Setting up bridge with IPv6 SLAAC for global prefix on target:data"): _, tport = env.ltop.xlate("target", "data") - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -40,7 +40,7 @@ }, ] } - }) + }}) with test.step("Verify using sysctl that 'net.ipv6.conf.br0.autoconf' is 1 on target"): def check_autoconf(): diff --git a/test/case/interfaces/lag_basic/test.py b/test/case/interfaces/lag_basic/test.py index 0e6464626..e4f8ddba9 100755 --- a/test/case/interfaces/lag_basic/test.py +++ b/test/case/interfaces/lag_basic/test.py @@ -113,7 +113,7 @@ def dut_init(dut, mode, addr): net = net_init(dut["mon"], addr) lag = lag_init(mode) - dut.put_config_dict("ietf-interfaces", { + dut.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [{ "name": "lag0", @@ -130,7 +130,7 @@ def dut_init(dut, mode, addr): "lag-port": {"lag": "lag0"} }] + net + lag } - }) + }}) with infamy.Test() as test: diff --git a/test/case/interfaces/lag_failure/test.py b/test/case/interfaces/lag_failure/test.py index fa86381fd..124ffebfe 100755 --- a/test/case/interfaces/lag_failure/test.py +++ b/test/case/interfaces/lag_failure/test.py @@ -98,7 +98,7 @@ def dut_init(dut, addr, peer): """Configure each DUT specific according to LAG mode and peer""" net = net_init(dut["mon"], addr) - dut.put_config_dict("ietf-interfaces", { + dut.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [{ "name": "lag0", @@ -116,7 +116,7 @@ def dut_init(dut, addr, peer): "lag-port": {"lag": "lag0"} }] + net } - }) + }}) with infamy.Test() as test: diff --git a/test/case/interfaces/neighbor_cache/test.py b/test/case/interfaces/neighbor_cache/test.py index 69f413c0e..e1f253c59 100755 --- a/test/case/interfaces/neighbor_cache/test.py +++ b/test/case/interfaces/neighbor_cache/test.py @@ -24,7 +24,7 @@ _, tport = env.ltop.xlate("target", "data") with test.step("Configure static IPv4 ARP and IPv6 neighbor entries on target:data"): - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [{ "name": tport, @@ -42,7 +42,7 @@ } }] } - }) + }}) with test.step("Verify static IPv4 ARP entry is visible in operational state"): until(lambda: iface.neighbor_exist(target, tport, IPV4_NEIGH, IPV4_LLADR, "static")) diff --git a/test/case/interfaces/routing_basic/test.py b/test/case/interfaces/routing_basic/test.py index 636e3f859..fcb7f9ea7 100755 --- a/test/case/interfaces/routing_basic/test.py +++ b/test/case/interfaces/routing_basic/test.py @@ -30,14 +30,14 @@ def iface_cfg(port, subnet, enable_fwd): def config_target(target, tport0, tport1, enable_fwd): """Configure forwarding and addresses for both address families.""" - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ iface_cfg(tport0, SUBNETS[0], enable_fwd), iface_cfg(tport1, SUBNETS[1], enable_fwd), ] } - }) + }}) def setup_host(ns, subnet): """Add IPv4 and IPv6 addresses and default routes.""" diff --git a/test/case/interfaces/static_multicast_filters/test.py b/test/case/interfaces/static_multicast_filters/test.py index afc798371..dfa54c025 100755 --- a/test/case/interfaces/static_multicast_filters/test.py +++ b/test/case/interfaces/static_multicast_filters/test.py @@ -32,7 +32,7 @@ from infamy.util import until def set_static_multicast_filter(target, address, port): - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -54,7 +54,7 @@ def set_static_multicast_filter(target, address, port): } ] } - }) + }}) with infamy.Test() as test: with test.step("Set up topology and attach to target DUTs"): @@ -68,7 +68,7 @@ def set_static_multicast_filter(target, address, port): mac_multicast_group = "01:00:00:01:02:03" with test.step("Configure device without static filter"): - target.put_config_dict("ietf-interfaces", + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ @@ -114,7 +114,7 @@ def set_static_multicast_filter(target, address, port): ] } - }) + }}) _, hsend = env.ltop.xlate("host", "data1") _, hreceive = env.ltop.xlate("host", "data2") diff --git a/test/case/interfaces/veth_delete/test.py b/test/case/interfaces/veth_delete/test.py index d36918d27..67091d984 100755 --- a/test/case/interfaces/veth_delete/test.py +++ b/test/case/interfaces/veth_delete/test.py @@ -27,7 +27,7 @@ veth0b = "veth0b" with test.step("Create VETH pair"): - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -48,7 +48,7 @@ } ] } - }) + }}) with test.step("Verify interfaces 'veth0a' and 'veth0b' exist"): assert iface.exist(target, veth0a), \ @@ -57,7 +57,7 @@ f"Interface <{veth0b}> does not exist." with test.step("Set IP address on target:data1 (dummy op)"): - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [{ "name": f"{data1}", @@ -69,10 +69,10 @@ } }] } - }) + }}) with test.step("Set IP address on target:data2 (dummy op)"): - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [{ "name": f"{data2}", @@ -84,7 +84,7 @@ } }] } - }) + }}) # TODO: need target.del_config_dict() or similar for VETH _pairs_, # because both interfaces must be removed at the same time. diff --git a/test/case/interfaces/vlan_ping/test.py b/test/case/interfaces/vlan_ping/test.py index db2060b22..4fe554388 100755 --- a/test/case/interfaces/vlan_ping/test.py +++ b/test/case/interfaces/vlan_ping/test.py @@ -27,7 +27,7 @@ """) with test.step("Configure VLAN 10 interface on target:data with IP 10.0.0.2"): - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -52,7 +52,7 @@ }, ] } - }) + }}) with test.step("Wait for links to come up"): until(lambda: iface.get_param(target, tport, "oper-status") == "up") diff --git a/test/case/interfaces/vlan_qos/test.py b/test/case/interfaces/vlan_qos/test.py index 4d3ca19cf..c00a2bb1a 100755 --- a/test/case/interfaces/vlan_qos/test.py +++ b/test/case/interfaces/vlan_qos/test.py @@ -64,7 +64,7 @@ def verify_priority_mapping(p): _, hd1 = env.ltop.xlate("host", "data1") with test.step("Apply initial config without priority mapping"): - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -107,7 +107,7 @@ def verify_priority_mapping(p): } ] } - }) + }}) with infamy.IsolatedMacVlan(hd0) as ns0, \ infamy.IsolatedMacVlan(hd1) as ns1 : @@ -134,7 +134,7 @@ def verify_priority_mapping(p): with test.step(desc): ns0.runsh(f"ip link set vlan10 type vlan egress-qos-map 0:{p['pcp']}") - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({"ietf-interfaces": { "interfaces": { "interface": [ { @@ -155,7 +155,7 @@ def verify_priority_mapping(p): }, ] } - }) + }}) ns0.must_reach("192.168.11.2", id=p["id"]) diff --git a/test/case/ptp/port_recovery/test.py b/test/case/ptp/port_recovery/test.py index 740d907ff..49f820ad6 100755 --- a/test/case/ptp/port_recovery/test.py +++ b/test/case/ptp/port_recovery/test.py @@ -63,12 +63,14 @@ def configure_oc(iface, ip, priority1, client_only, dm="e2e"): def set_iface_enabled(target, iface, enabled): - target.put_config_dict("ietf-interfaces", { - "interfaces": { - "interface": [{ - "name": iface, - "enabled": enabled, - }] + target.put_config_dicts({ + "ietf-interfaces": { + "interfaces": { + "interface": [{ + "name": iface, + "enabled": enabled, + }] + } } }) diff --git a/test/case/routing/ospf_basic/test.py b/test/case/routing/ospf_basic/test.py index 0ebb6006c..405abd531 100755 --- a/test/case/routing/ospf_basic/test.py +++ b/test/case/routing/ospf_basic/test.py @@ -20,7 +20,8 @@ def config_target1(target, data, link): - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({ + "ietf-interfaces": { "interfaces": { "interface": [ { @@ -56,135 +57,128 @@ def config_target1(target, data, link): } ] } - }) - target.put_config_dict("ietf-system", { - "system": { - "hostname": "R1" - } - }) - target.put_config_dict("ietf-routing", { - "routing": { - "control-plane-protocols": { - "control-plane-protocol": [{ - "type": "infix-routing:static", - "name": "default", - "static-routes": { - "ipv4": { - "route": [{ - "destination-prefix": "192.168.33.1/32", - "next-hop": { - "special-next-hop": "blackhole" - } - }] + }, + "ietf-routing": { + "routing": { + "control-plane-protocols": { + "control-plane-protocol": [{ + "type": "infix-routing:static", + "name": "default", + "static-routes": { + "ipv4": { + "route": [{ + "destination-prefix": "192.168.33.1/32", + "next-hop": { + "special-next-hop": "blackhole" + } + }] + } } - } - }, { - "type": "infix-routing:ospfv2", - "name": "default", - "ospf": { - "redistribute": { - "redistribute": [{ - "protocol": "static" - }, { - "protocol": "connected" - }] - }, - "areas": { - "area": [{ - "area-id": "0.0.0.0", - "interfaces": { - "interface": [{ - "enabled": True, - "name": link, - "hello-interval": 1, - "dead-interval": 3 - }] - }, - }] + }, { + "type": "infix-routing:ospfv2", + "name": "default", + "ospf": { + "redistribute": { + "redistribute": [{ + "protocol": "static" + }, { + "protocol": "connected" + }] + }, + "areas": { + "area": [{ + "area-id": "0.0.0.0", + "interfaces": { + "interface": [{ + "enabled": True, + "name": link, + "hello-interval": 1, + "dead-interval": 3 + }] + }, + }] + } } - } - }] + }] + } } } }) def config_target2(target, link, data): - target.put_config_dict("ietf-interfaces", { - "interfaces": { - "interface": [{ - "name": link, - "enabled": True, - "ipv4": { - "forwarding": True, - "address": [{ - "ip": "192.168.50.2", - "prefix-length": 24 - }] - } - }, { - "name": data, - "enabled": True, - "ipv4": { + target.put_config_dicts({ + "ietf-interfaces": { + "interfaces": { + "interface": [{ + "name": link, + "enabled": True, + "ipv4": { + "forwarding": True, + "address": [{ + "ip": "192.168.50.2", + "prefix-length": 24 + }] + } + }, { + "name": data, + "enabled": True, + "ipv4": { + "forwarding": True, + "address": [{ + "ip": "192.168.60.1", + "prefix-length": 24 + }] + } + }, { + "name": "lo", + "enabled": True, "forwarding": True, - "address": [{ - "ip": "192.168.60.1", - "prefix-length": 24 - }] - } - }, { - "name": "lo", - "enabled": True, - "forwarding": True, - "ipv4": { - "address": [{ - "ip": "192.168.200.1", - "prefix-length": 32 - }] - } - }] - } - }) - - target.put_config_dict("ietf-system", { - "system": { - "hostname": "R2" - } - }) - target.put_config_dict("ietf-routing", { - "routing": { - "control-plane-protocols": { - "control-plane-protocol": [{ - "type": "infix-routing:ospfv2", - "name": "default", - "ospf": { - "redistribute": { - "redistribute": [{ - "protocol": "connected" - }] - }, - "areas": { - "area": [{ - "area-id": "0.0.0.0", - "interfaces": { - "interface": [{ - "enabled": True, - "name": link, - "hello-interval": 1, - "dead-interval": 3 - }] - } - }] - } + "ipv4": { + "address": [{ + "ip": "192.168.200.1", + "prefix-length": 32 + }] } }] } + }, + "ietf-routing": { + "routing": { + "control-plane-protocols": { + "control-plane-protocol": [{ + "type": "infix-routing:ospfv2", + "name": "default", + "ospf": { + "redistribute": { + "redistribute": [{ + "protocol": "connected" + }] + }, + "areas": { + "area": [{ + "area-id": "0.0.0.0", + "interfaces": { + "interface": [{ + "enabled": True, + "name": link, + "hello-interval": 1, + "dead-interval": 3 + }] + } + }] + } + } + }] + } + } } }) def config_host(target, link): - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({ + "ietf-interfaces": { "interfaces": { "interface": [{ "name": link, @@ -197,11 +191,6 @@ def config_host(target, link): } }] } - }) - - target.put_config_dict("ietf-system", { - "system": { - "hostname": "HOST" } }) diff --git a/test/case/routing/ospf_bfd/test.py b/test/case/routing/ospf_bfd/test.py index 7a6c9a0bd..f08ae6606 100755 --- a/test/case/routing/ospf_bfd/test.py +++ b/test/case/routing/ospf_bfd/test.py @@ -43,7 +43,8 @@ def ifconfig(name, addr, plen): }]} } - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({ + "ietf-interfaces": { "interfaces": { "interface": [ ifconfig("lo", rid, 32), @@ -53,15 +54,8 @@ def ifconfig(name, addr, plen): ifconfig(sif, saddr, 30), ] } - }) - - target.put_config_dict("ietf-system", { - "system": { - "hostname": name, - } - }) - - target.put_config_dict("ietf-routing", { + }, + "ietf-routing": { "routing": { "control-plane-protocols": { "control-plane-protocol": [{ @@ -101,6 +95,7 @@ def ifconfig(name, addr, plen): }] } } + } }) with infamy.Test() as test: diff --git a/test/case/routing/ospf_multiarea/test.py b/test/case/routing/ospf_multiarea/test.py index 6da4a8787..df0f3cf4e 100755 --- a/test/case/routing/ospf_multiarea/test.py +++ b/test/case/routing/ospf_multiarea/test.py @@ -557,7 +557,8 @@ def config_target4(target, ring1, cross, link): def disable_link(target, link): - target.put_config_dict("ietf-interfaces", { + target.put_config_dicts({ + "ietf-interfaces": { "interfaces": { "interface": [ { @@ -565,6 +566,7 @@ def disable_link(target, link): "enabled": False }] } + } }) diff --git a/test/case/routing/ospf_unnumbered_interface/test.py b/test/case/routing/ospf_unnumbered_interface/test.py index 9f66d3d50..d03daffaf 100755 --- a/test/case/routing/ospf_unnumbered_interface/test.py +++ b/test/case/routing/ospf_unnumbered_interface/test.py @@ -18,135 +18,137 @@ # This test tests passive interfaces and unnumbered interfaces. def config_target1(target, data, link): - target.put_config_dict("ietf-interfaces", { - "interfaces": { - "interface": [ - { - "name": data, - "enabled": True, - "ipv4": { - "forwarding": True, - "address": [{ - "ip": "192.168.10.1", - "prefix-length": 24 - }]} - }, - { - "name": link, - "enabled": True, - "ipv4": { - "forwarding": True, - "address": [{ - "ip": "10.0.0.1", - "prefix-length": 32 - }] - } - }, - { - "name": "lo", - "enabled": True, - "ipv4": { - "address": [{ - "ip": "192.168.100.1", - "prefix-length": 32 - }] - } - } - ] - } - }) - - target.put_config_dict("ietf-routing", { - "routing": { - "control-plane-protocols": { - "control-plane-protocol": [{ - "type": "infix-routing:ospfv2", - "name": "default", - "ospf": { - "areas": { - "area": [{ - "area-id": "0.0.0.0", - "interfaces": - { - "interface": [{ - "name": link, - "hello-interval": 1, - "dead-interval": 3, - "interface-type": "point-to-point" - }, { - "name": data, - "passive": True - }, { - "name": "lo", - "passive": True - }] - }, - }] - } - } - }] - } - } - }) - - -def config_target2(target, link): - target.put_config_dict("ietf-interfaces", { - "interfaces": { - "interface": [ - { - "name": link, - "enabled": True, - "ipv4": { - "forwarding": True, - "address": [{ - "ip": "10.0.0.2", - "prefix-length": 32 - }] - } - }, - { - "name": "lo", - "enabled": True, - "forwarding": True, - "ipv4": { - "address": [{ - "ip": "192.168.200.1", - "prefix-length": 32 - }] + target.put_config_dicts({ + "ietf-interfaces": { + "interfaces": { + "interface": [ + { + "name": data, + "enabled": True, + "ipv4": { + "forwarding": True, + "address": [{ + "ip": "192.168.10.1", + "prefix-length": 24 + }]} + }, + { + "name": link, + "enabled": True, + "ipv4": { + "forwarding": True, + "address": [{ + "ip": "10.0.0.1", + "prefix-length": 32 + }] + } + }, + { + "name": "lo", + "enabled": True, + "ipv4": { + "address": [{ + "ip": "192.168.100.1", + "prefix-length": 32 + }] + } } - } - ] - } - }) - - target.put_config_dict("ietf-routing", { - "routing": { - "control-plane-protocols": { - "control-plane-protocol": [ - { + ] + } + }, + "ietf-routing": { + "routing": { + "control-plane-protocols": { + "control-plane-protocol": [{ "type": "infix-routing:ospfv2", "name": "default", "ospf": { "areas": { "area": [{ "area-id": "0.0.0.0", - "interfaces": { + "interfaces": + { "interface": [{ "name": link, "hello-interval": 1, "dead-interval": 3, "interface-type": "point-to-point" + }, { + "name": data, + "passive": True }, { "name": "lo", "passive": True }] - } + }, + }] + } + } + }] + } + } + } + }) + + +def config_target2(target, link): + target.put_config_dicts({ + "ietf-interfaces": { + "interfaces": { + "interface": [ + { + "name": link, + "enabled": True, + "ipv4": { + "forwarding": True, + "address": [{ + "ip": "10.0.0.2", + "prefix-length": 32 + }] + } + }, + { + "name": "lo", + "enabled": True, + "forwarding": True, + "ipv4": { + "address": [{ + "ip": "192.168.200.1", + "prefix-length": 32 }] } } - } - ] + ] + } + }, + "ietf-routing": { + "routing": { + "control-plane-protocols": { + "control-plane-protocol": [ + { + "type": "infix-routing:ospfv2", + "name": "default", + "ospf": { + "areas": { + "area": [{ + "area-id": "0.0.0.0", + "interfaces": { + "interface": [{ + "name": link, + "hello-interval": 1, + "dead-interval": 3, + "interface-type": "point-to-point" + }, { + "name": "lo", + "passive": True + }] + } + }] + } + } + } + ] + } } } }) diff --git a/test/case/services/lldp/lldp_enable_disable/test.py b/test/case/services/lldp/lldp_enable_disable/test.py index ae849e974..7f36f4034 100755 --- a/test/case/services/lldp/lldp_enable_disable/test.py +++ b/test/case/services/lldp/lldp_enable_disable/test.py @@ -25,10 +25,7 @@ } ] } - } - }) - - target.put_config_dicts({ + }, "ieee802-dot1ab-lldp": { "lldp": { "enabled": False diff --git a/test/case/services/mdns/mdns_allow_deny/test.py b/test/case/services/mdns/mdns_allow_deny/test.py index 8fa5707aa..0311d9168 100755 --- a/test/case/services/mdns/mdns_allow_deny/test.py +++ b/test/case/services/mdns/mdns_allow_deny/test.py @@ -54,7 +54,7 @@ def check(expected, allow=None, deny=None): if deny: mdns_config["mdns"]["interfaces"]["deny"] = deny - dut.put_config_dict("infix-services", mdns_config) + dut.put_config_dicts({"infix-services": mdns_config}) actual = mdns_scan() if actual != tuple(expected): diff --git a/test/case/services/mdns/mdns_enable_disable/test.py b/test/case/services/mdns/mdns_enable_disable/test.py index a76840890..5e7d32297 100755 --- a/test/case/services/mdns/mdns_enable_disable/test.py +++ b/test/case/services/mdns/mdns_enable_disable/test.py @@ -34,10 +34,7 @@ } ] } - } - }) - - target.put_config_dicts({ + }, "infix-services": { "mdns": { "enabled": False diff --git a/test/case/services/mdns/mdns_reflector/test.py b/test/case/services/mdns/mdns_reflector/test.py index 65d38764d..48292e2e0 100755 --- a/test/case/services/mdns/mdns_reflector/test.py +++ b/test/case/services/mdns/mdns_reflector/test.py @@ -41,10 +41,12 @@ def mdns_reflect_test(): def disable_reflector(): """Disable mDNS reflector""" - dut.put_config_dict("infix-services", { - "mdns": { - "reflector": { - "enabled": False + dut.put_config_dicts({ + "infix-services": { + "mdns": { + "reflector": { + "enabled": False + } } } }) diff --git a/test/case/services/ssh/ssh_key_authentication/test.py b/test/case/services/ssh/ssh_key_authentication/test.py index 0c5a9bbcd..d5b3306f4 100755 --- a/test/case/services/ssh/ssh_key_authentication/test.py +++ b/test/case/services/ssh/ssh_key_authentication/test.py @@ -52,22 +52,24 @@ # Upon attachment, target reverts to `test-config`, in which # the SSH service is enabled, hence we do not have to # explicitly enable it here. - target.put_config_dict("ietf-system", { - "system": { - "authentication": { - "user": [ - { - "name": USER, - "authorized-key": [ - { - "name":"guest-ssh-key", - "algorithm": "ssh-rsa", - "key-data": KEY["public"] - } - ], - "infix-system:shell":"bash" - } - ] + target.put_config_dicts({ + "ietf-system": { + "system": { + "authentication": { + "user": [ + { + "name": USER, + "authorized-key": [ + { + "name":"guest-ssh-key", + "algorithm": "ssh-rsa", + "key-data": KEY["public"] + } + ], + "infix-system:shell":"bash" + } + ] + } } } }) diff --git a/test/case/services/ssh/ssh_server_config/test.py b/test/case/services/ssh/ssh_server_config/test.py index d8026135b..f5bd36a5a 100755 --- a/test/case/services/ssh/ssh_server_config/test.py +++ b/test/case/services/ssh/ssh_server_config/test.py @@ -131,9 +131,11 @@ assert ns88.runsh(f"ssh-keyscan -p {SSH_PORT_1} {SSH_ADDRESS_2}").returncode == 1, "SSH is accessable on wrong interface" with test.step("Disable SSH server"): - target.put_config_dict("infix-services", { - "ssh": { - "enabled": False + target.put_config_dicts({ + "infix-services": { + "ssh": { + "enabled": False + } } }) assert(ns77.run( diff --git a/test/case/system/add_delete_user/test.py b/test/case/system/add_delete_user/test.py index 532cf5de2..448df181c 100755 --- a/test/case/system/add_delete_user/test.py +++ b/test/case/system/add_delete_user/test.py @@ -23,16 +23,18 @@ tgtssh = env.attach("target", "mgmt", "ssh") with test.step("Add new user 'newuser01' with password 'newuser01password'"): - target.put_config_dict("ietf-system", { - "system": { - "authentication": { - "user": [ - { - "name": username, - "password": hashed_password, - "shell": "infix-system:bash" - } - ] + target.put_config_dicts({ + "ietf-system": { + "system": { + "authentication": { + "user": [ + { + "name": username, + "password": hashed_password, + "shell": "infix-system:bash" + } + ] + } } } }) diff --git a/test/case/system/hostname/test.py b/test/case/system/hostname/test.py index e45226ddc..9c57f2653 100755 --- a/test/case/system/hostname/test.py +++ b/test/case/system/hostname/test.py @@ -19,9 +19,11 @@ NEW = "h0stn4m3" with test.step("Set hostname to 'h0stn4m3'"): - target.put_config_dict("ietf-system", { - "system": { - "hostname": NEW, + target.put_config_dicts({ + "ietf-system": { + "system": { + "hostname": NEW, + } } }) @@ -30,9 +32,11 @@ assert running["system"]["hostname"] == NEW with test.step("Set hostname to '%h-%m'"): - target.put_config_dict("ietf-system", { - "system": { - "hostname": FMT, + target.put_config_dicts({ + "ietf-system": { + "system": { + "hostname": FMT, + } } }) diff --git a/test/case/system/user_admin/test.py b/test/case/system/user_admin/test.py index defad1bb1..d6b39ffb6 100755 --- a/test/case/system/user_admin/test.py +++ b/test/case/system/user_admin/test.py @@ -23,16 +23,18 @@ USER = "jacky" PASS = "$1$3aR7Bq2u$G9kV.8AALtKkCnaAXFyu6/" - target.put_config_dict("ietf-system", { - "system": { - "authentication": { - "user": [ - { - "name": USER, - "password": PASS, - "shell": "infix-system:bash" - } - ] + target.put_config_dicts({ + "ietf-system": { + "system": { + "authentication": { + "user": [ + { + "name": USER, + "password": PASS, + "shell": "infix-system:bash" + } + ] + } } } }) @@ -60,7 +62,7 @@ if group["name"] == "admin": if USER not in group["user-name"]: group["user-name"].append(USER) - target.put_config_dict("ietf-netconf-acm", nacm) + target.put_config_dicts({"ietf-netconf-acm": nacm}) with test.step("Verify user jacky is now in wheel group (in Linux)"): if not tgtssh.runsh(f"grep wheel /etc/group | grep '{USER}'"): @@ -79,7 +81,7 @@ if user['name'] == USER: user['password'] = "$factory$" break - target.put_config_dict("ietf-system", running) + target.put_config_dicts({"ietf-system": running}) with test.step("Verify user jacky exists and has new password"): operational = target.get_data("/ietf-system:system/authentication") diff --git a/test/infamy/netconf.py b/test/infamy/netconf.py index 1b59f89e3..8d000122d 100644 --- a/test/infamy/netconf.py +++ b/test/infamy/netconf.py @@ -330,8 +330,17 @@ def put_config_dicts(self, models, retries=3): # print(f"Send new XML config: {config}") return self.put_config(config, retries=retries) - def put_config_dict(self, modname, edit, retries=3): - """Convert Python dictionary to XMl and send as configuration""" + def patch_config(self, modname, edit, retries=3): + """Merge configuration for a single model to running-config + + For NETCONF, edit-config already has proper NACM support, so a + single-model merge is sufficient. + + Args: + modname: YANG module name + edit: Configuration dictionary + retries: Number of retry attempts on failure (default 3) + """ try: mod = self.ly.get_module(modname) except libyang.util.LibyangError: @@ -343,19 +352,6 @@ def put_config_dict(self, modname, edit, retries=3): # print(f"Send new XML config: {config}") return self.put_config(config, retries=retries) - def patch_config(self, modname, edit, retries=3): - """Merge configuration for a single model to running-config - - For NETCONF, this is identical to put_config_dict() since - edit-config already has proper NACM support. - - Args: - modname: YANG module name - edit: Configuration dictionary - retries: Number of retry attempts on failure (default 3) - """ - return self.put_config_dict(modname, edit, retries=retries) - def call(self, call): """Call RPC, XML version""" return self.ncc.dispatch(call) diff --git a/test/infamy/restconf.py b/test/infamy/restconf.py index b59f6407b..2e4bdce9c 100644 --- a/test/infamy/restconf.py +++ b/test/infamy/restconf.py @@ -343,61 +343,6 @@ def put_config_dicts(self, models, retries=3): # Copy candidate to running (acts as "commit", triggers sysrepo callbacks) self.copy("candidate", "running") - def put_config_dict(self, xpath, edit, retries=3): - """PATCH configuration for a single model to running-config - - Uses candidate datastore + copy to running to trigger sysrepo - change callbacks, similar to how NETCONF edit-config + commit works. - - Args: - xpath: YANG module name - edit: Configuration dictionary - retries: Number of retry attempts on failure (default 3) - """ - try: - mod = self.lyctx.get_module(xpath) - except libyang.util.LibyangError: - raise Exception(f"YANG model '{xpath}' not found on device. " - f"Model may not be installed or enabled. " - f"Available models can be checked with get_schema_list()") from None - - # Copy running to candidate first (to preserve existing config) - self.copy("running", "candidate") - - # Parse and convert to get proper structure with module prefix - lyd = mod.parse_data_dict(edit, no_state=True, validate=False) - patch_data = json.loads(lyd.print_mem("json", with_siblings=True, pretty=False)) - - # PATCH to candidate datastore - url = f"{self.restconf_url}/ds/ietf-datastores:candidate" - last_error = None - for attempt in range(0, retries): - try: - response = requests_workaround_patch( - url, - json=patch_data, - headers=self.headers, - auth=self.auth, - verify=False - ) - response.raise_for_status() - last_error = None - break - except Exception as e: - last_error = e - if attempt < retries - 1: - print(f"Failed PATCH to {url}: {e} Retrying ...") - time.sleep(1) - else: - print(f"Failed PATCH to {url}: {e}") - continue - - if last_error is not None: - raise last_error - - # Copy candidate to running (acts as "commit", triggers sysrepo callbacks) - self.copy("candidate", "running") - def patch_config(self, xpath, edit, retries=3): """PATCH configuration directly to running datastore diff --git a/test/infamy/transport.py b/test/infamy/transport.py index e660e3e47..04efa387d 100644 --- a/test/infamy/transport.py +++ b/test/infamy/transport.py @@ -22,10 +22,6 @@ def get_data(self, xpath=None, parse=True): def get_config_dict(self, modname): pass - @abstractmethod - def put_config_dict(self, modname, edit): - pass - @abstractmethod def patch_config(self, modname, edit): pass