From a5d2de649166a5583c1f9989dac3492cbdf8f97b Mon Sep 17 00:00:00 2001 From: dzenichev Date: Mon, 8 Aug 2022 15:50:12 +0200 Subject: [PATCH] TT#168102 ngcp-instances-validator: Fix link interface check * check doesn't work for 'host' type * check doesn't test 'type' interface * introduce test for command Change-Id: I6a9c37a874aa219f33fde10fb0991f7450906443 (cherry picked from commit dc1213ad7a25396fc2de3c8fabda9d0850b4ab59) --- sbin/ngcp-instances-validator | 25 +- t/Dockerfile | 4 +- t/fixtures/instances-validator/wrong_link.yml | 216 ++++++++++++++++++ .../wrong_link_interfaces.yml | 216 ++++++++++++++++++ t/pytest.ini | 1 + t/test_ngcp_instances_validator.py | 69 ++++++ 6 files changed, 525 insertions(+), 6 deletions(-) create mode 100644 t/fixtures/instances-validator/wrong_link.yml create mode 100644 t/fixtures/instances-validator/wrong_link_interfaces.yml create mode 100644 t/test_ngcp_instances_validator.py diff --git a/sbin/ngcp-instances-validator b/sbin/ngcp-instances-validator index 1419a048..49d7db1e 100755 --- a/sbin/ngcp-instances-validator +++ b/sbin/ngcp-instances-validator @@ -67,6 +67,7 @@ if (exists $yaml->{instances}) { # Iterate through the list of connection links. foreach my $conn_link (@{$conn->{links}}) { my $conn_link_name = $conn_link->{name}; + my $remote; # Check that each connection of type instance/host indeed # exists. @@ -75,25 +76,41 @@ if (exists $yaml->{instances}) { warn " - [instances/$instance->{name}/$conn->{name}/$conn_link_name] Missing required instance for connection link\n"; $errors ++; } + $remote = first { $_->{name} eq $conn_link_name } @{$yaml->{instances}}; } elsif ($conn_link->{type} eq 'host') { if (none { $_ eq $conn_link_name } @host_names) { warn " - [instances/$instance->{name}/$conn->{name}/$conn_link_name] Missing required host for connection link\n"; $errors ++; } + $remote = $yaml->{hosts}->{$conn_link_name}; } # Iterate through the list of link interfaces. foreach my $link_iface (@{$conn_link->{interfaces}}) { my $link_iface_name = $link_iface->{name}; - my $found = 0; - my $remote_instance = first { $_->{name} eq $conn_link_name } @{$yaml->{instances}}; + my $link_iface_type = $link_iface->{type}; - # Requested instance must indeed have requested interface, + # Requested link must indeed have requested interface, # otherwise not possible to interconnect. - if (none { $_->{name} eq $link_iface_name } @{$remote_instance->{interfaces}}) { + if ($conn_link->{type} eq 'instance' ? + none { $_->{name} eq $link_iface_name } @{$remote->{interfaces}} : + none { $_ eq $link_iface_name } @{$remote->{interfaces}}) + { warn " - [instances/$instance->{name}/$conn->{name}/$conn_link_name/$link_iface_name] Missing required link interface\n"; $errors ++; } + + # Check type interface + my $iface; + if ($conn_link->{type} eq 'instance') { + $iface = first { $_->{name} eq $link_iface_name } @{$remote->{interfaces}}; + } else { + $iface = $remote->{$link_iface_name}; + } + if (none { $_ eq $link_iface_type } @{$iface->{type}}) { + warn " - [instances/$instance->{name}/$conn->{name}/$conn_link_name/$link_iface_name] Missing type $link_iface_type on link interface\n"; + $errors ++; + } } } diff --git a/t/Dockerfile b/t/Dockerfile index 7b58ade3..16b427a8 100644 --- a/t/Dockerfile +++ b/t/Dockerfile @@ -5,12 +5,12 @@ FROM docker.mgm.sipwise.com/sipwise-bullseye:latest # is updated with the current date. It will force refresh of all # of the base images and things like `apt-get update` won't be using # old cached versions when the Dockerfile is built. -ENV REFRESHED_AT 2021-10-04 +ENV REFRESHED_AT 2022-08-08 RUN apt-get update && apt-get install --assume-yes libhash-merge-perl libtemplate-perl \ libyaml-libyaml-perl libyaml-tiny-perl libyaml-perl \ libdata-validate-ip-perl libio-interface-perl libregexp-ipv6-perl \ - fakeroot git lsof make strace \ + fakeroot git lsof make strace pkwalify \ python3-pytest python3-junitxml file RUN echo './t/testrunner' >>/root/.bash_history diff --git a/t/fixtures/instances-validator/wrong_link.yml b/t/fixtures/instances-validator/wrong_link.yml new file mode 100644 index 00000000..b20c6059 --- /dev/null +++ b/t/fixtures/instances-validator/wrong_link.yml @@ -0,0 +1,216 @@ +--- +hosts: + sp1: + dbnode: '1' + interfaces: + - lo + - neth0 + - neth1 + - neth2 + lo: + advertised_ip: [] + hwaddr: 00:00:00:00:00:00 + ip: 127.0.0.1 + netmask: 255.0.0.0 + shared_ip: [] + shared_v6ip: [] + type: + - web_ext + - web_int + - aux_ext + - ssh_ext + - api_int + - stor_int + v6ip: ::1 + v6netmask: 128 + neth0: + dhcp: yes + dns_nameservers: + - 10.15.20.30 + gateway: 192.168.211.1 + hwaddr: 08:00:27:9c:a3:22 + ip: 10.0.2.15 + netmask: 255.255.255.0 + shared_ip: + shared_v6ip: + type: + - ssh_ext + - web_ext + - web_int + neth1: + cluster_sets: + - default + hwaddr: da:52:ca:90:8f:63 + ip: 192.168.255.251 + netmask: 255.255.255.248 + shared_ip: + - 192.168.255.250 + shared_v6ip: + type: + - ssh_ext + - ha_int + - boot_int + - sip_int + - rtp_int + neth2: + hwaddr: 0a:00:27:45:bb:ce + ip: 192.168.2.173 + netmask: 255.255.255.0 + shared_ip: + - 192.168.2.151 + shared_v6ip: + type: + - ssh_ext + - web_ext + - web_int + - sip_ext + - rtp_ext + - mon_ext + peer: sp2 + role: + - proxy + - lb + - mgmt + - rtp + - db + - storage + status: online + swraiddevices: [] + sysdescr: '' + syslocation: '' + sysname: '' + sp2: + dbnode: '2' + interfaces: + - lo + - neth0 + - neth1 + - neth2 + lo: + cluster_sets: + - default + hwaddr: 00:00:00:00:00:00 + ip: 127.0.0.1 + netmask: 255.0.0.0 + shared_ip: [] + shared_v6ip: [] + type: + - api_int + - stor_int + - web_int + - web_ext + - aux_ext + v6ip: ::1 + neth0: + dhcp: yes + dns_nameservers: + - 10.15.20.30 + gateway: 192.168.211.1 + hwaddr: 08:00:27:75:e6:93 + ip: 10.0.3.15 + netmask: 255.255.255.0 + shared_ip: + shared_v6ip: + type: + - ssh_ext + - web_int + - web_ext + neth1: + cluster_sets: + - default + hwaddr: 00:00:00:00:00:00 + ip: 192.168.255.252 + netmask: 255.255.255.248 + shared_ip: + - 192.168.255.250 + shared_v6ip: + type: + - ssh_ext + - ha_int + - boot_int + - sip_int + - rtp_int + neth2: + hwaddr: 0a:00:27:45:bb:66 + ip: 192.168.2.177 + netmask: 255.255.255.0 + shared_ip: + - 192.168.2.151 + shared_v6ip: + type: + - ssh_ext + - web_ext + - web_int + - sip_ext + - rtp_ext + - mon_ext + peer: sp1 + role: + - storage + - proxy + - lb + - mgmt + - rtp + - db + status: online + swraiddevices: [] + sysdescr: '' + syslocation: '' + sysname: '' +instances: + - name: A + service: kamailio-lb + host: sp2 + status: online + label: lb + interfaces: + - name: neth2 + ip: 192.168.2.250 + type: + - sip_ext + - name: neth1 + ip: 192.168.255.253 + type: + - sip_int + connections: + - name: proxy + algorithm: serial + links: + - type: instance + name: fake + interfaces: + - name: neth1 + type: sip_int + - name: B + service: kamailio-lb + host: sp1 + label: lb + status: online + interfaces: + - name: neth2 + ip: 192.168.2.251 + type: + - sip_ext + - name: neth1 + ip: 192.168.255.254 + type: + - sip_int + connections: + - name: proxy + algorithm: serial + links: + - type: host + name: sp3 + interfaces: + - name: neth1 + type: sip_int + - name: C + service: kamailio-proxy + host: sp1 + status: online + label: proxy + interfaces: + - name: neth1 + ip: 192.168.255.249 + type: + - sip_int diff --git a/t/fixtures/instances-validator/wrong_link_interfaces.yml b/t/fixtures/instances-validator/wrong_link_interfaces.yml new file mode 100644 index 00000000..78c94317 --- /dev/null +++ b/t/fixtures/instances-validator/wrong_link_interfaces.yml @@ -0,0 +1,216 @@ +--- +hosts: + sp1: + dbnode: '1' + interfaces: + - lo + - neth0 + - neth1 + - neth2 + lo: + advertised_ip: [] + hwaddr: 00:00:00:00:00:00 + ip: 127.0.0.1 + netmask: 255.0.0.0 + shared_ip: [] + shared_v6ip: [] + type: + - web_ext + - web_int + - aux_ext + - ssh_ext + - api_int + - stor_int + v6ip: ::1 + v6netmask: 128 + neth0: + dhcp: yes + dns_nameservers: + - 10.15.20.30 + gateway: 192.168.211.1 + hwaddr: 08:00:27:9c:a3:22 + ip: 10.0.2.15 + netmask: 255.255.255.0 + shared_ip: + shared_v6ip: + type: + - ssh_ext + - web_ext + - web_int + neth1: + cluster_sets: + - default + hwaddr: da:52:ca:90:8f:63 + ip: 192.168.255.251 + netmask: 255.255.255.248 + shared_ip: + - 192.168.255.250 + shared_v6ip: + type: + - ssh_ext + - ha_int + - boot_int + - sip_int + - rtp_int + neth2: + hwaddr: 0a:00:27:45:bb:ce + ip: 192.168.2.173 + netmask: 255.255.255.0 + shared_ip: + - 192.168.2.151 + shared_v6ip: + type: + - ssh_ext + - web_ext + - web_int + - sip_ext + - rtp_ext + - mon_ext + peer: sp2 + role: + - proxy + - lb + - mgmt + - rtp + - db + - storage + status: online + swraiddevices: [] + sysdescr: '' + syslocation: '' + sysname: '' + sp2: + dbnode: '2' + interfaces: + - lo + - neth0 + - neth1 + - neth2 + lo: + cluster_sets: + - default + hwaddr: 00:00:00:00:00:00 + ip: 127.0.0.1 + netmask: 255.0.0.0 + shared_ip: [] + shared_v6ip: [] + type: + - api_int + - stor_int + - web_int + - web_ext + - aux_ext + v6ip: ::1 + neth0: + dhcp: yes + dns_nameservers: + - 10.15.20.30 + gateway: 192.168.211.1 + hwaddr: 08:00:27:75:e6:93 + ip: 10.0.3.15 + netmask: 255.255.255.0 + shared_ip: + shared_v6ip: + type: + - ssh_ext + - web_int + - web_ext + neth1: + cluster_sets: + - default + hwaddr: 00:00:00:00:00:00 + ip: 192.168.255.252 + netmask: 255.255.255.248 + shared_ip: + - 192.168.255.250 + shared_v6ip: + type: + - ssh_ext + - ha_int + - boot_int + - sip_int + - rtp_int + neth2: + hwaddr: 0a:00:27:45:bb:66 + ip: 192.168.2.177 + netmask: 255.255.255.0 + shared_ip: + - 192.168.2.151 + shared_v6ip: + type: + - ssh_ext + - web_ext + - web_int + - sip_ext + - rtp_ext + - mon_ext + peer: sp1 + role: + - storage + - proxy + - lb + - mgmt + - rtp + - db + status: online + swraiddevices: [] + sysdescr: '' + syslocation: '' + sysname: '' +instances: + - name: A + service: kamailio-lb + host: sp2 + status: online + label: lb + interfaces: + - name: neth2 + ip: 192.168.2.250 + type: + - sip_ext + - name: neth1 + ip: 192.168.255.253 + type: + - sip_int + connections: + - name: proxy + algorithm: serial + links: + - type: instance + name: C + interfaces: + - name: neth1 + type: sip_X + - name: B + service: kamailio-lb + host: sp1 + label: lb + status: online + interfaces: + - name: neth2 + ip: 192.168.2.251 + type: + - sip_ext + - name: neth1 + ip: 192.168.255.254 + type: + - sip_int + connections: + - name: proxy + algorithm: serial + links: + - type: host + name: sp2 + interfaces: + - name: neth1 + type: sip_X + - name: C + service: kamailio-proxy + host: sp1 + status: online + label: proxy + interfaces: + - name: neth1 + ip: 192.168.255.249 + type: + - sip_int diff --git a/t/pytest.ini b/t/pytest.ini index 46b23001..4269e521 100644 --- a/t/pytest.ini +++ b/t/pytest.ini @@ -21,3 +21,4 @@ markers = tt_47255 tt_51601 tt_76851 + tt_168102 diff --git a/t/test_ngcp_instances_validator.py b/t/test_ngcp_instances_validator.py new file mode 100644 index 00000000..1a42f821 --- /dev/null +++ b/t/test_ngcp_instances_validator.py @@ -0,0 +1,69 @@ +#!/usr/bin/env py.test-3 +import re + +import pytest + +CMD = "../sbin/ngcp-instances-validator" + + +def test_help(cli): + cmd = [CMD, "--help"] + out = cli(*cmd) + assert out.exitcode == 0 + + +def test_no_network(cli): + cmd = [CMD] + out = cli(*cmd) + assert out.exitcode != 0 + assert re.search( + "Can't open '/etc/ngcp-config/network.yml' for input", out.stderr + ) + + +def test_no_instances(cli): + cmd = [CMD, "--network-file=./fixtures/repos/network_pro.yml"] + out = cli(*cmd) + assert out.exitcode == 0 + + +@pytest.mark.tt_168102 +def test_pro_instances(cli): + cmd = [CMD, "--network-file=./fixtures/repos/network_pro_instances.yml"] + out = cli(*cmd) + assert out.exitcode == 0 + + +def test_wrong_link(cli): + cmd = [CMD, "--network-file=./fixtures/instances-validator/wrong_link.yml"] + out = cli(*cmd) + assert out.exitcode != 0 + msg = "Missing required instance for connection link" + assert re.search( + rf"\[instances/A/proxy/fake\] {msg}", + out.stderr, + ) + msg = "Missing required host for connection link" + assert re.search( + rf"\[instances/B/proxy/sp3\] {msg}", + out.stderr, + ) + + +def test_wrong_link_interfaces(cli): + file = "wrong_link_interfaces" + cmd = [ + CMD, + f"--network-file=./fixtures/instances-validator/{file}.yml", + ] + out = cli(*cmd) + assert out.exitcode != 0 + msg = "Missing type sip_X on link interface" + assert re.search( + rf"\[instances/A/proxy/C/neth1\] {msg}", + out.stderr, + ) + assert re.search( + rf"\[instances/B/proxy/sp2/neth1\] {msg}", + out.stderr, + )