File Coverage

blib/lib/App/ElasticSearch/Utilities/VersionHacks.pm
Criterion Covered Total %
statement 18 84 21.4
branch 0 38 0.0
condition 0 6 0.0
subroutine 6 9 66.6
pod n/a
total 24 137 17.5


line stmt bran cond sub pod time code
1             # ABSTRACT: Fix version issues to support all the things
2             package App::ElasticSearch::Utilities::VersionHacks;
3              
4 4     4   28 use strict;
  4         11  
  4         119  
5 4     4   22 use warnings;
  4         14  
  4         120  
6 4     4   1717 use version;
  4         7474  
  4         25  
7              
8             our $VERSION = '8.5'; # VERSION
9              
10 4     4   2154 use Const::Fast;
  4         4223  
  4         26  
11 4     4   306 use CLI::Helpers qw(:all);
  4         12  
  4         37  
12 4         46 use Sub::Exporter -setup => {
13             exports => [ qw(
14             _fix_version_request
15             )],
16 4     4   1034 };
  4         9  
17              
18             const my $MIN_VERSION => 1.0;
19             const my %SIMPLE => (
20             '_cluster/nodes' => {
21             default => '_nodes',
22             },
23             '_optimize' => {
24             # Yes, in case you're wondering _optimize disappeared in 2.2 after being deprecated in 2.1
25             default => '_forcemerge',
26             'v1.0' => '_optimize',
27             'v1.1' => '_optimize',
28             'v1.2' => '_optimize',
29             'v1.3' => '_optimize',
30             'v1.4' => '_optimize',
31             'v1.5' => '_optimize',
32             'v1.6' => '_optimize',
33             'v1.7' => '_optimize',
34             'v1.8' => '_optimize',
35             'v1.9' => '_optimize',
36             'v2.0' => '_optimize',
37             },
38             '_status' => {
39             default => '_stats',
40             'v1.0' => '_status',
41             'v1.1' => '_status',
42             }
43             );
44             my %CALLBACKS = (
45             '_cluster/state' => {
46             default => \&_cluster_state_1_0,
47             },
48             '_search' => {
49             default => \&_search_params,
50             },
51             );
52              
53             my $version;
54              
55             sub _fix_version_request {
56 0     0     my ($url,$options,$data) = @_;
57              
58             # Requires App::ElasticSearch::Utilities to be loaded
59 0 0         if( ! defined $version ){
60             eval {
61 0           $version = sprintf "%0.1f", App::ElasticSearch::Utilities::_get_es_version();
62 0           1;
63 0 0         } or do {
64 0           my $err = $@;
65 0           output({stderr=>1,color=>'red'}, "Failed version detection!", $@);
66             };
67 0 0 0       if (defined $version && $version < $MIN_VERSION) {
68 0           output({stderr=>1,color=>'red',sticky=>1},
69             "!!! Detected ElasticSearch Version '$version', which is < $MIN_VERSION, please upgrade your cluster !!!");
70 0           exit 1;
71             }
72             }
73              
74 0           my $vstr = sprintf "v%0.1f", $version;
75              
76 0 0         if(exists $SIMPLE{$url}) {
77 0           my $versions = join(", ", sort keys %{ $SIMPLE{$url} });
  0            
78 0           debug("Method changed in API, evaluating rewrite ($versions) against $vstr");
79 0 0         if(exists $SIMPLE{$url}->{$vstr}) {
    0          
80 0           debug({indent=>1,color=>'yellow'}, "+ Rewriting $url to $SIMPLE{$url}->{$vstr}");
81 0           $url = $SIMPLE{$url}->{$vstr};
82             }
83             elsif(exists $SIMPLE{$url}->{default}) {
84 0           debug({indent=>1,color=>'yellow'}, "+ Rewriting $url to $SIMPLE{$url}->{default} by default rule");
85 0           $url = $SIMPLE{$url}->{default};
86             }
87             }
88             else {
89 0           my $cb;
90 0           foreach my $check (keys %CALLBACKS) {
91 0 0         next unless $url =~ /^\Q$check\E/i;
92 0           $cb = $check;
93 0           last;
94             }
95 0 0         if( defined $cb ) {
96 0           my $versions = join(", ", sort keys %{ $CALLBACKS{$cb} });
  0            
97 0           debug("Method changed in API, evaluating callback for $cb ($versions) against $vstr");
98 0 0         if(exists $CALLBACKS{$url}->{$vstr}) {
    0          
99 0           debug({indent=>1,color=>'yellow'}, "+ Callback dispatched for $url");
100 0           ($url,$options,$data) = $CALLBACKS{$url}->{$vstr}->($url,$options,$data);
101             }
102             elsif(exists $CALLBACKS{$url}->{default}) {
103 0           debug({indent=>1,color=>'yellow'}, "+ Callback dispatched for $url by default rule");
104 0           ($url,$options,$data) = $CALLBACKS{$url}->{default}->($url,$options,$data,$version);
105             }
106             }
107             }
108              
109 0           return ($url,$options,$data);
110             }
111              
112             my %_cluster_state = map { $_ => 1 } qw(
113             nodes
114             routing_table
115             metadata
116             indices
117             blocks
118             version
119             master_node
120             );
121              
122             sub _cluster_state_1_0 {
123 0     0     my ($url,$options,$data) = @_;
124              
125 0           my @parts = split /\//, $url;
126              
127             # Translate old to new
128 0           debug(sprintf("GOT %s with %d thingies", $url, scalar(@parts)));
129 0 0         if( @parts < 3 ) {
130 0           verbose({color=>'yellow'}, "DEPRECATION: Attempting to use legacy API for _cluster/state on ES $version");
131 0           verbose({level=>2,indent=>1}, "See: http://www.elasticsearch.org/guide/en/reference/$version/cluster-state.html#cluster-state");
132 0           my @requested = ();
133 0 0         if( exists $options->{uri_param} ) {
134             my %filters =
135 0           map { /filter_(.+)$/; $1 => 1 }
  0            
136 0 0         grep { /^filter_/ && $options->{uri_param}{$_} }
137 0           keys %{ $options->{uri_param} };
  0            
138             # Remove them from the parameters
139 0           delete $options->{uri_param}{"filter_$_"} for keys %filters;
140 0 0         if(keys %filters) {
141 0           foreach my $metric (keys %_cluster_state) {
142 0 0         push @requested, $metric unless exists $filters{$metric};
143             }
144             }
145             else {
146 0           push @requested, '_all';
147             }
148             }
149 0           push @parts, join(',', @requested);
150 0           my $new_url = join('/',@parts);
151 0           verbose("~ Cluster State rewritten from $url to $new_url");
152 0           $url=$new_url;
153             }
154 0           return ($url,$options,$data);
155             }
156              
157             sub _search_params {
158 0     0     my ($url,$options,$data,$version) = @_;
159              
160 0           my @invalid = ();
161 0 0         push @invalid, "track_total_hits" if qv($version) < qv("6.0.0");
162 0 0         push @invalid, "rest_total_hits_as_int" if qv($version) < qv("7.0.0");
163              
164 0 0 0       if( @invalid && exists $options->{uri_param} ) {
165 0           foreach my $invalid ( @invalid ) {
166             delete $options->{uri_param}{$invalid}
167 0 0         if exists $options->{uri_param}{$invalid};
168             }
169             }
170              
171 0           return ($url,$options,$data);
172             }
173              
174             1;
175              
176             __END__
177              
178             =pod
179              
180             =head1 NAME
181              
182             App::ElasticSearch::Utilities::VersionHacks - Fix version issues to support all the things
183              
184             =head1 VERSION
185              
186             version 8.5
187              
188             =head1 AUTHOR
189              
190             Brad Lhotsky <brad@divisionbyzero.net>
191              
192             =head1 COPYRIGHT AND LICENSE
193              
194             This software is Copyright (c) 2023 by Brad Lhotsky.
195              
196             This is free software, licensed under:
197              
198             The (three-clause) BSD License
199              
200             =cut