From 4b99f0bb9c7bee1749114b5c358fc9fc1aa6850b Mon Sep 17 00:00:00 2001 From: Oliver Gorwits Date: Wed, 19 Jul 2023 11:16:41 +0100 Subject: [PATCH] #1064 implement setting of tags on discovery based on config --- .../Worker/Plugin/Discover/Properties/Tags.pm | 83 +++++++++++++++++++ share/config.yml | 7 ++ 2 files changed, 90 insertions(+) create mode 100644 lib/App/Netdisco/Worker/Plugin/Discover/Properties/Tags.pm diff --git a/lib/App/Netdisco/Worker/Plugin/Discover/Properties/Tags.pm b/lib/App/Netdisco/Worker/Plugin/Discover/Properties/Tags.pm new file mode 100644 index 00000000..b1ca8eb0 --- /dev/null +++ b/lib/App/Netdisco/Worker/Plugin/Discover/Properties/Tags.pm @@ -0,0 +1,83 @@ +package App::Netdisco::Worker::Plugin::Discover::Properties::Tags; + +use Dancer ':syntax'; +use App::Netdisco::Worker::Plugin; +use aliased 'App::Netdisco::Worker::Status'; + +use Dancer::Plugin::DBIC 'schema'; +use App::Netdisco::Util::Web 'sort_port'; +use App::Netdisco::Util::Permission 'acl_matches'; + +register_worker({ phase => 'main' }, sub { + my ($job, $workerconf) = @_; + my $device = $job->device; + + return unless setting('tags') + and ref {} eq ref setting('tags') + and exists setting('tags')->{'device'} + and ref {} eq ref setting('tags')->{'device'}; + + my $tags = setting('tags')->{'device'}; + my @tags_to_set = (); + + foreach my $tag (sort keys %$tags) { + # lhs is tag, rhs matches device + next unless acl_matches($device, $tags->{$tag}); + push @tags_to_set, $tag; + } + + $device->update({ tags => \@tags_to_set }); + debug sprintf ' [%s] properties - set %s tag%s', + $device->ip, scalar @tags_to_set, (scalar @tags_to_set > 1); +}); + +register_worker({ phase => 'main' }, sub { + my ($job, $workerconf) = @_; + my $device = $job->device; + + return unless setting('tags') + and ref {} eq ref setting('tags') + and exists setting('tags')->{'device_port'} + and ref {} eq ref setting('tags')->{'device_port'}; + + my $tags = setting('tags')->{'device_port'}; + my %tags_to_set = (); + my $port_map = {}; + + # hook data appears after the Properties workers which are in early phase + map { push @{ $port_map->{ $_->{port} } }, $_ } + @{ vars->{'hook_data'}->{'ports'} || [] }, + grep { defined $_->{port} } @{ vars->{'hook_data'}->{'device_ips'} || [] }; + + foreach my $tag (sort keys %$tags) { + # lhs is tag, rhs is acl map + my $maps = (ref {} eq ref $tags->{$tag}) ? [ $tags->{$tag} ] + : ( $tags->{$tag} || [] ); + + foreach my $map (@$maps) { + foreach my $key (sort keys %$map) { + # lhs matches device, rhs matches port + next unless $key and $map->{$key}; + next unless acl_matches($device, $key); + + foreach my $port (sort { sort_port($a, $b) } keys %$port_map) { + next unless acl_matches($port_map->{$port}, $map->{$key}); + + push @{ $tags_to_set{$port} }, $tag; + } + } + } + } + + foreach my $port (sort keys %tags_to_set) { + schema('netdisco')->resultset('DevicePort') + ->search({ip => $device->ip, port => $port}, {for => 'update'}) + ->update({ tags => ( $tags_to_set{$port} || [] ) }); + + debug sprintf ' [%s] properties - set %s tag%s on port %s', + $device->ip, scalar @{ $tags_to_set{$port} }, + (scalar @{ $tags_to_set{$port} } > 1), $port; + } +}); + +true; diff --git a/share/config.yml b/share/config.yml index e899b52e..67a83b67 100644 --- a/share/config.yml +++ b/share/config.yml @@ -336,6 +336,12 @@ use_legacy_sshcollector: false custom_fields: device: [] device_port: [] +tags: + device: {} + device_port: {} +hide_tags: + device: [] + device_port: [] get_credentials: "" bulkwalk_off: false bulkwalk_no: [] @@ -516,6 +522,7 @@ worker_plugins: - 'Discover::PortProperties' - 'Discover::PortProperties::PortAccessEntity' - 'Discover::Properties' + - 'Discover::Properties::Tags' - 'Discover::VLANs' - 'Discover::Wireless' - 'Discover::WithNodes'