diff --git a/lib/App/Netdisco/JobQueue/PostgreSQL.pm b/lib/App/Netdisco/JobQueue/PostgreSQL.pm index a4dcb52b..30193eca 100644 --- a/lib/App/Netdisco/JobQueue/PostgreSQL.pm +++ b/lib/App/Netdisco/JobQueue/PostgreSQL.pm @@ -338,12 +338,18 @@ sub jq_insert { if ($spec->{port}) { $row = schema(vars->{'tenant'})->resultset('DevicePort') ->find($spec->{port}, $spec->{device}); + undef $row unless + scalar grep {('cf_'. $_) eq $spec->{action}} + @{ setting('_device_port_custom_fields') || [] }; } else { $row = schema(vars->{'tenant'})->resultset('Device') ->find($spec->{device}); + undef $row unless + scalar grep {('cf_'. $_) eq $spec->{action}} + @{ setting('_device_custom_fields') || [] }; } - undef $row unless $row->can($spec->{action}); + die 'failed to find row for custom field update' unless $row; $spec->{action} =~ s/^cf_//; diff --git a/lib/App/Netdisco/Web/CustomFields.pm b/lib/App/Netdisco/Web/CustomFields.pm index 05dfc5b4..217a8ea5 100644 --- a/lib/App/Netdisco/Web/CustomFields.pm +++ b/lib/App/Netdisco/Web/CustomFields.pm @@ -83,4 +83,7 @@ set('_inline_actions' => [ map {'cf_' . $_} (@inline_device_actions, @inline_device_port_actions) ]); +set('_device_custom_fields' => \@inline_device_actions); +set('_device_port_custom_fields' => \@inline_device_port_actions); + true; diff --git a/lib/App/Netdisco/Worker/Plugin/Discover/Properties.pm b/lib/App/Netdisco/Worker/Plugin/Discover/Properties.pm index e8b3e713..063a605f 100644 --- a/lib/App/Netdisco/Worker/Plugin/Discover/Properties.pm +++ b/lib/App/Netdisco/Worker/Plugin/Discover/Properties.pm @@ -11,6 +11,8 @@ use App::Netdisco::Util::Device 'get_device'; use App::Netdisco::Util::DNS 'hostname_from_ip'; use App::Netdisco::Util::SNMP 'snmp_comm_reindex'; use App::Netdisco::Util::Web 'sort_port'; +use App::Netdisco::Web::CustomFields; + use Dancer::Plugin::DBIC 'schema'; use Scope::Guard 'guard'; use NetAddr::IP::Lite ':lower'; @@ -75,6 +77,21 @@ register_worker({ phase => 'early', driver => 'snmp' }, sub { } } + # for existing device, filter custom_fields + if ($device->in_storage) { + # get the custom_fields + my $fields = from_json ($device->custom_fields || '{}'); + my %ok_fields = map {$_ => 1} @{ setting('_device_custom_fields') || [] }; + + # filter custom_fields for current valid fields + foreach my $field (keys %$fields) { + delete $fields->{$field} unless exists $ok_fields{$field}; + } + + # set new custom_fields + $device->set_column( custom_fields => to_json $fields ); + } + # support for Hooks vars->{'hook_data'} = { $device->get_columns }; delete vars->{'hook_data'}->{'snmp_comm'}; # for privacy @@ -365,10 +382,23 @@ register_worker({ phase => 'early', driver => 'snmp' }, sub { schema('netdisco')->resultset('DevicePort')->txn_do_locked(sub { # backup the custom_fields - my @fields = grep {exists $deviceports{$_->{port}}} $device->ports - ->search(undef, {columns => [qw/port custom_fields/]})->hri->all; - $deviceports{$_->{port}}->{custom_fields} = $_->{custom_fields} - for @fields; + my %fields = map {($_->{port} => from_json ($_->{custom_fields} || '{}'))} + grep {exists $deviceports{$_->{port}}} + $device->ports + ->search(undef, {columns => [qw/port custom_fields/]}) + ->hri->all; + + my %ok_fields = map {$_ => 1} @{ setting('_device_port_custom_fields') || [] }; + + # filter custom_fields for current valid fields + foreach my $port (keys %fields) { + foreach my $field (keys %{ $fields{$port} }) { + delete $fields{$port}->{$field} unless exists $ok_fields{$field}; + } + + # set new custom_fields + $deviceports{$port}->{custom_fields} = to_json $fields{$port}; + } my $gone = $device->ports->delete({keep_nodes => 1}); debug sprintf ' [%s] interfaces - removed %d interfaces',