Merge lp:~percona-toolkit-dev/percona-toolkit/release-2.2.8 into lp:percona-toolkit/2.2
- release-2.2.8
- Merge into 2.2
Proposed by
Daniel Nichter
Status: | Merged |
---|---|
Approved by: | Daniel Nichter |
Approved revision: | 604 |
Merged at revision: | 605 |
Proposed branch: | lp:~percona-toolkit-dev/percona-toolkit/release-2.2.8 |
Merge into: | lp:percona-toolkit/2.2 |
Diff against target: |
5689 lines (+347/-4800) (has conflicts) 59 files modified
Changelog (+10/-0) bin/pt-archiver (+1/-1) bin/pt-config-diff (+1/-1) bin/pt-deadlock-logger (+17/-2) bin/pt-diskstats (+1/-1) bin/pt-duplicate-key-checker (+1/-1) bin/pt-find (+1/-1) bin/pt-fk-error-logger (+1/-1) bin/pt-heartbeat (+1/-1) bin/pt-index-usage (+1/-1) bin/pt-kill (+1/-1) bin/pt-online-schema-change (+25/-16) bin/pt-query-digest (+1/-1) bin/pt-slave-delay (+1/-1) bin/pt-slave-restart (+1/-1) bin/pt-table-checksum (+128/-17) bin/pt-table-sync (+1/-1) bin/pt-upgrade (+1/-1) bin/pt-variable-advisor (+1/-1) lib/Percona/Agent/Logger.pm (+0/-341) lib/Percona/Test/Mock/AgentLogger.pm (+0/-129) lib/Percona/Test/Mock/UserAgent.pm (+0/-71) lib/Percona/Toolkit.pm (+1/-1) lib/Percona/WebAPI/Client.pm (+0/-321) lib/Percona/WebAPI/Exception/Request.pm (+0/-69) lib/Percona/WebAPI/Exception/Resource.pm (+0/-66) lib/Percona/WebAPI/Representation.pm (+0/-86) lib/Percona/WebAPI/Resource/Agent.pm (+0/-77) lib/Percona/WebAPI/Resource/Config.pm (+0/-55) lib/Percona/WebAPI/Resource/LogEntry.pm (+0/-66) lib/Percona/WebAPI/Resource/Service.pm (+0/-94) lib/Percona/WebAPI/Resource/Task.pm (+0/-62) t/lib/Percona/WebAPI/Client.t (+0/-236) t/lib/Percona/WebAPI/Representation.t (+0/-51) t/pt-agent/basics.t (+0/-101) t/pt-agent/get_services.t (+0/-423) t/pt-agent/init_agent.t (+0/-333) t/pt-agent/make_new_crontab.t (+0/-151) t/pt-agent/replace_special_vars.t (+0/-73) t/pt-agent/run_agent.t (+0/-527) t/pt-agent/run_service.t (+0/-503) t/pt-agent/samples/crontab001.out (+0/-2) t/pt-agent/samples/crontab002.in (+0/-1) t/pt-agent/samples/crontab002.out (+0/-3) t/pt-agent/samples/crontab003.in (+0/-3) t/pt-agent/samples/crontab003.out (+0/-3) t/pt-agent/samples/crontab004.in (+0/-2) t/pt-agent/samples/crontab004.out (+0/-2) t/pt-agent/samples/query-history/data001.json (+0/-152) t/pt-agent/samples/query-history/data001.send (+0/-166) t/pt-agent/samples/service001 (+0/-19) t/pt-agent/samples/write_services001 (+0/-19) t/pt-agent/schedule_services.t (+0/-200) t/pt-agent/send_data.t (+0/-234) t/pt-agent/write_services.t (+0/-108) t/pt-online-schema-change/plugin.t (+1/-0) t/pt-online-schema-change/samples/plugins/all_hooks.pm (+7/-0) t/pt-table-checksum/plugin.t (+98/-0) t/pt-table-checksum/samples/plugins/all_hooks.pm (+45/-0) Contents conflict in bin/pt-agent |
To merge this branch: | bzr merge lp:~percona-toolkit-dev/percona-toolkit/release-2.2.8 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel Nichter | Approve | ||
Review via email: mp+221476@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Daniel Nichter (daniel-nichter) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'Changelog' |
2 | --- Changelog 2014-02-20 08:10:16 +0000 |
3 | +++ Changelog 2014-05-30 01:02:37 +0000 |
4 | @@ -1,5 +1,15 @@ |
5 | Changelog for Percona Toolkit |
6 | |
7 | + * Removed pt-agent |
8 | + * Added pt-slave-restart GTID support |
9 | + * Added pt-table-checksum --plugin |
10 | + * Fixed bug 1304062: --ignore-tables does not work correctly |
11 | + * Fixed bug 1295667: pt-deadlock-logger logs incorrect ts |
12 | + * Fixed bug 1254233: pt-mysql-summary blank InnoDB section for 5.6 |
13 | + * Fixed bug 1286250: pt-online-schema-change requests password twice |
14 | + * Fixed bug 965553: pt-query-digest dosn't fingerprint true/false literals correctly |
15 | + * Fixed bug 290911: pt-show-grant --ask-pass prints "Enter password" to STDOUT |
16 | + |
17 | v2.2.7 released 2014-02-20 |
18 | |
19 | * Fixed bug 1279502: --version-check behaves like spyware |
20 | |
21 | === renamed file 'bin/pt-agent' => 'bin/pt-agent.THIS' |
22 | === modified file 'bin/pt-archiver' |
23 | --- bin/pt-archiver 2014-05-24 21:36:33 +0000 |
24 | +++ bin/pt-archiver 2014-05-30 01:02:37 +0000 |
25 | @@ -43,7 +43,7 @@ |
26 | { |
27 | package Percona::Toolkit; |
28 | |
29 | -our $VERSION = '2.2.7'; |
30 | +our $VERSION = '2.2.8'; |
31 | |
32 | use strict; |
33 | use warnings FATAL => 'all'; |
34 | |
35 | === modified file 'bin/pt-config-diff' |
36 | --- bin/pt-config-diff 2014-05-24 21:36:33 +0000 |
37 | +++ bin/pt-config-diff 2014-05-30 01:02:37 +0000 |
38 | @@ -43,7 +43,7 @@ |
39 | { |
40 | package Percona::Toolkit; |
41 | |
42 | -our $VERSION = '2.2.7'; |
43 | +our $VERSION = '2.2.8'; |
44 | |
45 | use strict; |
46 | use warnings FATAL => 'all'; |
47 | |
48 | === modified file 'bin/pt-deadlock-logger' |
49 | --- bin/pt-deadlock-logger 2014-05-24 21:36:33 +0000 |
50 | +++ bin/pt-deadlock-logger 2014-05-30 01:02:37 +0000 |
51 | @@ -42,7 +42,7 @@ |
52 | { |
53 | package Percona::Toolkit; |
54 | |
55 | -our $VERSION = '2.2.7'; |
56 | +our $VERSION = '2.2.8'; |
57 | |
58 | use strict; |
59 | use warnings FATAL => 'all'; |
60 | @@ -4440,12 +4440,27 @@ |
61 | |
62 | my $dst; |
63 | if ( my $dst_dsn = $o->get('dest') ) { |
64 | + |
65 | + # set time_zone = SYSTEM , addresses https://bugs.launchpad.net/percona-toolkit/+bug/1295667 |
66 | + my $set_tz = sub { |
67 | + my ($dbh) = @_; |
68 | + my $sql = "SET time_zone=SYSTEM /* pt-deadlock-logger */"; |
69 | + eval { |
70 | + PTDEBUG && _d($dbh, $sql); |
71 | + $dbh->do($sql); |
72 | + }; |
73 | + if ( $EVAL_ERROR ) { |
74 | + die "Failed to $sql: $EVAL_ERROR\n"; |
75 | + } |
76 | + }; |
77 | + |
78 | $dst = Cxn->new( |
79 | dsn => $dst_dsn, |
80 | prev_dsn => ($src ? $src->dsn : undef), |
81 | parent => $o->get('daemonize'), |
82 | DSNParser => $dp, |
83 | OptionParser => $o, |
84 | + set => $set_tz, |
85 | ); |
86 | } |
87 | |
88 | @@ -5199,7 +5214,7 @@ |
89 | |
90 | CREATE TABLE deadlocks ( |
91 | server char(20) NOT NULL, |
92 | - ts datetime NOT NULL, |
93 | + ts timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, |
94 | thread int unsigned NOT NULL, |
95 | txn_id bigint unsigned NOT NULL, |
96 | txn_time smallint unsigned NOT NULL, |
97 | |
98 | === modified file 'bin/pt-diskstats' |
99 | --- bin/pt-diskstats 2014-05-24 21:36:33 +0000 |
100 | +++ bin/pt-diskstats 2014-05-30 01:02:37 +0000 |
101 | @@ -38,7 +38,7 @@ |
102 | { |
103 | package Percona::Toolkit; |
104 | |
105 | -our $VERSION = '2.2.7'; |
106 | +our $VERSION = '2.2.8'; |
107 | |
108 | use strict; |
109 | use warnings FATAL => 'all'; |
110 | |
111 | === modified file 'bin/pt-duplicate-key-checker' |
112 | --- bin/pt-duplicate-key-checker 2014-05-28 01:15:25 +0000 |
113 | +++ bin/pt-duplicate-key-checker 2014-05-30 01:02:37 +0000 |
114 | @@ -39,7 +39,7 @@ |
115 | { |
116 | package Percona::Toolkit; |
117 | |
118 | -our $VERSION = '2.2.7'; |
119 | +our $VERSION = '2.2.8'; |
120 | |
121 | use strict; |
122 | use warnings FATAL => 'all'; |
123 | |
124 | === modified file 'bin/pt-find' |
125 | --- bin/pt-find 2014-05-24 21:36:33 +0000 |
126 | +++ bin/pt-find 2014-05-30 01:02:37 +0000 |
127 | @@ -35,7 +35,7 @@ |
128 | { |
129 | package Percona::Toolkit; |
130 | |
131 | -our $VERSION = '2.2.7'; |
132 | +our $VERSION = '2.2.8'; |
133 | |
134 | use strict; |
135 | use warnings FATAL => 'all'; |
136 | |
137 | === modified file 'bin/pt-fk-error-logger' |
138 | --- bin/pt-fk-error-logger 2014-05-24 21:36:33 +0000 |
139 | +++ bin/pt-fk-error-logger 2014-05-30 01:02:37 +0000 |
140 | @@ -37,7 +37,7 @@ |
141 | { |
142 | package Percona::Toolkit; |
143 | |
144 | -our $VERSION = '2.2.7'; |
145 | +our $VERSION = '2.2.8'; |
146 | |
147 | use strict; |
148 | use warnings FATAL => 'all'; |
149 | |
150 | === modified file 'bin/pt-heartbeat' |
151 | --- bin/pt-heartbeat 2014-05-24 21:36:33 +0000 |
152 | +++ bin/pt-heartbeat 2014-05-30 01:02:37 +0000 |
153 | @@ -38,7 +38,7 @@ |
154 | { |
155 | package Percona::Toolkit; |
156 | |
157 | -our $VERSION = '2.2.7'; |
158 | +our $VERSION = '2.2.8'; |
159 | |
160 | use strict; |
161 | use warnings FATAL => 'all'; |
162 | |
163 | === modified file 'bin/pt-index-usage' |
164 | --- bin/pt-index-usage 2014-05-28 17:03:30 +0000 |
165 | +++ bin/pt-index-usage 2014-05-30 01:02:37 +0000 |
166 | @@ -45,7 +45,7 @@ |
167 | { |
168 | package Percona::Toolkit; |
169 | |
170 | -our $VERSION = '2.2.7'; |
171 | +our $VERSION = '2.2.8'; |
172 | |
173 | use strict; |
174 | use warnings FATAL => 'all'; |
175 | |
176 | === modified file 'bin/pt-kill' |
177 | --- bin/pt-kill 2014-05-28 17:03:30 +0000 |
178 | +++ bin/pt-kill 2014-05-30 01:02:37 +0000 |
179 | @@ -47,7 +47,7 @@ |
180 | { |
181 | package Percona::Toolkit; |
182 | |
183 | -our $VERSION = '2.2.7'; |
184 | +our $VERSION = '2.2.8'; |
185 | |
186 | use strict; |
187 | use warnings FATAL => 'all'; |
188 | |
189 | === modified file 'bin/pt-online-schema-change' |
190 | --- bin/pt-online-schema-change 2014-05-24 21:36:33 +0000 |
191 | +++ bin/pt-online-schema-change 2014-05-30 01:02:37 +0000 |
192 | @@ -54,7 +54,7 @@ |
193 | { |
194 | package Percona::Toolkit; |
195 | |
196 | -our $VERSION = '2.2.7'; |
197 | +our $VERSION = '2.2.8'; |
198 | |
199 | use strict; |
200 | use warnings FATAL => 'all'; |
201 | @@ -3771,7 +3771,7 @@ |
202 | |
203 | my $dbh = $self->{dbh}; |
204 | if ( !$dbh || !$dbh->ping() ) { |
205 | - if ( $self->{ask_pass} && !$self->{asked_for_pass} ) { |
206 | + if ( $self->{ask_pass} && !$self->{asked_for_pass} && !defined $dsn->{p}) { |
207 | $dsn->{p} = OptionParser::prompt_noecho("Enter MySQL password: "); |
208 | $self->{asked_for_pass} = 1; |
209 | } |
210 | @@ -8105,21 +8105,29 @@ |
211 | return; |
212 | }; |
213 | |
214 | - my $get_lag = sub { |
215 | - my ($cxn) = @_; |
216 | - my $dbh = $cxn->dbh(); |
217 | - if ( !$dbh || !$dbh->ping() ) { |
218 | - eval { $dbh = $cxn->connect() }; # connect or die trying |
219 | - if ( $EVAL_ERROR ) { |
220 | - $oktorun = 0; # flag for cleanup tasks |
221 | - chomp $EVAL_ERROR; |
222 | - die "Lost connection to replica " . $cxn->name() |
223 | - . " while attempting to get its lag ($EVAL_ERROR)\n"; |
224 | + my $get_lag; |
225 | + # The plugin is able to override the slavelag check so tools like |
226 | + # pt-heartbeat or other replicators (Tungsten...) can be used to |
227 | + # measure replication lag |
228 | + if ( $plugin && $plugin->can('get_slave_lag') ) { |
229 | + $get_lag = $plugin->get_slave_lag(oktorun => \$oktorun); |
230 | + } else { |
231 | + $get_lag = sub { |
232 | + my ($cxn) = @_; |
233 | + my $dbh = $cxn->dbh(); |
234 | + if ( !$dbh || !$dbh->ping() ) { |
235 | + eval { $dbh = $cxn->connect() }; # connect or die trying |
236 | + if ( $EVAL_ERROR ) { |
237 | + $oktorun = 0; # flag for cleanup tasks |
238 | + chomp $EVAL_ERROR; |
239 | + die "Lost connection to replica " . $cxn->name() |
240 | + . " while attempting to get its lag ($EVAL_ERROR)\n"; |
241 | + } |
242 | } |
243 | - } |
244 | - return $ms->get_slave_lag($dbh); |
245 | - }; |
246 | - |
247 | + return $ms->get_slave_lag($dbh); |
248 | + }; |
249 | + } |
250 | + |
251 | $replica_lag = new ReplicaLagWaiter( |
252 | slaves => $slave_lag_cxns, |
253 | max_lag => $o->get('max-lag'), |
254 | @@ -11345,6 +11353,7 @@ |
255 | after_drop_old_table |
256 | before_drop_triggers |
257 | before_exit |
258 | + get_slave_lag |
259 | |
260 | Each hook is passed different arguments. To see which arguments are passed |
261 | to a hook, search for the hook's name in the tool's source code, like: |
262 | |
263 | === modified file 'bin/pt-query-digest' |
264 | --- bin/pt-query-digest 2014-05-28 17:03:30 +0000 |
265 | +++ bin/pt-query-digest 2014-05-30 01:02:37 +0000 |
266 | @@ -64,7 +64,7 @@ |
267 | { |
268 | package Percona::Toolkit; |
269 | |
270 | -our $VERSION = '2.2.7'; |
271 | +our $VERSION = '2.2.8'; |
272 | |
273 | use strict; |
274 | use warnings FATAL => 'all'; |
275 | |
276 | === modified file 'bin/pt-slave-delay' |
277 | --- bin/pt-slave-delay 2014-05-24 21:36:33 +0000 |
278 | +++ bin/pt-slave-delay 2014-05-30 01:02:37 +0000 |
279 | @@ -40,7 +40,7 @@ |
280 | { |
281 | package Percona::Toolkit; |
282 | |
283 | -our $VERSION = '2.2.7'; |
284 | +our $VERSION = '2.2.8'; |
285 | |
286 | use strict; |
287 | use warnings FATAL => 'all'; |
288 | |
289 | === modified file 'bin/pt-slave-restart' |
290 | --- bin/pt-slave-restart 2014-05-28 22:25:08 +0000 |
291 | +++ bin/pt-slave-restart 2014-05-30 01:02:37 +0000 |
292 | @@ -41,7 +41,7 @@ |
293 | { |
294 | package Percona::Toolkit; |
295 | |
296 | -our $VERSION = '2.2.7'; |
297 | +our $VERSION = '2.2.8'; |
298 | |
299 | use strict; |
300 | use warnings FATAL => 'all'; |
301 | |
302 | === modified file 'bin/pt-table-checksum' |
303 | --- bin/pt-table-checksum 2014-05-28 01:15:25 +0000 |
304 | +++ bin/pt-table-checksum 2014-05-30 01:02:37 +0000 |
305 | @@ -57,7 +57,7 @@ |
306 | { |
307 | package Percona::Toolkit; |
308 | |
309 | -our $VERSION = '2.2.7'; |
310 | +our $VERSION = '2.2.8'; |
311 | |
312 | use strict; |
313 | use warnings FATAL => 'all'; |
314 | @@ -9222,6 +9222,30 @@ |
315 | my $slaves = []; # all slaves (that we can find) |
316 | my $slave_lag_cxns; # slaves whose lag we'll check |
317 | |
318 | + # ######################################################################## |
319 | + # Create --plugin. |
320 | + # ######################################################################## |
321 | + my $plugin; |
322 | + if ( my $file = $o->get('plugin') ) { |
323 | + die "--plugin file $file does not exist\n" unless -f $file; |
324 | + eval { |
325 | + require $file; |
326 | + }; |
327 | + die "Error loading --plugin $file: $EVAL_ERROR" if $EVAL_ERROR; |
328 | + eval { |
329 | + $plugin = pt_table_checksum_plugin->new( |
330 | + master_cxn => $master_cxn, |
331 | + explain => $o->get('explain'), |
332 | + quiet => $o->get('quiet'), |
333 | + resume => $o->get('resume'), |
334 | + Quoter => $q, |
335 | + TableParser => $tp, |
336 | + ); |
337 | + }; |
338 | + die "Error creating --plugin: $EVAL_ERROR" if $EVAL_ERROR; |
339 | + print "Created plugin from $file.\n"; |
340 | + } |
341 | + |
342 | my $replica_lag; # ReplicaLagWaiter object |
343 | my $replica_lag_pr; # Progress for ReplicaLagWaiter |
344 | my $sys_load; # MySQLStatusWaiter object |
345 | @@ -9446,6 +9470,11 @@ |
346 | # ##################################################################### |
347 | if ( $o->get('replicate-check') && $o->get('replicate-check-only') ) { |
348 | PTDEBUG && _d('Will --replicate-check and exit'); |
349 | + |
350 | + # --plugin hook |
351 | + if ( $plugin && $plugin->can('before_replicate_check') ) { |
352 | + $plugin->before_replicate_check(); |
353 | + } |
354 | |
355 | foreach my $slave ( @$slaves ) { |
356 | my $diffs = $rc->find_replication_differences( |
357 | @@ -9466,6 +9495,11 @@ |
358 | } |
359 | } |
360 | |
361 | + # --plugin hook |
362 | + if ( $plugin && $plugin->can('after_replicate_check') ) { |
363 | + $plugin->after_replicate_check(); |
364 | + } |
365 | + |
366 | PTDEBUG && _d('Exit status', $exit_status, 'oktorun', $oktorun); |
367 | return $exit_status; |
368 | } |
369 | @@ -9544,23 +9578,31 @@ |
370 | return; |
371 | }; |
372 | |
373 | - my $get_lag = sub { |
374 | - my ($cxn) = @_; |
375 | - my $dbh = $cxn->dbh(); |
376 | - if ( !$dbh || !$dbh->ping() ) { |
377 | - PTDEBUG && _d('Lost connection to slave', $cxn->name(), |
378 | - 'while waiting for slave lag'); |
379 | - eval { $dbh = $cxn->connect() }; # connect or die trying |
380 | - if ( $EVAL_ERROR ) { |
381 | - $oktorun = 0; # Fatal error |
382 | - chomp $EVAL_ERROR; |
383 | - die "Lost connection to replica " . $cxn->name() |
384 | - . " while attempting to get its lag ($EVAL_ERROR)"; |
385 | + my $get_lag; |
386 | + # The plugin is able to override the slavelag check so tools like |
387 | + # pt-heartbeat or other replicators (Tungsten...) can be used to |
388 | + # measure replication lag |
389 | + if ( $plugin && $plugin->can('get_slave_lag') ) { |
390 | + $get_lag = $plugin->get_slave_lag(oktorun => \$oktorun); |
391 | + } else { |
392 | + $get_lag = sub { |
393 | + my ($cxn) = @_; |
394 | + my $dbh = $cxn->dbh(); |
395 | + if ( !$dbh || !$dbh->ping() ) { |
396 | + PTDEBUG && _d('Lost connection to slave', $cxn->name(), |
397 | + 'while waiting for slave lag'); |
398 | + eval { $dbh = $cxn->connect() }; # connect or die trying |
399 | + if ( $EVAL_ERROR ) { |
400 | + $oktorun = 0; # Fatal error |
401 | + chomp $EVAL_ERROR; |
402 | + die "Lost connection to replica " . $cxn->name() |
403 | + . " while attempting to get its lag ($EVAL_ERROR)"; |
404 | + } |
405 | } |
406 | - } |
407 | - return $ms->get_slave_lag($dbh); |
408 | - }; |
409 | - |
410 | + return $ms->get_slave_lag($dbh); |
411 | + }; |
412 | + } |
413 | + |
414 | $replica_lag = new ReplicaLagWaiter( |
415 | slaves => $slave_lag_cxns, |
416 | max_lag => $o->get('max-lag'), |
417 | @@ -10168,6 +10210,19 @@ |
418 | }; |
419 | |
420 | # ######################################################################## |
421 | + # Init the --plugin. |
422 | + # ######################################################################## |
423 | + |
424 | + # --plugin hook |
425 | + if ( $plugin && $plugin->can('init') ) { |
426 | + $plugin->init( |
427 | + slaves => $slaves, |
428 | + slave_lag_cxns => $slave_lag_cxns, |
429 | + repl_table => $repl_table, |
430 | + ); |
431 | + } |
432 | + |
433 | + # ######################################################################## |
434 | # Checksum each table. |
435 | # ######################################################################## |
436 | |
437 | @@ -10271,6 +10326,12 @@ |
438 | @$all_cols; |
439 | $tbl->{checksum_cols} = \@cols; |
440 | |
441 | + # --plugin hook |
442 | + if ( $plugin && $plugin->can('before_checksum_table') ) { |
443 | + $plugin->before_checksum_table( |
444 | + tbl => $tbl); |
445 | + } |
446 | + |
447 | # Finally, checksum the table. |
448 | # The "1 while" loop is necessary because we're executing REPLACE |
449 | # statements which don't return rows and NibbleIterator only |
450 | @@ -10279,6 +10340,11 @@ |
451 | # from the done callback, uses this start time. |
452 | $tbl->{checksum_results}->{start_time} = time; |
453 | 1 while $nibble_iter->next(); |
454 | + |
455 | + # --plugin hook |
456 | + if ( $plugin && $plugin->can('after_checksum_table') ) { |
457 | + $plugin->after_checksum_table(); |
458 | + } |
459 | } |
460 | }; |
461 | if ( $EVAL_ERROR ) { |
462 | @@ -12053,6 +12119,18 @@ |
463 | tool will overwrite the PID file with the current PID. The PID file is |
464 | removed automatically when the tool exits. |
465 | |
466 | +=item --plugin |
467 | + |
468 | +type: string |
469 | + |
470 | +Perl module file that defines a C<pt_table_checksum_plugin> class. |
471 | +A plugin allows you to write a Perl module that can hook into many parts |
472 | +of pt-table-checksum. This requires a good knowledge of Perl and |
473 | +Percona Toolkit conventions, which are beyond this scope of this |
474 | +documentation. Please contact Percona if you have questions or need help. |
475 | + |
476 | +See L<"PLUGIN"> for more information. |
477 | + |
478 | =item --port |
479 | |
480 | short form: -P; type: int; group: Connection |
481 | @@ -12401,6 +12479,39 @@ |
482 | |
483 | =back |
484 | |
485 | +=head1 PLUGIN |
486 | + |
487 | +The file specified by L<"--plugin"> must define a class (i.e. a package) |
488 | +called C<pt_table_checksum_plugin> with a C<new()> subroutine. |
489 | +The tool will create an instance of this class and call any hooks that |
490 | +it defines. No hooks are required, but a plugin isn't very useful without |
491 | +them. |
492 | + |
493 | +These hooks, in this order, are called if defined: |
494 | + |
495 | + init |
496 | + before_replicate_check |
497 | + after_replicate_check |
498 | + get_slave_lag |
499 | + before_checksum_table |
500 | + after_checksum_table |
501 | + |
502 | +Each hook is passed different arguments. To see which arguments are passed |
503 | +to a hook, search for the hook's name in the tool's source code, like: |
504 | + |
505 | + # --plugin hook |
506 | + if ( $plugin && $plugin->can('init') ) { |
507 | + $plugin->init( |
508 | + slaves => $slaves, |
509 | + slave_lag_cxns => $slave_lag_cxns, |
510 | + repl_table => $repl_table, |
511 | + ); |
512 | + } |
513 | + |
514 | +The comment C<# --plugin hook> precedes every hook call. |
515 | + |
516 | +Please contact Percona if you have questions or need help. |
517 | + |
518 | =head1 DSN OPTIONS |
519 | |
520 | These DSN options are used to create a DSN. Each option is given like |
521 | |
522 | === modified file 'bin/pt-table-sync' |
523 | --- bin/pt-table-sync 2014-05-28 01:15:25 +0000 |
524 | +++ bin/pt-table-sync 2014-05-30 01:02:37 +0000 |
525 | @@ -55,7 +55,7 @@ |
526 | { |
527 | package Percona::Toolkit; |
528 | |
529 | -our $VERSION = '2.2.7'; |
530 | +our $VERSION = '2.2.8'; |
531 | |
532 | use strict; |
533 | use warnings FATAL => 'all'; |
534 | |
535 | === modified file 'bin/pt-upgrade' |
536 | --- bin/pt-upgrade 2014-05-28 17:03:30 +0000 |
537 | +++ bin/pt-upgrade 2014-05-30 01:02:37 +0000 |
538 | @@ -61,7 +61,7 @@ |
539 | { |
540 | package Percona::Toolkit; |
541 | |
542 | -our $VERSION = '2.2.7'; |
543 | +our $VERSION = '2.2.8'; |
544 | |
545 | use strict; |
546 | use warnings FATAL => 'all'; |
547 | |
548 | === modified file 'bin/pt-variable-advisor' |
549 | --- bin/pt-variable-advisor 2014-05-24 21:36:33 +0000 |
550 | +++ bin/pt-variable-advisor 2014-05-30 01:02:37 +0000 |
551 | @@ -44,7 +44,7 @@ |
552 | { |
553 | package Percona::Toolkit; |
554 | |
555 | -our $VERSION = '2.2.7'; |
556 | +our $VERSION = '2.2.8'; |
557 | |
558 | use strict; |
559 | use warnings FATAL => 'all'; |
560 | |
561 | === removed directory 'lib/Percona/Agent' |
562 | === removed file 'lib/Percona/Agent/Logger.pm' |
563 | --- lib/Percona/Agent/Logger.pm 2013-12-11 03:07:36 +0000 |
564 | +++ lib/Percona/Agent/Logger.pm 1970-01-01 00:00:00 +0000 |
565 | @@ -1,341 +0,0 @@ |
566 | -# This program is copyright 2013 Percona Ireland Ltd. |
567 | -# Feedback and improvements are welcome. |
568 | -# |
569 | -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
570 | -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
571 | -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
572 | -# |
573 | -# This program is free software; you can redistribute it and/or modify it under |
574 | -# the terms of the GNU General Public License as published by the Free Software |
575 | -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar |
576 | -# systems, you can issue `man perlgpl' or `man perlartistic' to read these |
577 | -# licenses. |
578 | -# |
579 | -# You should have received a copy of the GNU General Public License along with |
580 | -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
581 | -# Place, Suite 330, Boston, MA 02111-1307 USA. |
582 | -# ########################################################################### |
583 | -# Percona::Agent::Logger package |
584 | -# ########################################################################### |
585 | -package Percona::Agent::Logger; |
586 | - |
587 | -use strict; |
588 | -use warnings FATAL => 'all'; |
589 | -use English qw(-no_match_vars); |
590 | - |
591 | -use constant PTDEBUG => $ENV{PTDEBUG} || 0; |
592 | - |
593 | -use POSIX qw(SIGALRM); |
594 | - |
595 | -use Lmo; |
596 | -use Transformers; |
597 | -use Percona::WebAPI::Resource::LogEntry; |
598 | - |
599 | -Transformers->import(qw(ts)); |
600 | - |
601 | -has 'exit_status' => ( |
602 | - is => 'rw', |
603 | - isa => 'ScalarRef', |
604 | - required => 1, |
605 | -); |
606 | - |
607 | -has 'pid' => ( |
608 | - is => 'ro', |
609 | - isa => 'Int', |
610 | - required => 1, |
611 | -); |
612 | - |
613 | -has 'service' => ( |
614 | - is => 'rw', |
615 | - isa => 'Maybe[Str]', |
616 | - required => 0, |
617 | - default => sub { return; }, |
618 | -); |
619 | - |
620 | -has 'data_ts' => ( |
621 | - is => 'rw', |
622 | - isa => 'Maybe[Int]', |
623 | - required => 0, |
624 | - default => sub { return; }, |
625 | -); |
626 | - |
627 | -has 'online_logging' => ( |
628 | - is => 'ro', |
629 | - isa => 'Bool', |
630 | - required => 0, |
631 | - default => sub { return 1 }, |
632 | -); |
633 | - |
634 | -has 'online_logging_enabled' => ( |
635 | - is => 'rw', |
636 | - isa => 'Bool', |
637 | - required => 0, |
638 | - default => sub { return 0 }, |
639 | -); |
640 | - |
641 | -has 'quiet' => ( |
642 | - is => 'rw', |
643 | - isa => 'Int', |
644 | - required => 0, |
645 | - default => sub { return 0 }, |
646 | -); |
647 | - |
648 | -has '_buffer' => ( |
649 | - is => 'rw', |
650 | - isa => 'ArrayRef', |
651 | - required => 0, |
652 | - default => sub { return []; }, |
653 | -); |
654 | - |
655 | -has '_pipe_write' => ( |
656 | - is => 'rw', |
657 | - isa => 'Maybe[FileHandle]', |
658 | - required => 0, |
659 | -); |
660 | - |
661 | -sub read_stdin { |
662 | - my ( $t ) = @_; |
663 | - |
664 | - # Set the SIGALRM handler. |
665 | - POSIX::sigaction( |
666 | - SIGALRM, |
667 | - POSIX::SigAction->new(sub { die 'read timeout'; }), |
668 | - ) or die "Error setting SIGALRM handler: $OS_ERROR"; |
669 | - |
670 | - my $timeout = 0; |
671 | - my @lines; |
672 | - eval { |
673 | - alarm $t; |
674 | - while(defined(my $line = <STDIN>)) { |
675 | - push @lines, $line; |
676 | - } |
677 | - alarm 0; |
678 | - }; |
679 | - if ( $EVAL_ERROR ) { |
680 | - PTDEBUG && _d('Read error:', $EVAL_ERROR); |
681 | - die $EVAL_ERROR unless $EVAL_ERROR =~ m/read timeout/; |
682 | - $timeout = 1; |
683 | - } |
684 | - return unless scalar @lines || $timeout; |
685 | - return \@lines; |
686 | -} |
687 | - |
688 | -sub start_online_logging { |
689 | - my ($self, %args) = @_; |
690 | - my $client = $args{client}; |
691 | - my $log_link = $args{log_link}; |
692 | - my $read_timeout = $args{read_timeout} || 3; |
693 | - |
694 | - return unless $self->online_logging; |
695 | - |
696 | - my $pid = open(my $pipe_write, "|-"); |
697 | - |
698 | - if ($pid) { |
699 | - # parent |
700 | - select $pipe_write; |
701 | - $OUTPUT_AUTOFLUSH = 1; |
702 | - $self->_pipe_write($pipe_write); |
703 | - $self->online_logging_enabled(1); |
704 | - } |
705 | - else { |
706 | - # child |
707 | - my @log_entries; |
708 | - my $n_errors = 0; |
709 | - my $oktorun = 1; |
710 | - QUEUE: |
711 | - while ($oktorun) { |
712 | - my $lines = read_stdin($read_timeout); |
713 | - last QUEUE unless $lines; |
714 | - LINE: |
715 | - while ( defined(my $line = shift @$lines) ) { |
716 | - # $line = ts,level,n_lines,message |
717 | - my ($ts, $level, $n_lines, $msg) = $line =~ m/^([^,]+),([^,]+),([^,]+),(.+)/s; |
718 | - if ( !$ts || !$level || !$n_lines || !$msg ) { |
719 | - warn "$line\n"; |
720 | - next LINE; |
721 | - } |
722 | - if ( $n_lines > 1 ) { |
723 | - $n_lines--; # first line |
724 | - for ( 1..$n_lines ) { |
725 | - $msg .= shift @$lines; |
726 | - } |
727 | - } |
728 | - |
729 | - push @log_entries, Percona::WebAPI::Resource::LogEntry->new( |
730 | - pid => $self->pid, |
731 | - entry_ts => $ts, |
732 | - log_level => $level, |
733 | - message => $msg, |
734 | - ($self->service ? (service => $self->service) : ()), |
735 | - ($self->data_ts ? (data_ts => $self->data_ts) : ()), |
736 | - ); |
737 | - } # LINE |
738 | - |
739 | - if ( scalar @log_entries ) { |
740 | - eval { |
741 | - $client->post( |
742 | - link => $log_link, |
743 | - resources => \@log_entries, |
744 | - ); |
745 | - }; |
746 | - if ( my $e = $EVAL_ERROR ) { |
747 | - # Safegaurd: don't spam the agent log file with errors. |
748 | - if ( ++$n_errors <= 10 ) { |
749 | - warn "Error sending log entry to API: $e"; |
750 | - if ( $n_errors == 10 ) { |
751 | - my $ts = ts(time, 1); # 1=UTC |
752 | - warn "$ts WARNING $n_errors consecutive errors, no more " |
753 | - . "error messages will be printed until log entries " |
754 | - . "are sent successfully again.\n"; |
755 | - } |
756 | - } |
757 | - } |
758 | - else { |
759 | - @log_entries = (); |
760 | - $n_errors = 0; |
761 | - } |
762 | - } # have log entries |
763 | - |
764 | - # Safeguard: don't use too much memory if we lose connection |
765 | - # to the API for a long time. |
766 | - my $n_log_entries = scalar @log_entries; |
767 | - if ( $n_log_entries > 1_000 ) { |
768 | - warn "$n_log_entries log entries in send buffer, " |
769 | - . "removing first 100 to avoid excessive usage.\n"; |
770 | - @log_entries = @log_entries[100..($n_log_entries-1)]; |
771 | - } |
772 | - } # QUEUE |
773 | - |
774 | - if ( scalar @log_entries ) { |
775 | - my $ts = ts(time, 1); # 1=UTC |
776 | - warn "$ts WARNING Failed to send these log entries " |
777 | - . "(timestamps are UTC):\n"; |
778 | - foreach my $log ( @log_entries ) { |
779 | - warn sprintf("%s %s %s\n", |
780 | - $log->entry_ts, |
781 | - level_name($log->log_level), |
782 | - $log->message, |
783 | - ); |
784 | - } |
785 | - } |
786 | - |
787 | - exit 0; |
788 | - } # child |
789 | - |
790 | - return; |
791 | -} |
792 | - |
793 | -sub level_number { |
794 | - my $name = shift; |
795 | - die "No log level name given" unless $name; |
796 | - my $number = $name eq 'DEBUG' ? 1 |
797 | - : $name eq 'INFO' ? 2 |
798 | - : $name eq 'WARNING' ? 3 |
799 | - : $name eq 'ERROR' ? 4 |
800 | - : $name eq 'FATAL' ? 5 |
801 | - : die "Invalid log level name: $name"; |
802 | -} |
803 | - |
804 | -sub level_name { |
805 | - my $number = shift; |
806 | - die "No log level name given" unless $number; |
807 | - my $name = $number == 1 ? 'DEBUG' |
808 | - : $number == 2 ? 'INFO' |
809 | - : $number == 3 ? 'WARNING' |
810 | - : $number == 4 ? 'ERROR' |
811 | - : $number == 5 ? 'FATAL' |
812 | - : die "Invalid log level number: $number"; |
813 | -} |
814 | - |
815 | -sub debug { |
816 | - my $self = shift; |
817 | - return if $self->online_logging; |
818 | - return $self->_log(0, 'DEBUG', @_); |
819 | -} |
820 | - |
821 | -sub info { |
822 | - my $self = shift; |
823 | - return $self->_log(1, 'INFO', @_); |
824 | -} |
825 | - |
826 | -sub warning { |
827 | - my $self = shift; |
828 | - $self->_set_exit_status(); |
829 | - return $self->_log(1, 'WARNING', @_); |
830 | -} |
831 | - |
832 | -sub error { |
833 | - my $self = shift; |
834 | - $self->_set_exit_status(); |
835 | - return $self->_log(1, 'ERROR', @_); |
836 | -} |
837 | - |
838 | -sub fatal { |
839 | - my $self = shift; |
840 | - $self->_set_exit_status(); |
841 | - $self->_log(1, 'FATAL', @_); |
842 | - exit $self->exit_status; |
843 | -} |
844 | - |
845 | -sub _set_exit_status { |
846 | - my $self = shift; |
847 | - # exit_status is a scalar ref |
848 | - my $exit_status = $self->exit_status; # get ref |
849 | - $$exit_status |= 1; # deref to set |
850 | - $self->exit_status($exit_status); # save back ref |
851 | - return; |
852 | -} |
853 | - |
854 | -sub _log { |
855 | - my ($self, $online, $level, $msg) = @_; |
856 | - |
857 | - my $ts = ts(time, 1); # 1=UTC |
858 | - my $level_number = level_number($level); |
859 | - |
860 | - return if $self->quiet && $level_number < $self->quiet; |
861 | - |
862 | - chomp($msg); |
863 | - my $n_lines = 1; |
864 | - $n_lines++ while $msg =~ m/\n/g; |
865 | - |
866 | - if ( $online && $self->online_logging_enabled ) { |
867 | - while ( defined(my $log_entry = shift @{$self->_buffer}) ) { |
868 | - $self->_queue_log_entry(@$log_entry); |
869 | - } |
870 | - $self->_queue_log_entry($ts, $level_number, $n_lines, $msg); |
871 | - } |
872 | - else { |
873 | - if ( $online && $self->online_logging ) { |
874 | - push @{$self->_buffer}, [$ts, $level_number, $n_lines, $msg]; |
875 | - } |
876 | - |
877 | - if ( $level_number >= 3 ) { # warning |
878 | - print STDERR "$ts $level $msg\n"; |
879 | - } |
880 | - else { |
881 | - print STDOUT "$ts $level $msg\n"; |
882 | - } |
883 | - } |
884 | - |
885 | - return; |
886 | -} |
887 | - |
888 | -sub _queue_log_entry { |
889 | - my ($self, $ts, $log_level, $n_lines, $msg) = @_; |
890 | - print "$ts,$log_level,$n_lines,$msg\n"; |
891 | - return; |
892 | -} |
893 | - |
894 | -sub _d { |
895 | - my ($package, undef, $line) = caller 0; |
896 | - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } |
897 | - map { defined $_ ? $_ : 'undef' } |
898 | - @_; |
899 | - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; |
900 | -} |
901 | - |
902 | -no Lmo; |
903 | -1; |
904 | -# ########################################################################### |
905 | -# End Percona::Agent::Logger package |
906 | -# ########################################################################### |
907 | |
908 | === removed directory 'lib/Percona/Test' |
909 | === removed directory 'lib/Percona/Test/Mock' |
910 | === removed file 'lib/Percona/Test/Mock/AgentLogger.pm' |
911 | --- lib/Percona/Test/Mock/AgentLogger.pm 2013-06-17 00:28:18 +0000 |
912 | +++ lib/Percona/Test/Mock/AgentLogger.pm 1970-01-01 00:00:00 +0000 |
913 | @@ -1,129 +0,0 @@ |
914 | -# This program is copyright 2013 Percona Ireland Ltd. |
915 | -# Feedback and improvements are welcome. |
916 | -# |
917 | -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
918 | -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
919 | -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
920 | -# |
921 | -# This program is free software; you can redistribute it and/or modify it under |
922 | -# the terms of the GNU General Public License as published by the Free Software |
923 | -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar |
924 | -# systems, you can issue `man perlgpl' or `man perlartistic' to read these |
925 | -# licenses. |
926 | -# |
927 | -# You should have received a copy of the GNU General Public License along with |
928 | -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
929 | -# Place, Suite 330, Boston, MA 02111-1307 USA. |
930 | -# ########################################################################### |
931 | -# Percona::Agent::Logger package |
932 | -# ########################################################################### |
933 | -package Percona::Test::Mock::AgentLogger; |
934 | - |
935 | -use strict; |
936 | -use warnings FATAL => 'all'; |
937 | -use English qw(-no_match_vars); |
938 | - |
939 | -use constant PTDEBUG => $ENV{PTDEBUG} || 0; |
940 | - |
941 | -sub new { |
942 | - my ($class, %args) = @_; |
943 | - my $self = { |
944 | - log => $args{log}, |
945 | - |
946 | - exit_status => $args{exit_status}, |
947 | - pid => $args{pid}, |
948 | - online_logging => $args{online_logging}, |
949 | - |
950 | - service => undef, |
951 | - data_ts => undef, |
952 | - quiet => 0, |
953 | - |
954 | - }; |
955 | - return bless $self, $class; |
956 | -} |
957 | - |
958 | -sub service { |
959 | - my $self = shift; |
960 | - my $_service = shift; |
961 | - $self->{service} = $_service if $_service; |
962 | - return $self->{service}; |
963 | -} |
964 | - |
965 | -sub data_ts { |
966 | - my $self = shift; |
967 | - my $_data_ts = shift; |
968 | - $self->{data_ts} = $_data_ts if $_data_ts; |
969 | - return $self->{data_ts}; |
970 | -} |
971 | - |
972 | -sub quiet { |
973 | - my $self = shift; |
974 | - my $_quiet = shift; |
975 | - $self->{quiet} = $_quiet if $_quiet; |
976 | - return $self->{quiet}; |
977 | -} |
978 | - |
979 | -sub start_online_logging { |
980 | - my ($self, %args) = @_; |
981 | - $self->_log('-', 'Called start_online_logging()'); |
982 | - return; |
983 | -} |
984 | - |
985 | -sub level_number { |
986 | - my $name = shift; |
987 | - die "No log level name given" unless $name; |
988 | - my $number = $name eq 'DEBUG' ? 1 |
989 | - : $name eq 'INFO' ? 2 |
990 | - : $name eq 'WARNING' ? 3 |
991 | - : $name eq 'ERROR' ? 4 |
992 | - : $name eq 'FATAL' ? 5 |
993 | - : die "Invalid log level name: $name"; |
994 | -} |
995 | - |
996 | -sub level_name { |
997 | - my $number = shift; |
998 | - die "No log level name given" unless $number; |
999 | - my $name = $number == 1 ? 'DEBUG' |
1000 | - : $number == 2 ? 'INFO' |
1001 | - : $number == 3 ? 'WARNING' |
1002 | - : $number == 4 ? 'ERROR' |
1003 | - : $number == 5 ? 'FATAL' |
1004 | - : die "Invalid log level number: $number"; |
1005 | -} |
1006 | - |
1007 | -sub debug { |
1008 | - my $self = shift; |
1009 | - return $self->_log('DEBUG', @_); |
1010 | -} |
1011 | - |
1012 | -sub info { |
1013 | - my $self = shift; |
1014 | - return $self->_log('INFO', @_); |
1015 | -} |
1016 | - |
1017 | -sub warning { |
1018 | - my $self = shift; |
1019 | - return $self->_log('WARNING', @_); |
1020 | -} |
1021 | - |
1022 | -sub error { |
1023 | - my $self = shift; |
1024 | - return $self->_log('ERROR', @_); |
1025 | -} |
1026 | - |
1027 | -sub fatal { |
1028 | - my $self = shift; |
1029 | - $self->_log('FATAL', @_); |
1030 | - return 255; |
1031 | -} |
1032 | - |
1033 | -sub _log { |
1034 | - my ($self, $level, $msg) = @_; |
1035 | - push @{$self->{log}}, "$level $msg"; |
1036 | - return; |
1037 | -} |
1038 | - |
1039 | -1; |
1040 | -# ########################################################################### |
1041 | -# End Percona::Test::Mock::AgentLogger package |
1042 | -# ########################################################################### |
1043 | |
1044 | === removed file 'lib/Percona/Test/Mock/UserAgent.pm' |
1045 | --- lib/Percona/Test/Mock/UserAgent.pm 2013-03-21 19:50:49 +0000 |
1046 | +++ lib/Percona/Test/Mock/UserAgent.pm 1970-01-01 00:00:00 +0000 |
1047 | @@ -1,71 +0,0 @@ |
1048 | -# This program is copyright 2012-2013 Percona Inc. |
1049 | -# Feedback and improvements are welcome. |
1050 | -# |
1051 | -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
1052 | -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
1053 | -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
1054 | -# |
1055 | -# This program is free software; you can redistribute it and/or modify it under |
1056 | -# the terms of the GNU General Public License as published by the Free Software |
1057 | -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar |
1058 | -# systems, you can issue `man perlgpl' or `man perlartistic' to read these |
1059 | -# licenses. |
1060 | -# |
1061 | -# You should have received a copy of the GNU General Public License along with |
1062 | -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
1063 | -# Place, Suite 330, Boston, MA 02111-1307 USA. |
1064 | -# ########################################################################### |
1065 | -# Percona::Test::Mock::UserAgent package |
1066 | -# ########################################################################### |
1067 | -{ |
1068 | -package Percona::Test::Mock::UserAgent; |
1069 | - |
1070 | -sub new { |
1071 | - my ($class, %args) = @_; |
1072 | - my $self = { |
1073 | - encode => $args{encode} || sub { return $_[0] }, |
1074 | - decode => $args{decode} || sub { return $_[0] }, |
1075 | - requests => [], |
1076 | - request_objs => [], |
1077 | - responses => { |
1078 | - get => [], |
1079 | - post => [], |
1080 | - put => [], |
1081 | - }, |
1082 | - content => { |
1083 | - post => [], |
1084 | - put => [], |
1085 | - }, |
1086 | - }; |
1087 | - return bless $self, $class; |
1088 | -} |
1089 | - |
1090 | -sub request { |
1091 | - my ($self, $req) = @_; |
1092 | - if ( scalar @{$self->{request_objs}} > 10 ) { |
1093 | - $self->{request_objs} = []; |
1094 | - } |
1095 | - push @{$self->{request_objs}}, $req; |
1096 | - my $type = lc($req->method); |
1097 | - push @{$self->{requests}}, uc($type) . ' ' . $req->uri; |
1098 | - if ( $type eq 'post' || $type eq 'put' ) { |
1099 | - push @{$self->{content}->{$type}}, $req->content; |
1100 | - } |
1101 | - my $r = shift @{$self->{responses}->{$type}}; |
1102 | - my $c = $r->{content} ? $self->{encode}->($r->{content}) : ''; |
1103 | - my $h = HTTP::Headers->new; |
1104 | - $h->header(%{$r->{headers}}) if exists $r->{headers}; |
1105 | - my $res = HTTP::Response->new( |
1106 | - $r->{code} || 200, |
1107 | - '', |
1108 | - $h, |
1109 | - $c, |
1110 | - ); |
1111 | - return $res; |
1112 | -} |
1113 | - |
1114 | -1; |
1115 | -} |
1116 | -# ########################################################################### |
1117 | -# End Percona::Test::Mock::UserAgent package |
1118 | -# ########################################################################### |
1119 | |
1120 | === modified file 'lib/Percona/Toolkit.pm' |
1121 | --- lib/Percona/Toolkit.pm 2014-02-20 03:47:43 +0000 |
1122 | +++ lib/Percona/Toolkit.pm 2014-05-30 01:02:37 +0000 |
1123 | @@ -18,7 +18,7 @@ |
1124 | # ########################################################################### |
1125 | package Percona::Toolkit; |
1126 | |
1127 | -our $VERSION = '2.2.7'; |
1128 | +our $VERSION = '2.2.8'; |
1129 | |
1130 | use strict; |
1131 | use warnings FATAL => 'all'; |
1132 | |
1133 | === removed directory 'lib/Percona/WebAPI' |
1134 | === removed file 'lib/Percona/WebAPI/Client.pm' |
1135 | --- lib/Percona/WebAPI/Client.pm 2013-09-19 04:05:48 +0000 |
1136 | +++ lib/Percona/WebAPI/Client.pm 1970-01-01 00:00:00 +0000 |
1137 | @@ -1,321 +0,0 @@ |
1138 | -# This program is copyright 2012 codenode LLC, 2012-2013 Percona Ireland Ltd. |
1139 | -# |
1140 | -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
1141 | -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
1142 | -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
1143 | -# |
1144 | -# This program is free software; you can redistribute it and/or modify it under |
1145 | -# the terms of the GNU General Public License as published by the Free Software |
1146 | -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar |
1147 | -# systems, you can issue `man perlgpl' or `man perlartistic' to read these |
1148 | -# licenses. |
1149 | -# |
1150 | -# You should have received a copy of the GNU General Public License along with |
1151 | -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
1152 | -# Place, Suite 330, Boston, MA 02111-1307 USA. |
1153 | -# ########################################################################### |
1154 | -# Percona::WebAPI::Client package |
1155 | -# ########################################################################### |
1156 | -{ |
1157 | -package Percona::WebAPI::Client; |
1158 | - |
1159 | -our $VERSION = '0.01'; |
1160 | - |
1161 | -use strict; |
1162 | -use warnings FATAL => 'all'; |
1163 | -use English qw(-no_match_vars); |
1164 | -use constant PTDEBUG => $ENV{PTDEBUG} || 0; |
1165 | - |
1166 | -eval { |
1167 | - require LWP; |
1168 | - require JSON; |
1169 | -}; |
1170 | - |
1171 | -use Scalar::Util qw(blessed); |
1172 | - |
1173 | -use Lmo; |
1174 | -use Percona::Toolkit; |
1175 | -use Percona::WebAPI::Representation; |
1176 | -use Percona::WebAPI::Exception::Request; |
1177 | -use Percona::WebAPI::Exception::Resource; |
1178 | - |
1179 | -Percona::WebAPI::Representation->import(qw(as_json)); |
1180 | -Percona::Toolkit->import(qw(_d Dumper have_required_args)); |
1181 | - |
1182 | -has 'api_key' => ( |
1183 | - is => 'ro', |
1184 | - isa => 'Str', |
1185 | - required => 1, |
1186 | -); |
1187 | - |
1188 | -has 'entry_link' => ( |
1189 | - is => 'rw', |
1190 | - isa => 'Str', |
1191 | - required => 0, |
1192 | - default => sub { return 'https://cloud-api.percona.com' }, |
1193 | -); |
1194 | - |
1195 | -has 'ua' => ( |
1196 | - is => 'rw', |
1197 | - isa => 'Object', |
1198 | - lazy => 1, |
1199 | - required => 0, |
1200 | - builder => '_build_ua', |
1201 | -); |
1202 | - |
1203 | -has 'response' => ( |
1204 | - is => 'rw', |
1205 | - isa => 'Object', |
1206 | - required => 0, |
1207 | - default => undef, |
1208 | -); |
1209 | - |
1210 | -sub _build_ua { |
1211 | - my $self = shift; |
1212 | - my $ua = LWP::UserAgent->new; |
1213 | - $ua->agent("Percona::WebAPI::Client/$Percona::WebAPI::Client::VERSION"); |
1214 | - $ua->default_header('Content-Type', 'application/json'); |
1215 | - $ua->default_header('X-Percona-API-Key', $self->api_key); |
1216 | - return $ua; |
1217 | -} |
1218 | - |
1219 | -sub get { |
1220 | - my ($self, %args) = @_; |
1221 | - |
1222 | - have_required_args(\%args, qw( |
1223 | - link |
1224 | - )) or die; |
1225 | - my ($link) = $args{link}; |
1226 | - |
1227 | - # Get the resources at the link. |
1228 | - eval { |
1229 | - $self->_request( |
1230 | - method => 'GET', |
1231 | - link => $link, |
1232 | - ); |
1233 | - }; |
1234 | - if ( my $e = $EVAL_ERROR ) { |
1235 | - if (blessed($e) && $e->isa('Percona::WebAPI::Exception::Request')) { |
1236 | - die $e; |
1237 | - } |
1238 | - else { |
1239 | - die "Unknown error: $e"; |
1240 | - } |
1241 | - } |
1242 | - |
1243 | - # The resource should be represented as JSON, decode it. |
1244 | - my $resource = eval { |
1245 | - JSON::decode_json($self->response->content); |
1246 | - }; |
1247 | - if ( $EVAL_ERROR ) { |
1248 | - warn sprintf "Error decoding resource: %s: %s", |
1249 | - $self->response->content, |
1250 | - $EVAL_ERROR; |
1251 | - return; |
1252 | - } |
1253 | - |
1254 | - # If the server tells us the resource's type, create a new object |
1255 | - # of that type. Else, if there's no type, there's no resource, so |
1256 | - # we should have received links. This usually only happens for the |
1257 | - # entry link. The returned resource objects ref may be scalar or |
1258 | - # an arrayref; the caller should know. |
1259 | - my $resource_objects; |
1260 | - if ( my $type = $self->response->headers->{'x-percona-resource-type'} ) { |
1261 | - eval { |
1262 | - $type = "Percona::WebAPI::Resource::$type"; |
1263 | - if ( ref $resource eq 'ARRAY' ) { |
1264 | - PTDEBUG && _d('Got a list of', $type, 'resources'); |
1265 | - $resource_objects = []; |
1266 | - foreach my $attribs ( @$resource ) { |
1267 | - my $obj = $type->new(%$attribs); |
1268 | - push @$resource_objects, $obj; |
1269 | - } |
1270 | - } |
1271 | - else { |
1272 | - PTDEBUG && _d('Got a', $type, 'resource', Dumper($resource)); |
1273 | - $resource_objects = $type->new(%$resource); |
1274 | - } |
1275 | - }; |
1276 | - if ( my $e = $EVAL_ERROR ) { |
1277 | - die Percona::WebAPI::Exception::Resource->new( |
1278 | - type => $type, |
1279 | - link => $link, |
1280 | - data => (ref $resource eq 'ARRAY' ? $resource : [ $resource ]), |
1281 | - error => $e, |
1282 | - ); |
1283 | - } |
1284 | - } |
1285 | - elsif ( exists $resource->{links} ) { |
1286 | - # Lie to the caller: this isn't an object, but the caller can |
1287 | - # treat it like one, e.g. my $links = $api->get(<entry links>); |
1288 | - # then access $links->{self}. A Links object couldn't have |
1289 | - # dynamic attribs anyway, so no use having a real Links obj. |
1290 | - $resource_objects = $resource->{links}; |
1291 | - } |
1292 | - elsif ( exists $resource->{pong} ) { |
1293 | - PTDEBUG && _d("Ping pong!"); |
1294 | - } |
1295 | - else { |
1296 | - warn "Did not get X-Percona-Resource-Type or links from $link\n"; |
1297 | - } |
1298 | - |
1299 | - return $resource_objects; |
1300 | -} |
1301 | - |
1302 | -# For a successful POST, the server sets the Location header with |
1303 | -# the URI of the newly created resource. |
1304 | -sub post { |
1305 | - my $self = shift; |
1306 | - $self->_set( |
1307 | - @_, |
1308 | - method => 'POST', |
1309 | - ); |
1310 | - return $self->response->header('Location'); |
1311 | -} |
1312 | - |
1313 | -sub put { |
1314 | - my $self = shift; |
1315 | - $self->_set( |
1316 | - @_, |
1317 | - method => 'PUT', |
1318 | - ); |
1319 | - return $self->response->header('Location'); |
1320 | -} |
1321 | - |
1322 | -sub delete { |
1323 | - my ($self, %args) = @_; |
1324 | - have_required_args(\%args, qw( |
1325 | - link |
1326 | - )) or die; |
1327 | - my ($link) = $args{link}; |
1328 | - |
1329 | - eval { |
1330 | - $self->_request( |
1331 | - method => 'DELETE', |
1332 | - link => $link, |
1333 | - headers => { 'Content-Length' => 0 }, |
1334 | - ); |
1335 | - }; |
1336 | - if ( my $e = $EVAL_ERROR ) { |
1337 | - if (blessed($e) && $e->isa('Percona::WebAPI::Exception::Request')) { |
1338 | - die $e; |
1339 | - } |
1340 | - else { |
1341 | - die "Unknown error: $e"; |
1342 | - } |
1343 | - } |
1344 | - |
1345 | - return; |
1346 | -} |
1347 | - |
1348 | -# Low-level POST and PUT handler. |
1349 | -sub _set { |
1350 | - my ($self, %args) = @_; |
1351 | - have_required_args(\%args, qw( |
1352 | - method |
1353 | - resources |
1354 | - link |
1355 | - )) or die; |
1356 | - my $method = $args{method}; |
1357 | - my $res = $args{resources}; |
1358 | - my $link = $args{link}; |
1359 | - |
1360 | - # Optional args |
1361 | - my $headers = $args{headers}; |
1362 | - |
1363 | - my $content = ''; |
1364 | - if ( ref($res) eq 'ARRAY' ) { |
1365 | - PTDEBUG && _d('List of resources'); |
1366 | - $content = '[' . join(",\n", map { as_json($_) } @$res) . ']'; |
1367 | - } |
1368 | - elsif ( ref($res) ) { |
1369 | - PTDEBUG && _d('Resource object'); |
1370 | - $content = as_json($res); |
1371 | - } |
1372 | - elsif ( $res !~ m/\n/ && -f $res ) { |
1373 | - PTDEBUG && _d('List of resources in file', $res); |
1374 | - $content = '['; |
1375 | - my $data = do { |
1376 | - local $INPUT_RECORD_SEPARATOR = undef; |
1377 | - open my $fh, '<', $res |
1378 | - or die "Error opening $res: $OS_ERROR"; |
1379 | - <$fh>; |
1380 | - }; |
1381 | - $data =~ s/,?\s*$/]/; |
1382 | - $content .= $data; |
1383 | - } |
1384 | - else { |
1385 | - PTDEBUG && _d('Resource text'); |
1386 | - $content = $res; |
1387 | - } |
1388 | - |
1389 | - eval { |
1390 | - $self->_request( |
1391 | - method => $method, |
1392 | - link => $link, |
1393 | - content => $content, |
1394 | - headers => $headers, |
1395 | - ); |
1396 | - }; |
1397 | - if ( my $e = $EVAL_ERROR ) { |
1398 | - if (blessed($e) && $e->isa('Percona::WebAPI::Exception::Request')) { |
1399 | - die $e; |
1400 | - } |
1401 | - else { |
1402 | - die "Unknown error: $e"; |
1403 | - } |
1404 | - } |
1405 | - |
1406 | - return; |
1407 | -} |
1408 | - |
1409 | -# Low-level HTTP request handler for all methods. Sets $self->response |
1410 | -# from the request. Returns nothing on success (HTTP status 2xx-3xx), |
1411 | -# else throws an Percona::WebAPI::Exception::Request. |
1412 | -sub _request { |
1413 | - my ($self, %args) = @_; |
1414 | - |
1415 | - have_required_args(\%args, qw( |
1416 | - method |
1417 | - link |
1418 | - )) or die; |
1419 | - my $method = $args{method}; |
1420 | - my $link = $args{link}; |
1421 | - |
1422 | - # Optional args |
1423 | - my $content = $args{content}; |
1424 | - my $headers = $args{headers}; |
1425 | - |
1426 | - my $req = HTTP::Request->new($method => $link); |
1427 | - if ( $content ) { |
1428 | - $req->content($content); |
1429 | - } |
1430 | - if ( $headers ) { |
1431 | - map { $req->header($_ => $headers->{$_}) } keys %$headers; |
1432 | - } |
1433 | - PTDEBUG && _d('Request', $method, $link, Dumper($req)); |
1434 | - |
1435 | - my $response = $self->ua->request($req); |
1436 | - PTDEBUG && _d('Response', Dumper($response)); |
1437 | - |
1438 | - $self->response($response); |
1439 | - |
1440 | - if ( !($response->code >= 200 && $response->code < 400) ) { |
1441 | - die Percona::WebAPI::Exception::Request->new( |
1442 | - method => $method, |
1443 | - url => $link, |
1444 | - content => $content, |
1445 | - status => $response->code, |
1446 | - error => "Failed to $method $link", |
1447 | - ); |
1448 | - } |
1449 | - |
1450 | - return; |
1451 | -} |
1452 | - |
1453 | -no Lmo; |
1454 | -1; |
1455 | -} |
1456 | -# ########################################################################### |
1457 | -# End Percona::WebAPI::Client package |
1458 | -# ########################################################################### |
1459 | |
1460 | === removed directory 'lib/Percona/WebAPI/Exception' |
1461 | === removed file 'lib/Percona/WebAPI/Exception/Request.pm' |
1462 | --- lib/Percona/WebAPI/Exception/Request.pm 2012-12-26 20:00:46 +0000 |
1463 | +++ lib/Percona/WebAPI/Exception/Request.pm 1970-01-01 00:00:00 +0000 |
1464 | @@ -1,69 +0,0 @@ |
1465 | -# This program is copyright 2012-2013 Percona Inc. |
1466 | -# Feedback and improvements are welcome. |
1467 | -# |
1468 | -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
1469 | -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
1470 | -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
1471 | -# |
1472 | -# This program is free software; you can redistribute it and/or modify it under |
1473 | -# the terms of the GNU General Public License as published by the Free Software |
1474 | -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar |
1475 | -# systems, you can issue `man perlgpl' or `man perlartistic' to read these |
1476 | -# licenses. |
1477 | -# |
1478 | -# You should have received a copy of the GNU General Public License along with |
1479 | -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
1480 | -# Place, Suite 330, Boston, MA 02111-1307 USA. |
1481 | -# ########################################################################### |
1482 | -# Percona::WebAPI::Exception::Request package |
1483 | -# ########################################################################### |
1484 | -{ |
1485 | -package Percona::WebAPI::Exception::Request; |
1486 | - |
1487 | -use Lmo; |
1488 | -use overload '""' => \&as_string; |
1489 | - |
1490 | -has 'method' => ( |
1491 | - is => 'ro', |
1492 | - isa => 'Str', |
1493 | - required => 1, |
1494 | -); |
1495 | - |
1496 | -has 'url' => ( |
1497 | - is => 'ro', |
1498 | - isa => 'Str', |
1499 | - required => 1, |
1500 | -); |
1501 | - |
1502 | -has 'content' => ( |
1503 | - is => 'ro', |
1504 | - isa => 'Maybe[Str]', |
1505 | - required => 0, |
1506 | -); |
1507 | - |
1508 | -has 'status' => ( |
1509 | - is => 'ro', |
1510 | - isa => 'Int', |
1511 | - required => 1, |
1512 | -); |
1513 | - |
1514 | -has 'error' => ( |
1515 | - is => 'ro', |
1516 | - isa => 'Str', |
1517 | - required => 1, |
1518 | -); |
1519 | - |
1520 | -sub as_string { |
1521 | - my $self = shift; |
1522 | - chomp(my $error = $self->error); |
1523 | - $error =~ s/\n/ /g; |
1524 | - return sprintf "%s\nRequest: %s %s %s\nStatus: %d\n", |
1525 | - $error, $self->method, $self->url, $self->content || '', $self->status; |
1526 | -} |
1527 | - |
1528 | -no Lmo; |
1529 | -1; |
1530 | -} |
1531 | -# ########################################################################### |
1532 | -# End Percona::WebAPI::Exception::Request package |
1533 | -# ########################################################################### |
1534 | |
1535 | === removed file 'lib/Percona/WebAPI/Exception/Resource.pm' |
1536 | --- lib/Percona/WebAPI/Exception/Resource.pm 2013-03-01 16:47:49 +0000 |
1537 | +++ lib/Percona/WebAPI/Exception/Resource.pm 1970-01-01 00:00:00 +0000 |
1538 | @@ -1,66 +0,0 @@ |
1539 | -# This program is copyright 2012-2013 Percona Inc. |
1540 | -# Feedback and improvements are welcome. |
1541 | -# |
1542 | -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
1543 | -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
1544 | -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
1545 | -# |
1546 | -# This program is free software; you can redistribute it and/or modify it under |
1547 | -# the terms of the GNU General Public License as published by the Free Software |
1548 | -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar |
1549 | -# systems, you can issue `man perlgpl' or `man perlartistic' to read these |
1550 | -# licenses. |
1551 | -# |
1552 | -# You should have received a copy of the GNU General Public License along with |
1553 | -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
1554 | -# Place, Suite 330, Boston, MA 02111-1307 USA. |
1555 | -# ########################################################################### |
1556 | -# Percona::WebAPI::Exception::Resource package |
1557 | -# ########################################################################### |
1558 | -{ |
1559 | -package Percona::WebAPI::Exception::Resource; |
1560 | - |
1561 | -use Lmo; |
1562 | -use overload '""' => \&as_string; |
1563 | -use Data::Dumper; |
1564 | - |
1565 | -has 'type' => ( |
1566 | - is => 'ro', |
1567 | - isa => 'Str', |
1568 | - required => 1, |
1569 | -); |
1570 | - |
1571 | -has 'link' => ( |
1572 | - is => 'ro', |
1573 | - isa => 'Str', |
1574 | - required => 1, |
1575 | -); |
1576 | - |
1577 | -has 'data' => ( |
1578 | - is => 'ro', |
1579 | - isa => 'ArrayRef', |
1580 | - required => 1, |
1581 | -); |
1582 | - |
1583 | -has 'error' => ( |
1584 | - is => 'ro', |
1585 | - isa => 'Str', |
1586 | - required => 1, |
1587 | -); |
1588 | - |
1589 | -sub as_string { |
1590 | - my $self = shift; |
1591 | - chomp(my $error = $self->error); |
1592 | - local $Data::Dumper::Indent = 1; |
1593 | - local $Data::Dumper::Sortkeys = 1; |
1594 | - local $Data::Dumper::Quotekeys = 0; |
1595 | - return sprintf "Invalid %s resource from %s:\n\n%s\nError: %s\n\n", |
1596 | - $self->type, $self->link, Dumper($self->data), $error; |
1597 | -} |
1598 | - |
1599 | -no Lmo; |
1600 | -1; |
1601 | -} |
1602 | -# ########################################################################### |
1603 | -# End Percona::WebAPI::Exception::Resource package |
1604 | -# ########################################################################### |
1605 | |
1606 | === removed file 'lib/Percona/WebAPI/Representation.pm' |
1607 | --- lib/Percona/WebAPI/Representation.pm 2013-06-15 19:31:38 +0000 |
1608 | +++ lib/Percona/WebAPI/Representation.pm 1970-01-01 00:00:00 +0000 |
1609 | @@ -1,86 +0,0 @@ |
1610 | -# This program is copyright 2012-2013 Percona Inc. |
1611 | -# Feedback and improvements are welcome. |
1612 | -# |
1613 | -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
1614 | -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
1615 | -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
1616 | -# |
1617 | -# This program is free software; you can redistribute it and/or modify it under |
1618 | -# the terms of the GNU General Public License as published by the Free Software |
1619 | -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar |
1620 | -# systems, you can issue `man perlgpl' or `man perlartistic' to read these |
1621 | -# licenses. |
1622 | -# |
1623 | -# You should have received a copy of the GNU General Public License along with |
1624 | -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
1625 | -# Place, Suite 330, Boston, MA 02111-1307 USA. |
1626 | -# ########################################################################### |
1627 | -# Percona::WebAPI::Representation package |
1628 | -# ########################################################################### |
1629 | -{ |
1630 | -package Percona::WebAPI::Representation; |
1631 | - |
1632 | -eval { |
1633 | - require JSON; |
1634 | -}; |
1635 | - |
1636 | -require Exporter; |
1637 | -our @ISA = qw(Exporter); |
1638 | -our @EXPORT_OK = qw( |
1639 | - as_hashref |
1640 | - as_json |
1641 | - as_config |
1642 | -); |
1643 | - |
1644 | -sub as_hashref { |
1645 | - my ($resource, %args) = @_; |
1646 | - |
1647 | - # Copy the object into a new hashref. |
1648 | - my $as_hashref = { %$resource }; |
1649 | - |
1650 | - # Delete the links because they're just for client-side use |
1651 | - # and the caller should be sending this object, not getting it. |
1652 | - # But sometimes for testing we want to keep the links. |
1653 | - if ( !defined $args{with_links} || !$args{with_links} ) { |
1654 | - delete $as_hashref->{links}; |
1655 | - } |
1656 | - |
1657 | - return $as_hashref; |
1658 | -} |
1659 | - |
1660 | -sub as_json { |
1661 | - my ($resource, %args) = @_; |
1662 | - |
1663 | - my $json = $args{json} || JSON->new; |
1664 | - $json->allow_blessed([]); |
1665 | - $json->convert_blessed([]); |
1666 | - |
1667 | - my $text = $json->encode( |
1668 | - ref $resource eq 'ARRAY' ? $resource : as_hashref($resource, %args) |
1669 | - ); |
1670 | - if ( $args{json} && $text ) { # for testing |
1671 | - chomp($text); |
1672 | - $text .= "\n"; |
1673 | - } |
1674 | - return $text; |
1675 | -} |
1676 | - |
1677 | -sub as_config { |
1678 | - my $resource = shift; |
1679 | - if ( !$resource->isa('Percona::WebAPI::Resource::Config') ) { |
1680 | - die "Only Config resources can be represented as config.\n"; |
1681 | - } |
1682 | - my $as_hashref = as_hashref($resource); |
1683 | - my $options = $as_hashref->{options}; |
1684 | - my $config = join("\n", |
1685 | - map { defined $options->{$_} ? "$_=$options->{$_}" : "$_" } |
1686 | - sort keys %$options |
1687 | - ) . "\n"; |
1688 | - return $config; |
1689 | -} |
1690 | - |
1691 | -1; |
1692 | -} |
1693 | -# ########################################################################### |
1694 | -# End Percona::WebAPI::Representation package |
1695 | -# ########################################################################### |
1696 | |
1697 | === removed directory 'lib/Percona/WebAPI/Resource' |
1698 | === removed file 'lib/Percona/WebAPI/Resource/Agent.pm' |
1699 | --- lib/Percona/WebAPI/Resource/Agent.pm 2013-06-15 02:59:14 +0000 |
1700 | +++ lib/Percona/WebAPI/Resource/Agent.pm 1970-01-01 00:00:00 +0000 |
1701 | @@ -1,77 +0,0 @@ |
1702 | -# This program is copyright 2012-2013 Percona Inc. |
1703 | -# Feedback and improvements are welcome. |
1704 | -# |
1705 | -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
1706 | -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
1707 | -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
1708 | -# |
1709 | -# This program is free software; you can redistribute it and/or modify it under |
1710 | -# the terms of the GNU General Public License as published by the Free Software |
1711 | -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar |
1712 | -# systems, you can issue `man perlgpl' or `man perlartistic' to read these |
1713 | -# licenses. |
1714 | -# |
1715 | -# You should have received a copy of the GNU General Public License along with |
1716 | -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
1717 | -# Place, Suite 330, Boston, MA 02111-1307 USA. |
1718 | -# ########################################################################### |
1719 | -# Percona::WebAPI::Resource::Agent package |
1720 | -# ########################################################################### |
1721 | -{ |
1722 | -package Percona::WebAPI::Resource::Agent; |
1723 | - |
1724 | -use Lmo; |
1725 | - |
1726 | -has 'uuid' => ( |
1727 | - is => 'ro', |
1728 | - isa => 'Str', |
1729 | - required => 0, |
1730 | -); |
1731 | - |
1732 | -has 'username' => ( |
1733 | - is => 'rw', |
1734 | - isa => 'Str', |
1735 | - required => 0, |
1736 | - default => sub { return $ENV{USER} || $ENV{LOGNAME} }, |
1737 | -); |
1738 | - |
1739 | -has 'hostname' => ( |
1740 | - is => 'rw', |
1741 | - isa => 'Str', |
1742 | - required => 0, |
1743 | - default => sub { |
1744 | - chomp(my $hostname = `hostname`); |
1745 | - return $hostname; |
1746 | - }, |
1747 | -); |
1748 | - |
1749 | -has 'alias' => ( |
1750 | - is => 'rw', |
1751 | - isa => 'Str', |
1752 | - required => 0, |
1753 | -); |
1754 | - |
1755 | -has 'versions' => ( |
1756 | - is => 'rw', |
1757 | - isa => 'Maybe[HashRef]', |
1758 | - required => 0, |
1759 | -); |
1760 | - |
1761 | -has 'links' => ( |
1762 | - is => 'rw', |
1763 | - isa => 'Maybe[HashRef]', |
1764 | - required => 0, |
1765 | - default => sub { return {} }, |
1766 | -); |
1767 | - |
1768 | -sub name { |
1769 | - my ($self) = @_; |
1770 | - return $self->alias || $self->hostname || $self->uuid || 'Unknown'; |
1771 | -} |
1772 | - |
1773 | -no Lmo; |
1774 | -1; |
1775 | -} |
1776 | -# ########################################################################### |
1777 | -# End Percona::WebAPI::Resource::Agent package |
1778 | -# ########################################################################### |
1779 | |
1780 | === removed file 'lib/Percona/WebAPI/Resource/Config.pm' |
1781 | --- lib/Percona/WebAPI/Resource/Config.pm 2013-03-01 16:47:49 +0000 |
1782 | +++ lib/Percona/WebAPI/Resource/Config.pm 1970-01-01 00:00:00 +0000 |
1783 | @@ -1,55 +0,0 @@ |
1784 | -# This program is copyright 2012-2013 Percona Inc. |
1785 | -# Feedback and improvements are welcome. |
1786 | -# |
1787 | -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
1788 | -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
1789 | -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
1790 | -# |
1791 | -# This program is free software; you can redistribute it and/or modify it under |
1792 | -# the terms of the GNU General Public License as published by the Free Software |
1793 | -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar |
1794 | -# systems, you can issue `man perlgpl' or `man perlartistic' to read these |
1795 | -# licenses. |
1796 | -# |
1797 | -# You should have received a copy of the GNU General Public License along with |
1798 | -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
1799 | -# Place, Suite 330, Boston, MA 02111-1307 USA. |
1800 | -# ########################################################################### |
1801 | -# Percona::WebAPI::Resource::Config package |
1802 | -# ########################################################################### |
1803 | -{ |
1804 | -package Percona::WebAPI::Resource::Config; |
1805 | - |
1806 | -use Lmo; |
1807 | - |
1808 | -has 'ts' => ( |
1809 | - is => 'ro', |
1810 | - isa => 'Int', |
1811 | - required => 1, |
1812 | -); |
1813 | - |
1814 | -has 'name' => ( |
1815 | - is => 'ro', |
1816 | - isa => 'Str', |
1817 | - required => 1, |
1818 | -); |
1819 | - |
1820 | -has 'options' => ( |
1821 | - is => 'ro', |
1822 | - isa => 'HashRef', |
1823 | - required => 1, |
1824 | -); |
1825 | - |
1826 | -has 'links' => ( |
1827 | - is => 'rw', |
1828 | - isa => 'Maybe[HashRef]', |
1829 | - required => 0, |
1830 | - default => sub { return {} }, |
1831 | -); |
1832 | - |
1833 | -no Lmo; |
1834 | -1; |
1835 | -} |
1836 | -# ########################################################################### |
1837 | -# End Percona::WebAPI::Resource::Config package |
1838 | -# ########################################################################### |
1839 | |
1840 | === removed file 'lib/Percona/WebAPI/Resource/LogEntry.pm' |
1841 | --- lib/Percona/WebAPI/Resource/LogEntry.pm 2013-06-10 00:15:16 +0000 |
1842 | +++ lib/Percona/WebAPI/Resource/LogEntry.pm 1970-01-01 00:00:00 +0000 |
1843 | @@ -1,66 +0,0 @@ |
1844 | -# This program is copyright 2013 Percona Inc. |
1845 | -# Feedback and improvements are welcome. |
1846 | -# |
1847 | -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
1848 | -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
1849 | -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
1850 | -# |
1851 | -# This program is free software; you can redistribute it and/or modify it under |
1852 | -# the terms of the GNU General Public License as published by the Free Software |
1853 | -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar |
1854 | -# systems, you can issue `man perlgpl' or `man perlartistic' to read these |
1855 | -# licenses. |
1856 | -# |
1857 | -# You should have received a copy of the GNU General Public License along with |
1858 | -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
1859 | -# Place, Suite 330, Boston, MA 02111-1307 USA. |
1860 | -# ########################################################################### |
1861 | -# Percona::WebAPI::Resource::LogEntry package |
1862 | -# ########################################################################### |
1863 | -{ |
1864 | -package Percona::WebAPI::Resource::LogEntry; |
1865 | - |
1866 | -use Lmo; |
1867 | - |
1868 | -has 'pid' => ( |
1869 | - is => 'ro', |
1870 | - isa => 'Int', |
1871 | - required => 1, |
1872 | -); |
1873 | - |
1874 | -has 'service' => ( |
1875 | - is => 'ro', |
1876 | - isa => 'Str', |
1877 | - required => 0, |
1878 | -); |
1879 | - |
1880 | -has 'data_ts' => ( |
1881 | - is => 'ro', |
1882 | - isa => 'Int', |
1883 | - required => 0, |
1884 | -); |
1885 | - |
1886 | -has 'entry_ts' => ( |
1887 | - is => 'ro', |
1888 | - isa => 'Str', |
1889 | - required => 1, |
1890 | -); |
1891 | - |
1892 | -has 'log_level' => ( |
1893 | - is => 'ro', |
1894 | - isa => 'Int', |
1895 | - required => 1, |
1896 | -); |
1897 | - |
1898 | -has 'message' => ( |
1899 | - is => 'ro', |
1900 | - isa => 'Str', |
1901 | - required => 1, |
1902 | -); |
1903 | - |
1904 | -no Lmo; |
1905 | -1; |
1906 | -} |
1907 | -# ########################################################################### |
1908 | -# End Percona::WebAPI::Resource::LogEntry package |
1909 | -# ########################################################################### |
1910 | |
1911 | === removed file 'lib/Percona/WebAPI/Resource/Service.pm' |
1912 | --- lib/Percona/WebAPI/Resource/Service.pm 2013-04-19 20:49:01 +0000 |
1913 | +++ lib/Percona/WebAPI/Resource/Service.pm 1970-01-01 00:00:00 +0000 |
1914 | @@ -1,94 +0,0 @@ |
1915 | -# This program is copyright 2012-2013 Percona Inc. |
1916 | -# Feedback and improvements are welcome. |
1917 | -# |
1918 | -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
1919 | -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
1920 | -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
1921 | -# |
1922 | -# This program is free software; you can redistribute it and/or modify it under |
1923 | -# the terms of the GNU General Public License as published by the Free Software |
1924 | -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar |
1925 | -# systems, you can issue `man perlgpl' or `man perlartistic' to read these |
1926 | -# licenses. |
1927 | -# |
1928 | -# You should have received a copy of the GNU General Public License along with |
1929 | -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
1930 | -# Place, Suite 330, Boston, MA 02111-1307 USA. |
1931 | -# ########################################################################### |
1932 | -# Percona::WebAPI::Resource::Service package |
1933 | -# ########################################################################### |
1934 | -{ |
1935 | -package Percona::WebAPI::Resource::Service; |
1936 | - |
1937 | -use Lmo; |
1938 | - |
1939 | -has 'ts' => ( |
1940 | - is => 'ro', |
1941 | - isa => 'Int', |
1942 | - required => 1, |
1943 | -); |
1944 | - |
1945 | -has 'name' => ( |
1946 | - is => 'ro', |
1947 | - isa => 'Str', |
1948 | - required => 1, |
1949 | -); |
1950 | - |
1951 | -has 'tasks' => ( |
1952 | - is => 'ro', |
1953 | - isa => 'ArrayRef[Percona::WebAPI::Resource::Task]', |
1954 | - required => 1, |
1955 | -); |
1956 | - |
1957 | -has 'run_schedule' => ( |
1958 | - is => 'ro', |
1959 | - isa => 'Str', |
1960 | - required => 0, |
1961 | -); |
1962 | - |
1963 | -has 'spool_schedule' => ( |
1964 | - is => 'ro', |
1965 | - isa => 'Str', |
1966 | - required => 0, |
1967 | -); |
1968 | - |
1969 | -has 'meta' => ( |
1970 | - is => 'ro', |
1971 | - isa => 'Bool', |
1972 | - required => 0, |
1973 | - default => sub { return 0 }, |
1974 | -); |
1975 | - |
1976 | -has 'run_once' => ( |
1977 | - is => 'ro', |
1978 | - isa => 'Bool', |
1979 | - required => 0, |
1980 | - default => sub { return 0 }, |
1981 | -); |
1982 | - |
1983 | -has 'links' => ( |
1984 | - is => 'rw', |
1985 | - isa => 'Maybe[HashRef]', |
1986 | - required => 0, |
1987 | - default => sub { return {} }, |
1988 | -); |
1989 | - |
1990 | -sub BUILDARGS { |
1991 | - my ($class, %args) = @_; |
1992 | - if ( ref $args{tasks} eq 'ARRAY' ) { |
1993 | - my @tasks; |
1994 | - foreach my $run_hashref ( @{$args{tasks}} ) { |
1995 | - my $task = Percona::WebAPI::Resource::Task->new(%$run_hashref); |
1996 | - push @tasks, $task; |
1997 | - } |
1998 | - $args{tasks} = \@tasks; |
1999 | - } |
2000 | - return $class->SUPER::BUILDARGS(%args); |
2001 | -} |
2002 | - |
2003 | -no Lmo; |
2004 | -1; |
2005 | -} |
2006 | -# ########################################################################### |
2007 | -# End Percona::WebAPI::Resource::Service package |
2008 | -# ########################################################################### |
2009 | |
2010 | === removed file 'lib/Percona/WebAPI/Resource/Task.pm' |
2011 | --- lib/Percona/WebAPI/Resource/Task.pm 2013-04-19 20:49:01 +0000 |
2012 | +++ lib/Percona/WebAPI/Resource/Task.pm 1970-01-01 00:00:00 +0000 |
2013 | @@ -1,62 +0,0 @@ |
2014 | -# This program is copyright 2012-2013 Percona Inc. |
2015 | -# Feedback and improvements are welcome. |
2016 | -# |
2017 | -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
2018 | -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
2019 | -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
2020 | -# |
2021 | -# This program is free software; you can redistribute it and/or modify it under |
2022 | -# the terms of the GNU General Public License as published by the Free Software |
2023 | -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar |
2024 | -# systems, you can issue `man perlgpl' or `man perlartistic' to read these |
2025 | -# licenses. |
2026 | -# |
2027 | -# You should have received a copy of the GNU General Public License along with |
2028 | -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
2029 | -# Place, Suite 330, Boston, MA 02111-1307 USA. |
2030 | -# ########################################################################### |
2031 | -# Percona::WebAPI::Resource::Task package |
2032 | -# ########################################################################### |
2033 | -{ |
2034 | -package Percona::WebAPI::Resource::Task; |
2035 | - |
2036 | -use Lmo; |
2037 | - |
2038 | -has 'name' => ( |
2039 | - is => 'ro', |
2040 | - isa => 'Str', |
2041 | - required => 1, |
2042 | -); |
2043 | - |
2044 | -has 'number' => ( |
2045 | - is => 'ro', |
2046 | - isa => 'Int', |
2047 | - required => 1, |
2048 | -); |
2049 | - |
2050 | -has 'program' => ( |
2051 | - is => 'ro', |
2052 | - isa => 'Maybe[Str]', |
2053 | - required => 0, |
2054 | -); |
2055 | - |
2056 | -has 'query' => ( |
2057 | - is => 'ro', |
2058 | - isa => 'Maybe[Str]', |
2059 | - required => 0, |
2060 | -); |
2061 | - |
2062 | -has 'output' => ( |
2063 | - is => 'ro', |
2064 | - isa => 'Maybe[Str]', |
2065 | - required => 0, |
2066 | -); |
2067 | - |
2068 | -sub TO_JSON { return { %{ shift() } }; } |
2069 | - |
2070 | -no Lmo; |
2071 | -1; |
2072 | -} |
2073 | -# ########################################################################### |
2074 | -# End Percona::WebAPI::Resource::Task package |
2075 | -# ########################################################################### |
2076 | |
2077 | === removed directory 't/lib/Percona/WebAPI' |
2078 | === removed file 't/lib/Percona/WebAPI/Client.t' |
2079 | --- t/lib/Percona/WebAPI/Client.t 2013-08-08 19:34:29 +0000 |
2080 | +++ t/lib/Percona/WebAPI/Client.t 1970-01-01 00:00:00 +0000 |
2081 | @@ -1,236 +0,0 @@ |
2082 | -#!/usr/bin/env perl |
2083 | - |
2084 | -BEGIN { |
2085 | - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" |
2086 | - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; |
2087 | - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; |
2088 | -}; |
2089 | - |
2090 | -use strict; |
2091 | -use warnings FATAL => 'all'; |
2092 | -use English qw(-no_match_vars); |
2093 | -use Test::More; |
2094 | -use JSON; |
2095 | -use File::Temp qw(tempdir); |
2096 | - |
2097 | -use Percona::Test; |
2098 | -use Percona::Test::Mock::UserAgent; |
2099 | -use Percona::WebAPI::Client; |
2100 | -use Percona::WebAPI::Resource::Agent; |
2101 | -use Percona::WebAPI::Resource::Config; |
2102 | -use Percona::WebAPI::Resource::Service; |
2103 | -use Percona::WebAPI::Resource::Task; |
2104 | - |
2105 | -Percona::Toolkit->import(qw(Dumper have_required_args)); |
2106 | -Percona::WebAPI::Representation->import(qw(as_json as_hashref)); |
2107 | - |
2108 | -# ############################################################################# |
2109 | -# Create a client with a mock user-agent. |
2110 | -# ############################################################################# |
2111 | - |
2112 | -my $json = JSON->new; |
2113 | -$json->allow_blessed([]); |
2114 | -$json->convert_blessed([]); |
2115 | - |
2116 | -my $ua = Percona::Test::Mock::UserAgent->new( |
2117 | - encode => sub { my $c = shift; return $json->encode($c || {}) }, |
2118 | -); |
2119 | - |
2120 | -my $client = eval { |
2121 | - Percona::WebAPI::Client->new( |
2122 | - api_key => '123', |
2123 | - ua => $ua, |
2124 | - ); |
2125 | -}; |
2126 | - |
2127 | -is( |
2128 | - $EVAL_ERROR, |
2129 | - '', |
2130 | - 'Create client' |
2131 | -) or die; |
2132 | - |
2133 | -# ############################################################################# |
2134 | -# First thing a client should do is get the entry links. |
2135 | -# ############################################################################# |
2136 | - |
2137 | -my $return_links = { # what the server returns |
2138 | - agents => '/agents', |
2139 | -}; |
2140 | - |
2141 | -$ua->{responses}->{get} = [ |
2142 | - { |
2143 | - content => { |
2144 | - links => $return_links, |
2145 | - } |
2146 | - }, |
2147 | -]; |
2148 | - |
2149 | -my $links = $client->get(link => $client->entry_link); |
2150 | - |
2151 | -is_deeply( |
2152 | - $links, |
2153 | - $return_links, |
2154 | - "Get entry links" |
2155 | -) or diag(Dumper($links)); |
2156 | - |
2157 | -is_deeply( |
2158 | - $ua->{requests}, |
2159 | - [ |
2160 | - 'GET https://cloud-api.percona.com', |
2161 | - ], |
2162 | - "1 request, 1 GET" |
2163 | -) or diag(Dumper($ua->{requests})); |
2164 | - |
2165 | - |
2166 | -# ############################################################################# |
2167 | -# Second, a new client will POST an Agent for itself. The entry links |
2168 | -# should have an "agents" link. The server response is empty but the |
2169 | -# URI for the new Agent resource is given by the Location header. |
2170 | -# ############################################################################# |
2171 | - |
2172 | -my $agent = Percona::WebAPI::Resource::Agent->new( |
2173 | - id => '123', |
2174 | - hostname => 'host', |
2175 | -); |
2176 | - |
2177 | -$ua->{responses}->{post} = [ |
2178 | - { |
2179 | - headers => { 'Location' => 'agents/5' }, |
2180 | - content => '', |
2181 | - }, |
2182 | -]; |
2183 | - |
2184 | -my $uri = $client->post(resources => $agent, link => $links->{agents}); |
2185 | - |
2186 | -is( |
2187 | - $uri, |
2188 | - "agents/5", |
2189 | - "POST Agent, got Location URI" |
2190 | -); |
2191 | - |
2192 | -# ############################################################################# |
2193 | -# After successfully creating the new Agent, the client should fetch |
2194 | -# the new Agent resoruce which will have links to the next step: the |
2195 | -# agent's config. |
2196 | -# ############################################################################# |
2197 | - |
2198 | -$return_links = { |
2199 | - self => 'agents/5', |
2200 | - config => 'agents/5/config', |
2201 | -}; |
2202 | - |
2203 | -my $content = { |
2204 | - %{ as_hashref($agent) }, |
2205 | - links => $return_links, |
2206 | -}; |
2207 | - |
2208 | -$ua->{responses}->{get} = [ |
2209 | - { |
2210 | - headers => { 'X-Percona-Resource-Type' => 'Agent' }, |
2211 | - content => $content, |
2212 | - }, |
2213 | -]; |
2214 | - |
2215 | -# Re-using $agent, i.e. updating it with the actual, newly created |
2216 | -# Agent resource as returned by the server with links. |
2217 | -$agent = $client->get(link => $uri); |
2218 | - |
2219 | -# Need to use with_links=>1 here because by as_hashref() removes |
2220 | -# links by default because it's usually used to encode and send |
2221 | -# resources, and clients never send links; but here we're using |
2222 | -# it for testing. |
2223 | -is_deeply( |
2224 | - as_hashref($agent, with_links => 1), |
2225 | - $content, |
2226 | - "GET Agent with links" |
2227 | -) or diag(Dumper(as_hashref($agent, with_links => 1))); |
2228 | - |
2229 | -# ############################################################################# |
2230 | -# Now the agent can get its Config. |
2231 | -# ############################################################################# |
2232 | - |
2233 | -$return_links = { |
2234 | - self => 'agents/5/config', |
2235 | - services => 'agents/5/services', |
2236 | -}; |
2237 | - |
2238 | -my $return_config = Percona::WebAPI::Resource::Config->new( |
2239 | - ts => '100', |
2240 | - name => 'Default', |
2241 | - options => {}, |
2242 | - links => $return_links, |
2243 | -); |
2244 | - |
2245 | -$ua->{responses}->{get} = [ |
2246 | - { |
2247 | - headers => { 'X-Percona-Resource-Type' => 'Config' }, |
2248 | - content => as_hashref($return_config, with_links => 1), |
2249 | - }, |
2250 | -]; |
2251 | - |
2252 | -my $config = $client->get(link => $agent->links->{config}); |
2253 | - |
2254 | -is_deeply( |
2255 | - as_hashref($config, with_links => 1), |
2256 | - as_hashref($return_config, with_links => 1), |
2257 | - "GET Config" |
2258 | -) or diag(Dumper(as_hashref($config, with_links => 1))); |
2259 | - |
2260 | -# ############################################################################# |
2261 | -# Once an agent is configured, i.e. successfully gets a Config resource, |
2262 | -# its Config should have a services link which returns a list of Service |
2263 | -# resources, each with their own links. |
2264 | -# ############################################################################# |
2265 | - |
2266 | -$return_links = { |
2267 | - 'send_data' => '/query-monitor', |
2268 | -}; |
2269 | - |
2270 | -my $run0 = Percona::WebAPI::Resource::Task->new( |
2271 | - name => 'run-pqd', |
2272 | - number => '0', |
2273 | - program => 'pt-query-digest', |
2274 | - options => '--output json', |
2275 | - output => 'spool', |
2276 | -); |
2277 | - |
2278 | -my $svc0 = Percona::WebAPI::Resource::Service->new( |
2279 | - ts => '123', |
2280 | - name => 'query-monitor', |
2281 | - run_schedule => '1 * * * *', |
2282 | - spool_schedule => '2 * * * *', |
2283 | - tasks => [ $run0 ], |
2284 | - links => $return_links, |
2285 | -); |
2286 | - |
2287 | -$ua->{responses}->{get} = [ |
2288 | - { |
2289 | - headers => { 'X-Percona-Resource-Type' => 'Service' }, |
2290 | - content => [ as_hashref($svc0, with_links => 1) ], |
2291 | - }, |
2292 | -]; |
2293 | - |
2294 | -my $services = $client->get(link => $config->links->{services}); |
2295 | - |
2296 | -is( |
2297 | - scalar @$services, |
2298 | - 1, |
2299 | - "Got 1 service" |
2300 | -); |
2301 | - |
2302 | -is_deeply( |
2303 | - as_hashref($services->[0], with_links => 1), |
2304 | - as_hashref($svc0, with_links => 1), |
2305 | - "GET Services" |
2306 | -) or diag(Dumper(as_hashref($services, with_links => 1))); |
2307 | - |
2308 | -is( |
2309 | - $services->[0]->links->{send_data}, |
2310 | - "/query-monitor", |
2311 | - "send_data link for Service" |
2312 | -); |
2313 | - |
2314 | -# ############################################################################# |
2315 | -# Done. |
2316 | -# ############################################################################# |
2317 | -done_testing; |
2318 | |
2319 | === removed file 't/lib/Percona/WebAPI/Representation.t' |
2320 | --- t/lib/Percona/WebAPI/Representation.t 2013-03-01 16:47:49 +0000 |
2321 | +++ t/lib/Percona/WebAPI/Representation.t 1970-01-01 00:00:00 +0000 |
2322 | @@ -1,51 +0,0 @@ |
2323 | -#!/usr/bin/perl |
2324 | - |
2325 | -BEGIN { |
2326 | - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" |
2327 | - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; |
2328 | - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; |
2329 | -}; |
2330 | - |
2331 | -use strict; |
2332 | -use warnings FATAL => 'all'; |
2333 | -use English qw(-no_match_vars); |
2334 | -use Test::More; |
2335 | - |
2336 | -use PerconaTest; |
2337 | -use Percona::Toolkit; |
2338 | -use Percona::WebAPI::Resource::Agent; |
2339 | -use Percona::WebAPI::Resource::Config; |
2340 | -use Percona::WebAPI::Representation; |
2341 | - |
2342 | -my $agent = Percona::WebAPI::Resource::Agent->new( |
2343 | - id => '123', |
2344 | - hostname => 'pt', |
2345 | - versions => { |
2346 | - Perl => '5.10.1', |
2347 | - }, |
2348 | -); |
2349 | - |
2350 | -is( |
2351 | - Percona::WebAPI::Representation::as_json($agent), |
2352 | - q/{"versions":{"Perl":"5.10.1"},"id":"123","hostname":"pt"}/, |
2353 | - "as_json" |
2354 | -); |
2355 | - |
2356 | -my $config = Percona::WebAPI::Resource::Config->new( |
2357 | - ts => '100', |
2358 | - name => 'Default', |
2359 | - options => { |
2360 | - 'check-interval' => 60, |
2361 | - }, |
2362 | -); |
2363 | - |
2364 | -is( |
2365 | - Percona::WebAPI::Representation::as_config($config), |
2366 | - "check-interval=60\n", |
2367 | - "as_config" |
2368 | -); |
2369 | - |
2370 | -# ############################################################################# |
2371 | -# Done. |
2372 | -# ############################################################################# |
2373 | -done_testing; |
2374 | |
2375 | === removed directory 't/pt-agent' |
2376 | === removed file 't/pt-agent/basics.t' |
2377 | --- t/pt-agent/basics.t 2013-04-13 17:27:45 +0000 |
2378 | +++ t/pt-agent/basics.t 1970-01-01 00:00:00 +0000 |
2379 | @@ -1,101 +0,0 @@ |
2380 | -#!/usr/bin/env perl |
2381 | - |
2382 | -BEGIN { |
2383 | - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" |
2384 | - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; |
2385 | - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; |
2386 | -}; |
2387 | - |
2388 | -use strict; |
2389 | -use warnings FATAL => 'all'; |
2390 | -use English qw(-no_match_vars); |
2391 | -use Test::More; |
2392 | - |
2393 | -use File::Temp qw(tempdir); |
2394 | - |
2395 | -use Percona::Test; |
2396 | -use Sandbox; |
2397 | -use Percona::Test::Mock::UserAgent; |
2398 | -require "$trunk/bin/pt-agent"; |
2399 | - |
2400 | -my $dp = new DSNParser(opts=>$dsn_opts); |
2401 | -my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); |
2402 | -my $dbh = $sb->get_dbh_for('master'); |
2403 | -my $dsn = $sb->dsn_for('master'); |
2404 | -my $o = new OptionParser(); |
2405 | -$o->get_specs("$trunk/bin/pt-agent"); |
2406 | -$o->get_opts(); |
2407 | -my $cxn = Cxn->new( |
2408 | - dsn_string => $dsn, |
2409 | - OptionParser => $o, |
2410 | - DSNParser => $dp, |
2411 | -); |
2412 | - |
2413 | -Percona::Toolkit->import(qw(Dumper)); |
2414 | -Percona::WebAPI::Representation->import(qw(as_hashref)); |
2415 | - |
2416 | -# Running the agent is going to cause it to schedule the services, |
2417 | -# i.e. write a real crontab. The test box/user shouldn't have a |
2418 | -# crontab, so we'll warn and clobber it if there is one. |
2419 | -my $crontab = `crontab -l 2>/dev/null`; |
2420 | -if ( $crontab ) { |
2421 | - warn "Removing crontab: $crontab\n"; |
2422 | - `crontab -r`; |
2423 | -} |
2424 | - |
2425 | -my $tmp_lib = "/tmp/pt-agent"; |
2426 | -my $tmp_log = "/tmp/pt-agent.log"; |
2427 | -my $tmp_pid = "/tmp/pt-agent.pid"; |
2428 | - |
2429 | -diag(`rm -rf $tmp_lib`) if -d $tmp_lib; |
2430 | -unlink $tmp_log if -f $tmp_log; |
2431 | -unlink $tmp_pid if -f $tmp_pid; |
2432 | - |
2433 | -my $config_file = pt_agent::get_config_file(); |
2434 | -unlink $config_file if -f $config_file; |
2435 | - |
2436 | -my $output; |
2437 | - |
2438 | -{ |
2439 | - no strict; |
2440 | - no warnings; |
2441 | - local *pt_agent::start_agent = sub { |
2442 | - print "start_agent\n"; |
2443 | - return { |
2444 | - agent => 0, |
2445 | - client => 0, |
2446 | - daemon => 0, |
2447 | - }; |
2448 | - }; |
2449 | - local *pt_agent::run_agent = sub { |
2450 | - print "run_agent\n"; |
2451 | - }; |
2452 | - |
2453 | - $output = output( |
2454 | - sub { |
2455 | - pt_agent::main( |
2456 | - qw(--api-key 123) |
2457 | - ); |
2458 | - }, |
2459 | - stderr => 1, |
2460 | - ); |
2461 | -} |
2462 | - |
2463 | -like( |
2464 | - $output, |
2465 | - qr/start_agent\nrun_agent\n/, |
2466 | - "Starts and runs without a config file" |
2467 | -); |
2468 | - |
2469 | -# ############################################################################# |
2470 | -# Done. |
2471 | -# ############################################################################# |
2472 | - |
2473 | -`crontab -r 2>/dev/null`; |
2474 | - |
2475 | -if ( -f $config_file ) { |
2476 | - unlink $config_file |
2477 | - or warn "Error removing $config_file: $OS_ERROR"; |
2478 | -} |
2479 | - |
2480 | -done_testing; |
2481 | |
2482 | === removed file 't/pt-agent/get_services.t' |
2483 | --- t/pt-agent/get_services.t 2013-06-17 04:01:30 +0000 |
2484 | +++ t/pt-agent/get_services.t 1970-01-01 00:00:00 +0000 |
2485 | @@ -1,423 +0,0 @@ |
2486 | -#!/usr/bin/env perl |
2487 | - |
2488 | -BEGIN { |
2489 | - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" |
2490 | - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; |
2491 | - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; |
2492 | -}; |
2493 | - |
2494 | -use strict; |
2495 | -use warnings FATAL => 'all'; |
2496 | -use English qw(-no_match_vars); |
2497 | -use Test::More; |
2498 | - |
2499 | -use JSON; |
2500 | -use File::Temp qw(tempdir); |
2501 | - |
2502 | -use Percona::Test; |
2503 | -use Percona::Test::Mock::UserAgent; |
2504 | -use Percona::Test::Mock::AgentLogger; |
2505 | -require "$trunk/bin/pt-agent"; |
2506 | - |
2507 | -Percona::Toolkit->import(qw(Dumper)); |
2508 | -Percona::WebAPI::Representation->import(qw(as_hashref)); |
2509 | - |
2510 | -my @log; |
2511 | -my $logger = Percona::Test::Mock::AgentLogger->new(log => \@log); |
2512 | -pt_agent::_logger($logger); |
2513 | - |
2514 | -# Fake --lib and --spool dirs. |
2515 | -my $tmpdir = tempdir("/tmp/pt-agent.$PID.XXXXXX", CLEANUP => 1); |
2516 | -output( sub { |
2517 | - pt_agent::init_lib_dir(lib_dir => $tmpdir); |
2518 | -}); |
2519 | - |
2520 | -# ############################################################################# |
2521 | -# Create mock client and Agent |
2522 | -# ############################################################################# |
2523 | - |
2524 | -# These aren't the real tests yet: to run_agent, first we need |
2525 | -# a client and Agent, so create mock ones. |
2526 | - |
2527 | -my $output; |
2528 | -my $json = JSON->new->canonical([1])->pretty; |
2529 | -$json->allow_blessed([]); |
2530 | -$json->convert_blessed([]); |
2531 | - |
2532 | -my $ua = Percona::Test::Mock::UserAgent->new( |
2533 | - encode => sub { my $c = shift; return $json->encode($c || {}) }, |
2534 | -); |
2535 | - |
2536 | -my $client = eval { |
2537 | - Percona::WebAPI::Client->new( |
2538 | - api_key => '123', |
2539 | - ua => $ua, |
2540 | - ); |
2541 | -}; |
2542 | - |
2543 | -is( |
2544 | - $EVAL_ERROR, |
2545 | - '', |
2546 | - 'Create mock client' |
2547 | -) or die; |
2548 | - |
2549 | -my $agent = Percona::WebAPI::Resource::Agent->new( |
2550 | - uuid => '123', |
2551 | - hostname => 'host', |
2552 | - username => 'user', |
2553 | - links => { |
2554 | - self => '/agents/123', |
2555 | - config => '/agents/123/config', |
2556 | - }, |
2557 | -); |
2558 | - |
2559 | -my @cmds; |
2560 | -my $exec_cmd = sub { |
2561 | - my $cmd = shift; |
2562 | - push @cmds, $cmd; |
2563 | - return 0; |
2564 | -}; |
2565 | - |
2566 | -# ############################################################################# |
2567 | -# Test get_services() |
2568 | -# ############################################################################# |
2569 | - |
2570 | -# query-history |
2571 | - |
2572 | -my $run0 = Percona::WebAPI::Resource::Task->new( |
2573 | - name => 'query-history', |
2574 | - number => '0', |
2575 | - program => 'pt-query-digest --output json', |
2576 | - output => 'spool', |
2577 | -); |
2578 | - |
2579 | -my $qh = Percona::WebAPI::Resource::Service->new( |
2580 | - ts => '100', |
2581 | - name => 'query-history', |
2582 | - run_schedule => '1 * * * *', |
2583 | - spool_schedule => '2 * * * *', |
2584 | - tasks => [ $run0 ], |
2585 | - links => { |
2586 | - self => '/query-history', |
2587 | - data => '/query-history/data', |
2588 | - }, |
2589 | -); |
2590 | - |
2591 | -my $run1 = Percona::WebAPI::Resource::Task->new( |
2592 | - name => 'start-query-history', |
2593 | - number => '0', |
2594 | - program => 'echo "start-qh"', |
2595 | - output => 'spool', |
2596 | -); |
2597 | - |
2598 | -my $start_qh = Percona::WebAPI::Resource::Service->new( |
2599 | - ts => '100', |
2600 | - name => 'start-query-history', |
2601 | - meta => 1, |
2602 | - tasks => [ $run1 ], |
2603 | - links => { |
2604 | - self => '/query-history', |
2605 | - data => '/query-history/data', |
2606 | - }, |
2607 | -); |
2608 | - |
2609 | -$ua->{responses}->{get} = [ |
2610 | - { |
2611 | - headers => { 'X-Percona-Resource-Type' => 'Service' }, |
2612 | - content => [ |
2613 | - as_hashref($qh, with_links => 1), |
2614 | - as_hashref($start_qh, with_links => 1), |
2615 | - ], |
2616 | - }, |
2617 | -]; |
2618 | - |
2619 | -my $services = {}; |
2620 | -my $success = 0; |
2621 | - |
2622 | -$output = output( |
2623 | - sub { |
2624 | - ($services, $success) = pt_agent::get_services( |
2625 | - # Required args |
2626 | - link => '/agents/123/services', |
2627 | - agent => $agent, |
2628 | - client => $client, |
2629 | - lib_dir => $tmpdir, |
2630 | - services => $services, |
2631 | - # Optional args, for testing |
2632 | - json => $json, |
2633 | - bin_dir => "$trunk/bin/", |
2634 | - exec_cmd => $exec_cmd, |
2635 | - ); |
2636 | - }, |
2637 | - stderr => 1, |
2638 | -); |
2639 | - |
2640 | -is( |
2641 | - $success, |
2642 | - 1, |
2643 | - "Success" |
2644 | -); |
2645 | - |
2646 | -is( |
2647 | - ref $services, |
2648 | - 'HASH', |
2649 | - "Return services as hashref" |
2650 | -) or diag(Dumper($services)); |
2651 | - |
2652 | -is( |
2653 | - scalar keys %$services, |
2654 | - 2, |
2655 | - 'Only 2 services' |
2656 | -) or diag(Dumper($services)); |
2657 | - |
2658 | -ok( |
2659 | - exists $services->{'query-history'}, |
2660 | - "services hashref keyed on service name" |
2661 | -) or diag(Dumper($services)); |
2662 | - |
2663 | -isa_ok( |
2664 | - ref $services->{'query-history'}, |
2665 | - 'Percona::WebAPI::Resource::Service', |
2666 | - 'services->{query-history}' |
2667 | -); |
2668 | - |
2669 | -my $crontab = -f "$tmpdir/crontab" ? slurp_file("$tmpdir/crontab") : ''; |
2670 | -is( |
2671 | - $crontab, |
2672 | - "1 * * * * $trunk/bin/pt-agent --run-service query-history |
2673 | -2 * * * * $trunk/bin/pt-agent --send-data query-history |
2674 | -", |
2675 | - "crontab file" |
2676 | -) or diag($output, `ls -l $tmpdir/*`, Dumper(\@log)); |
2677 | - |
2678 | -is_deeply( |
2679 | - \@cmds, |
2680 | - [ |
2681 | - "$trunk/bin/pt-agent --run-service start-query-history >> $tmpdir/logs/start-stop.log 2>&1", |
2682 | - "crontab $tmpdir/crontab > $tmpdir/crontab.err 2>&1", |
2683 | - ], |
2684 | - "Ran start-service and crontab" |
2685 | -) or diag(Dumper(\@cmds), Dumper(\@log)); |
2686 | - |
2687 | -ok( |
2688 | - -f "$tmpdir/services/query-history", |
2689 | - "Wrote --lib/services/query-history" |
2690 | -); |
2691 | - |
2692 | -# ############################################################################# |
2693 | -# A more realistic transaction |
2694 | -# ############################################################################# |
2695 | - |
2696 | -# services/query-history should exist from the previous tests. For these |
2697 | -# tests, get_services() should update the file, so we empty it and check |
2698 | -# that it's re-created, i.e. updated. |
2699 | -diag(`echo -n > $tmpdir/services/query-history`); |
2700 | -is( |
2701 | - -s "$tmpdir/services/query-history", |
2702 | - 0, |
2703 | - "Start: empty --lib/services/query-history" |
2704 | -); |
2705 | - |
2706 | -# start-query-history |
2707 | - |
2708 | -my $task1 = Percona::WebAPI::Resource::Task->new( |
2709 | - name => 'disable-slow-query-log', |
2710 | - number => '0', |
2711 | - query => "SET GLOBAL slow_query_log=0", |
2712 | -); |
2713 | - |
2714 | -my $task2 = Percona::WebAPI::Resource::Task->new( |
2715 | - name => 'set-slow-query-log-file', |
2716 | - number => '1', |
2717 | - query => "SET GLOBAL slow_query_log_file='/tmp/slow.log'", |
2718 | -); |
2719 | - |
2720 | -my $task3 = Percona::WebAPI::Resource::Task->new( |
2721 | - name => 'set-long-query-time', |
2722 | - number => '2', |
2723 | - query => "SET GLOBAL long_query_time=0.01", |
2724 | -); |
2725 | - |
2726 | -my $task4 = Percona::WebAPI::Resource::Task->new( |
2727 | - name => 'enable-slow-query-log', |
2728 | - number => '3', |
2729 | - query => "SET GLOBAL slow_query_log=1", |
2730 | -); |
2731 | - |
2732 | -$start_qh = Percona::WebAPI::Resource::Service->new( |
2733 | - ts => '100', |
2734 | - name => 'start-query-history', |
2735 | - tasks => [ $task1, $task2, $task3, $task4 ], |
2736 | - meta => 1, |
2737 | - links => { |
2738 | - self => '/query-history', |
2739 | - data => '/query-history/data', |
2740 | - }, |
2741 | -); |
2742 | - |
2743 | -# stop-query-history |
2744 | - |
2745 | -my $task5 = Percona::WebAPI::Resource::Task->new( |
2746 | - name => 'disable-slow-query-log', |
2747 | - number => '0', |
2748 | - query => "SET GLOBAL slow_query_log=0", |
2749 | -); |
2750 | - |
2751 | -my $stop_qh = Percona::WebAPI::Resource::Service->new( |
2752 | - ts => '100', |
2753 | - name => 'stop-query-history', |
2754 | - tasks => [ $task5 ], |
2755 | - meta => 1, |
2756 | - links => { |
2757 | - self => '/query-history', |
2758 | - data => '/query-history/data', |
2759 | - }, |
2760 | -); |
2761 | - |
2762 | -# We'll use query-history from the previous tests. |
2763 | - |
2764 | -$ua->{responses}->{get} = [ |
2765 | - { |
2766 | - headers => { 'X-Percona-Resource-Type' => 'Service' }, |
2767 | - content => [ |
2768 | - as_hashref($start_qh, with_links => 1), |
2769 | - as_hashref($stop_qh, with_links => 1), |
2770 | - as_hashref($qh, with_links => 1), # from previous tests |
2771 | - ], |
2772 | - }, |
2773 | -]; |
2774 | - |
2775 | -@log = (); |
2776 | -@cmds = (); |
2777 | -$services = {}; |
2778 | -$success = 0; |
2779 | - |
2780 | -$output = output( |
2781 | - sub { |
2782 | - ($services, $success) = pt_agent::get_services( |
2783 | - # Required args |
2784 | - link => '/agents/123/services', |
2785 | - agent => $agent, |
2786 | - client => $client, |
2787 | - lib_dir => $tmpdir, |
2788 | - services => $services, |
2789 | - # Optional args, for testing |
2790 | - json => $json, |
2791 | - bin_dir => "$trunk/bin/", |
2792 | - exec_cmd => $exec_cmd, |
2793 | - ); |
2794 | - }, |
2795 | - stderr => 1, |
2796 | -); |
2797 | - |
2798 | -is_deeply( |
2799 | - \@cmds, |
2800 | - [ |
2801 | - "$trunk/bin/pt-agent --run-service start-query-history >> $tmpdir/logs/start-stop.log 2>&1", |
2802 | - "crontab $tmpdir/crontab > $tmpdir/crontab.err 2>&1", |
2803 | - ], |
2804 | - "Start: ran start-query-history" |
2805 | -) or diag(Dumper(\@cmds), $output); |
2806 | - |
2807 | -ok( |
2808 | - -f "$tmpdir/services/start-query-history", |
2809 | - "Start: added --lib/services/start-query-history" |
2810 | -) or diag($output); |
2811 | - |
2812 | -ok( |
2813 | - -f "$tmpdir/services/stop-query-history", |
2814 | - "Start: added --lib/services/stop-query-history" |
2815 | -) or diag($output); |
2816 | - |
2817 | -my $contents = slurp_file("$tmpdir/services/query-history"); |
2818 | -like( |
2819 | - $contents, |
2820 | - qr/query-history/, |
2821 | - "Start: updated --lib/services/query-history" |
2822 | -) or diag($output); |
2823 | - |
2824 | -$crontab = slurp_file("$tmpdir/crontab"); |
2825 | -is( |
2826 | - $crontab, |
2827 | - "1 * * * * $trunk/bin/pt-agent --run-service query-history |
2828 | -2 * * * * $trunk/bin/pt-agent --send-data query-history |
2829 | -", |
2830 | - "Start: only scheduled query-history" |
2831 | -) or diag($output); |
2832 | - |
2833 | -# ############################################################################# |
2834 | -# Update and restart a service |
2835 | -# ############################################################################# |
2836 | - |
2837 | -# pt-agent should remove a service's --lib/meta/ files when restarting, |
2838 | -# so create one and check that it's removed. |
2839 | -diag(`touch $tmpdir/meta/query-history.foo`); |
2840 | -ok( |
2841 | - -f "$tmpdir/meta/query-history.foo", |
2842 | - "Restart: meta file exists" |
2843 | -); |
2844 | - |
2845 | -$qh = Percona::WebAPI::Resource::Service->new( |
2846 | - ts => '200', # was 100 |
2847 | - name => 'query-history', |
2848 | - run_schedule => '1 * * * *', |
2849 | - spool_schedule => '2 * * * *', |
2850 | - tasks => [ $run0 ], |
2851 | - links => { |
2852 | - self => '/query-history', |
2853 | - data => '/query-history/data', |
2854 | - }, |
2855 | -); |
2856 | - |
2857 | -$ua->{responses}->{get} = [ |
2858 | - { |
2859 | - headers => { 'X-Percona-Resource-Type' => 'Service' }, |
2860 | - content => [ |
2861 | - as_hashref($start_qh, with_links => 1), # has not changed |
2862 | - as_hashref($stop_qh, with_links => 1), # has not changed |
2863 | - as_hashref($qh, with_links => 1), |
2864 | - ], |
2865 | - }, |
2866 | -]; |
2867 | - |
2868 | -@log = (); |
2869 | -@cmds = (); |
2870 | -$success = 0; |
2871 | - |
2872 | -$output = output( |
2873 | - sub { |
2874 | - ($services, $success) = pt_agent::get_services( |
2875 | - # Required args |
2876 | - link => '/agents/123/services', |
2877 | - agent => $agent, |
2878 | - client => $client, |
2879 | - lib_dir => $tmpdir, |
2880 | - services => $services, # retval from previous call |
2881 | - # Optional args, for testing |
2882 | - json => $json, |
2883 | - bin_dir => "$trunk/bin/", |
2884 | - exec_cmd => $exec_cmd, |
2885 | - ); |
2886 | - }, |
2887 | - stderr => 1, |
2888 | -); |
2889 | - |
2890 | -is_deeply( |
2891 | - \@cmds, |
2892 | - [ |
2893 | - "$trunk/bin/pt-agent --run-service stop-query-history >> $tmpdir/logs/start-stop.log 2>&1", |
2894 | - "$trunk/bin/pt-agent --run-service start-query-history >> $tmpdir/logs/start-stop.log 2>&1", |
2895 | - "crontab $tmpdir/crontab > $tmpdir/crontab.err 2>&1", |
2896 | - ], |
2897 | - "Restart: ran stop-query-history then start-query-history" |
2898 | -) or diag(Dumper(\@cmds), $output); |
2899 | - |
2900 | -ok( |
2901 | - !-f "$tmpdir/meta/query-history.foo", |
2902 | - "Restart: meta file removed" |
2903 | -) or diag($output); |
2904 | - |
2905 | -# ############################################################################# |
2906 | -# Done. |
2907 | -# ############################################################################# |
2908 | -done_testing; |
2909 | |
2910 | === removed file 't/pt-agent/init_agent.t' |
2911 | --- t/pt-agent/init_agent.t 2013-09-23 19:07:34 +0000 |
2912 | +++ t/pt-agent/init_agent.t 1970-01-01 00:00:00 +0000 |
2913 | @@ -1,333 +0,0 @@ |
2914 | -#!/usr/bin/env perl |
2915 | - |
2916 | -BEGIN { |
2917 | - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" |
2918 | - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; |
2919 | - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; |
2920 | -}; |
2921 | - |
2922 | -use strict; |
2923 | -use warnings FATAL => 'all'; |
2924 | -use English qw(-no_match_vars); |
2925 | -use Test::More; |
2926 | -use JSON; |
2927 | -use File::Temp qw(tempdir); |
2928 | - |
2929 | -use Percona::Test; |
2930 | -use Percona::Test::Mock::UserAgent; |
2931 | -use Percona::Test::Mock::AgentLogger; |
2932 | -require "$trunk/bin/pt-agent"; |
2933 | - |
2934 | -Percona::Toolkit->import(qw(Dumper)); |
2935 | -Percona::WebAPI::Representation->import(qw(as_hashref)); |
2936 | - |
2937 | -my $tmpdir = tempdir("/tmp/pt-agent.$PID.XXXXXX", CLEANUP => 1); |
2938 | - |
2939 | -my $json = JSON->new->canonical([1])->pretty; |
2940 | -$json->allow_blessed([]); |
2941 | -$json->convert_blessed([]); |
2942 | - |
2943 | -my @log; |
2944 | -my $logger = Percona::Test::Mock::AgentLogger->new(log => \@log); |
2945 | -pt_agent::_logger($logger); |
2946 | - |
2947 | -my $ua = Percona::Test::Mock::UserAgent->new( |
2948 | - encode => sub { my $c = shift; return $json->encode($c || {}) }, |
2949 | -); |
2950 | - |
2951 | -my $client = eval { |
2952 | - Percona::WebAPI::Client->new( |
2953 | - api_key => '123', |
2954 | - ua => $ua, |
2955 | - ); |
2956 | -}; |
2957 | - |
2958 | -is( |
2959 | - $EVAL_ERROR, |
2960 | - '', |
2961 | - 'Create Client with mock user agent' |
2962 | -) or die; |
2963 | - |
2964 | -my @ok; |
2965 | -my $oktorun = sub { |
2966 | - return shift @ok; |
2967 | -}; |
2968 | - |
2969 | -my @wait; |
2970 | -my $interval = sub { |
2971 | - my $t = shift; |
2972 | - push @wait, $t; |
2973 | -}; |
2974 | - |
2975 | -# ############################################################################# |
2976 | -# Init a new agent, i.e. create it. |
2977 | -# ############################################################################# |
2978 | - |
2979 | -my $post_agent = Percona::WebAPI::Resource::Agent->new( |
2980 | - uuid => '123', |
2981 | - hostname => 'host1', |
2982 | - username => 'name1', |
2983 | - versions => { |
2984 | - }, |
2985 | - links => { |
2986 | - self => '/agents/123', |
2987 | - config => '/agents/123/config', |
2988 | - }, |
2989 | -); |
2990 | - |
2991 | -my $return_agent = Percona::WebAPI::Resource::Agent->new( |
2992 | - uuid => '123', |
2993 | - hostname => 'host2', |
2994 | - username => 'name2', |
2995 | - versions => { |
2996 | - }, |
2997 | - links => { |
2998 | - self => '/agents/123', |
2999 | - config => '/agents/123/config', |
3000 | - }, |
3001 | -); |
3002 | - |
3003 | -$ua->{responses}->{post} = [ |
3004 | - { |
3005 | - headers => { 'Location' => '/agents/123' }, |
3006 | - }, |
3007 | -]; |
3008 | - |
3009 | -$ua->{responses}->{get} = [ |
3010 | - { |
3011 | - headers => { 'X-Percona-Resource-Type' => 'Agent' }, |
3012 | - content => as_hashref($return_agent, with_links =>1 ), |
3013 | - }, |
3014 | -]; |
3015 | - |
3016 | -my $got_agent; |
3017 | -my $output = output( |
3018 | - sub { |
3019 | - ($got_agent) = pt_agent::init_agent( |
3020 | - agent => $post_agent, |
3021 | - action => 'post', |
3022 | - link => "/agents", |
3023 | - client => $client, |
3024 | - interval => $interval, |
3025 | - tries => 4, |
3026 | - ); |
3027 | - }, |
3028 | - stderr => 1, |
3029 | -); |
3030 | - |
3031 | -is( |
3032 | - $got_agent->hostname, |
3033 | - 'host2', |
3034 | - 'Got and returned Agent' |
3035 | -) or diag($output, Dumper(as_hashref($got_agent, with_links => 1))); |
3036 | - |
3037 | -is( |
3038 | - scalar @wait, |
3039 | - 0, |
3040 | - "Client did not wait (new Agent)" |
3041 | -) or diag($output); |
3042 | - |
3043 | -# ############################################################################# |
3044 | -# Repeat this test but this time fake an error, so the tool isn't able |
3045 | -# to create the Agent first time, so it should wait (call interval), |
3046 | -# and try again. |
3047 | -# ############################################################################# |
3048 | - |
3049 | -$return_agent->{id} = '456'; |
3050 | -$return_agent->{links} = { |
3051 | - self => '/agents/456', |
3052 | - config => '/agents/456/config', |
3053 | -}; |
3054 | - |
3055 | -$ua->{responses}->{post} = [ |
3056 | - { # 1, the fake error |
3057 | - code => 500, |
3058 | - }, |
3059 | - # 2, code should call interval |
3060 | - { # 3, code should try again, then receive this |
3061 | - code => 200, |
3062 | - headers => { 'Location' => '/agents/456' }, |
3063 | - }, |
3064 | -]; |
3065 | - # 4, code will GET the new Agent |
3066 | -$ua->{responses}->{get} = [ |
3067 | - { |
3068 | - headers => { 'X-Percona-Resource-Type' => 'Agent' }, |
3069 | - content => as_hashref($return_agent, with_links =>1 ), |
3070 | - }, |
3071 | -]; |
3072 | - |
3073 | -@ok = qw(1 1 0); |
3074 | -@wait = (); |
3075 | -@log = (); |
3076 | -$ua->{requests} = []; |
3077 | - |
3078 | -$output = output( |
3079 | - sub { |
3080 | - ($got_agent) = pt_agent::init_agent( |
3081 | - agent => $post_agent, |
3082 | - action => 'post', |
3083 | - link => "/agents", |
3084 | - client => $client, |
3085 | - interval => $interval, |
3086 | - tries => 5, |
3087 | - oktorun => $oktorun, |
3088 | - ); |
3089 | - }, |
3090 | - stderr => 1, |
3091 | -); |
3092 | - |
3093 | -is( |
3094 | - ($got_agent ? $got_agent->hostname : ''), |
3095 | - 'host2', |
3096 | - 'Got and returned Agent after error' |
3097 | -) or diag($output, Dumper($got_agent)); |
3098 | - |
3099 | -is( |
3100 | - scalar @wait, |
3101 | - 1, |
3102 | - "Client waited after error" |
3103 | -); |
3104 | - |
3105 | -is_deeply( |
3106 | - $ua->{requests}, |
3107 | - [ |
3108 | - 'POST /agents', # first attempt, 500 error |
3109 | - 'POST /agents', # second attemp, 200 OK |
3110 | - 'GET /agents/456', # GET new Agent |
3111 | - ], |
3112 | - "POST POST GET new Agent after error" |
3113 | -) or diag(Dumper($ua->{requests})); |
3114 | - |
3115 | -like( |
3116 | - $log[1], |
3117 | - qr{WARNING Failed to POST /agents}, |
3118 | - "POST /agents failure logged after error" |
3119 | -) or diag(Dumper($ua->{requests}), Dumper(\@log)); |
3120 | - |
3121 | -# ############################################################################# |
3122 | -# Init an existing agent, i.e. update it. |
3123 | -# ############################################################################# |
3124 | - |
3125 | -my $put_agent = Percona::WebAPI::Resource::Agent->new( |
3126 | - uuid => '123', |
3127 | - hostname => 'host3', |
3128 | - username => 'name3', |
3129 | - versions => { |
3130 | - }, |
3131 | - links => { |
3132 | - self => '/agents/123', |
3133 | - config => '/agents/123/config', |
3134 | - }, |
3135 | -); |
3136 | - |
3137 | -$ua->{responses}->{put} = [ |
3138 | - { |
3139 | - code => 200, |
3140 | - headers => { |
3141 | - Location => '/agents/123', |
3142 | - }, |
3143 | - }, |
3144 | -]; |
3145 | -$ua->{responses}->{get} = [ |
3146 | - { |
3147 | - code => 200, |
3148 | - headers => { 'X-Percona-Resource-Type' => 'Agent' }, |
3149 | - content => as_hashref($return_agent, with_links =>1 ), |
3150 | - } |
3151 | -]; |
3152 | - |
3153 | -@wait = (); |
3154 | -$ua->{requests} = []; |
3155 | - |
3156 | -$output = output( |
3157 | - sub { |
3158 | - ($got_agent) = pt_agent::init_agent( |
3159 | - agent => $put_agent, |
3160 | - action => 'put', |
3161 | - link => "/agents/123", |
3162 | - client => $client, |
3163 | - interval => $interval, |
3164 | - tries => 4, |
3165 | - ); |
3166 | - }, |
3167 | - stderr => 1, |
3168 | -); |
3169 | - |
3170 | -is( |
3171 | - $got_agent->hostname, |
3172 | - 'host2', |
3173 | - 'PUT Agent' |
3174 | -) or diag($output, Dumper(as_hashref($got_agent, with_links => 1))); |
3175 | - |
3176 | -is( |
3177 | - scalar @wait, |
3178 | - 0, |
3179 | - "Client did not wait (saved Agent)" |
3180 | -); |
3181 | - |
3182 | -is_deeply( |
3183 | - $ua->{requests}, |
3184 | - [ |
3185 | - 'PUT /agents/123', |
3186 | - 'GET /agents/123', |
3187 | - ], |
3188 | - "PUT then GET Agent" |
3189 | -) or diag(Dumper($ua->{requests})); |
3190 | - |
3191 | -# ############################################################################# |
3192 | -# Status 403 (too many agents) should abort further attempts. |
3193 | -# ############################################################################# |
3194 | - |
3195 | -$ua->{responses}->{post} = [ |
3196 | - { # 1, the fake error |
3197 | - code => 403, |
3198 | - }, |
3199 | -]; |
3200 | - |
3201 | -@ok = qw(1 1 0); |
3202 | -@wait = (); |
3203 | -@log = (); |
3204 | -$ua->{requests} = []; |
3205 | - |
3206 | -$output = output( |
3207 | - sub { |
3208 | - ($got_agent) = pt_agent::init_agent( |
3209 | - agent => $post_agent, |
3210 | - action => 'post', |
3211 | - link => "/agents", |
3212 | - client => $client, |
3213 | - interval => $interval, |
3214 | - tries => 3, |
3215 | - oktorun => $oktorun, |
3216 | - ); |
3217 | - }, |
3218 | - stderr => 1, |
3219 | -); |
3220 | - |
3221 | -is( |
3222 | - scalar @wait, |
3223 | - 2, |
3224 | - "Too many agents (403): waits" |
3225 | -); |
3226 | - |
3227 | -is_deeply( |
3228 | - $ua->{requests}, |
3229 | - [ |
3230 | - 'POST /agents', |
3231 | - 'POST /agents', |
3232 | - ], |
3233 | - "Too many agents (403): tries" |
3234 | -) or diag(Dumper($ua->{requests})); |
3235 | - |
3236 | -my $n = grep { $_ =~ m/too many agents/ } @log; |
3237 | -is( |
3238 | - $n, |
3239 | - 1, |
3240 | - "Too many agents (403): does not repeat warning" |
3241 | -) or diag(Dumper(\@log)); |
3242 | - |
3243 | -# ############################################################################# |
3244 | -# Done. |
3245 | -# ############################################################################# |
3246 | -done_testing; |
3247 | |
3248 | === removed file 't/pt-agent/make_new_crontab.t' |
3249 | --- t/pt-agent/make_new_crontab.t 2013-04-19 20:49:01 +0000 |
3250 | +++ t/pt-agent/make_new_crontab.t 1970-01-01 00:00:00 +0000 |
3251 | @@ -1,151 +0,0 @@ |
3252 | -#!/usr/bin/env perl |
3253 | - |
3254 | -BEGIN { |
3255 | - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" |
3256 | - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; |
3257 | - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; |
3258 | -}; |
3259 | - |
3260 | -use strict; |
3261 | -use warnings FATAL => 'all'; |
3262 | -use English qw(-no_match_vars); |
3263 | -use Test::More; |
3264 | -use JSON; |
3265 | -use File::Temp qw(tempfile); |
3266 | - |
3267 | -use Percona::Test; |
3268 | -require "$trunk/bin/pt-agent"; |
3269 | - |
3270 | -Percona::Toolkit->import(qw(have_required_args Dumper)); |
3271 | - |
3272 | -my $sample = "t/pt-agent/samples"; |
3273 | - |
3274 | -sub test_make_new_crontab { |
3275 | - my (%args) = @_; |
3276 | - have_required_args(\%args, qw( |
3277 | - file |
3278 | - services |
3279 | - )) or die; |
3280 | - my $file = $args{file}; |
3281 | - my $services = $args{services}; |
3282 | - |
3283 | - my $crontab_list = slurp_file("$trunk/$sample/$file.in"); |
3284 | - |
3285 | - my $new_crontab = pt_agent::make_new_crontab( |
3286 | - services => $services, |
3287 | - crontab_list => $crontab_list, |
3288 | - bin_dir => '', |
3289 | - ); |
3290 | - |
3291 | - ok( |
3292 | - no_diff( |
3293 | - $new_crontab, |
3294 | - "$sample/$file.out", |
3295 | - cmd_output => 1, |
3296 | - ), |
3297 | - $args{name} || $file, |
3298 | - ) or diag($new_crontab); |
3299 | -} |
3300 | - |
3301 | -my $run0 = Percona::WebAPI::Resource::Task->new( |
3302 | - name => 'query-history', |
3303 | - number => '0', |
3304 | - program => 'pt-query-digest', |
3305 | - options => '--output json', |
3306 | - output => 'spool', |
3307 | -); |
3308 | - |
3309 | -my $svc0 = Percona::WebAPI::Resource::Service->new( |
3310 | - ts => '100', |
3311 | - name => 'query-history', |
3312 | - run_schedule => '* 8 * * 1,2,3,4,5', |
3313 | - spool_schedule => '* 9 * * 1,2,3,4,5', |
3314 | - tasks => [ $run0 ], |
3315 | -); |
3316 | - |
3317 | -# Empty crontab, add the service. |
3318 | -test_make_new_crontab( |
3319 | - file => "crontab001", |
3320 | - services => [ $svc0 ], |
3321 | -); |
3322 | - |
3323 | -# Crontab has another line, add the service to it. |
3324 | -test_make_new_crontab( |
3325 | - file => "crontab002", |
3326 | - services => [ $svc0 ], |
3327 | -); |
3328 | - |
3329 | -# Crontab has another line and an old service, remove the old service |
3330 | -# and add the current service. |
3331 | -test_make_new_crontab( |
3332 | - file => "crontab003", |
3333 | - services => [ $svc0 ], |
3334 | -); |
3335 | - |
3336 | -# Crontab has old service, remove it and add only new service. |
3337 | -test_make_new_crontab( |
3338 | - file => "crontab004", |
3339 | - services => [ $svc0 ], |
3340 | -); |
3341 | - |
3342 | -# ############################################################################# |
3343 | -# Use real crontab. |
3344 | -# ############################################################################# |
3345 | - |
3346 | -# The previous tests pass in a crontab file to make testing easier. |
3347 | -# Now test that make_new_crontab() will run `crontab -l' if not given |
3348 | -# input. To test this, we add a fake line to our crontab. If |
3349 | -# make_new_crontab() really runs `crontab -l', then this fake line |
3350 | -# will be in the new crontab it returns. |
3351 | - |
3352 | -my $crontab = `crontab -l 2>/dev/null`; |
3353 | -SKIP: { |
3354 | - skip 'Crontab is not empty', 3 if $crontab; |
3355 | - |
3356 | - # On most systems[1], crontab lines must end with a newline, |
3357 | - # else an error like this happens: |
3358 | - # "/tmp/new_crontab_file":1: premature EOF |
3359 | - # errors in crontab file, can't install. |
3360 | - # [1] Ubuntu 10 and Mac OS X work without the newline. |
3361 | - my ($fh, $file) = tempfile(); |
3362 | - print {$fh} "* 0 * * * date > /dev/null\n"; |
3363 | - close $fh or warn "Cannot close $file: $OS_ERROR"; |
3364 | - my $output = `crontab $file 2>&1`; |
3365 | - |
3366 | - $crontab = `crontab -l 2>&1`; |
3367 | - |
3368 | - is( |
3369 | - $crontab, |
3370 | - "* 0 * * * date > /dev/null\n", |
3371 | - "Set other crontab line" |
3372 | - ) or diag($output); |
3373 | - |
3374 | - unlink $file or warn "Cannot remove $file: $OS_ERROR"; |
3375 | - |
3376 | - my $new_crontab = pt_agent::make_new_crontab( |
3377 | - services => [ $svc0 ], |
3378 | - bin_dir => '', |
3379 | - ); |
3380 | - |
3381 | - is( |
3382 | - $new_crontab, |
3383 | - "* 0 * * * date > /dev/null |
3384 | -* 8 * * 1,2,3,4,5 pt-agent --run-service query-history |
3385 | -* 9 * * 1,2,3,4,5 pt-agent --send-data query-history |
3386 | -", |
3387 | - "Runs crontab -l by default" |
3388 | - ); |
3389 | - |
3390 | - system("crontab -r 2>/dev/null"); |
3391 | - $crontab = `crontab -l 2>/dev/null`; |
3392 | - is( |
3393 | - $crontab, |
3394 | - "", |
3395 | - "Removed crontab" |
3396 | - ); |
3397 | -}; |
3398 | - |
3399 | -# ############################################################################# |
3400 | -# Done. |
3401 | -# ############################################################################# |
3402 | -done_testing; |
3403 | |
3404 | === removed file 't/pt-agent/replace_special_vars.t' |
3405 | --- t/pt-agent/replace_special_vars.t 2013-06-17 00:28:18 +0000 |
3406 | +++ t/pt-agent/replace_special_vars.t 1970-01-01 00:00:00 +0000 |
3407 | @@ -1,73 +0,0 @@ |
3408 | -#!/usr/bin/env perl |
3409 | - |
3410 | -BEGIN { |
3411 | - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" |
3412 | - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; |
3413 | - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; |
3414 | -}; |
3415 | - |
3416 | -use strict; |
3417 | -use warnings FATAL => 'all'; |
3418 | -use English qw(-no_match_vars); |
3419 | -use Test::More; |
3420 | -use JSON; |
3421 | -use File::Temp qw(tempfile); |
3422 | - |
3423 | -use Percona::Test; |
3424 | -use Percona::Test::Mock::AgentLogger; |
3425 | -require "$trunk/bin/pt-agent"; |
3426 | - |
3427 | -Percona::Toolkit->import(qw(have_required_args Dumper)); |
3428 | - |
3429 | -my @log; |
3430 | -my $logger = Percona::Test::Mock::AgentLogger->new(log => \@log); |
3431 | -pt_agent::_logger($logger); |
3432 | - |
3433 | -my @output_files = (); |
3434 | -my $store = {}; |
3435 | - |
3436 | -sub test_replace { |
3437 | - my (%args) = @_; |
3438 | - have_required_args(\%args, qw( |
3439 | - cmd |
3440 | - expect |
3441 | - )) or die; |
3442 | - my $cmd = $args{cmd}; |
3443 | - my $expect = $args{expect}; |
3444 | - |
3445 | - my $new_cmd = pt_agent::replace_special_vars( |
3446 | - cmd => $cmd, |
3447 | - output_files => \@output_files, |
3448 | - service => 'service-name', |
3449 | - lib_dir => '/var/lib/pt-agent', |
3450 | - meta_dir => '/var/lib/pt-agent/meta', |
3451 | - stage_dir => '/var/spool/.tmp', |
3452 | - spool_dir => '/var/spool', |
3453 | - bin_dir => $trunk, |
3454 | - ts => '123', |
3455 | - store => $store, |
3456 | - ); |
3457 | - |
3458 | - is( |
3459 | - $new_cmd, |
3460 | - $expect, |
3461 | - $cmd, |
3462 | - ); |
3463 | -}; |
3464 | - |
3465 | -@output_files = qw(zero one two); |
3466 | -test_replace( |
3467 | - cmd => "pt-query-digest __RUN_0_OUTPUT__", |
3468 | - expect => "pt-query-digest zero", |
3469 | -); |
3470 | - |
3471 | -$store->{slow_query_log_file} = 'slow.log'; |
3472 | -test_replace( |
3473 | - cmd => "echo '__STORE_slow_query_log_file__' > /var/spool/pt-agent/.tmp/1371269644.rotate-slow-query-log-all-5.1.slow_query_log_file", |
3474 | - expect => "echo 'slow.log' > /var/spool/pt-agent/.tmp/1371269644.rotate-slow-query-log-all-5.1.slow_query_log_file", |
3475 | -); |
3476 | - |
3477 | -# ############################################################################# |
3478 | -# Done. |
3479 | -# ############################################################################# |
3480 | -done_testing; |
3481 | |
3482 | === removed file 't/pt-agent/run_agent.t' |
3483 | --- t/pt-agent/run_agent.t 2013-06-17 04:01:30 +0000 |
3484 | +++ t/pt-agent/run_agent.t 1970-01-01 00:00:00 +0000 |
3485 | @@ -1,527 +0,0 @@ |
3486 | -#!/usr/bin/env perl |
3487 | - |
3488 | -BEGIN { |
3489 | - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" |
3490 | - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; |
3491 | - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; |
3492 | -}; |
3493 | - |
3494 | -use strict; |
3495 | -use warnings FATAL => 'all'; |
3496 | -use English qw(-no_match_vars); |
3497 | -use Test::More; |
3498 | - |
3499 | -plan skip_all => "Need to make start-service testable"; |
3500 | - |
3501 | -use JSON; |
3502 | -use File::Temp qw(tempdir); |
3503 | - |
3504 | -use Percona::Test; |
3505 | -use Sandbox; |
3506 | -use Percona::Test::Mock::UserAgent; |
3507 | -use Percona::Test::Mock::AgentLogger; |
3508 | -require "$trunk/bin/pt-agent"; |
3509 | - |
3510 | -my $dp = new DSNParser(opts=>$dsn_opts); |
3511 | -my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); |
3512 | -my $dbh = $sb->get_dbh_for('master'); |
3513 | -my $dsn = $sb->dsn_for('master'); |
3514 | -my $o = new OptionParser(); |
3515 | -$o->get_specs("$trunk/bin/pt-agent"); |
3516 | -$o->get_opts(); |
3517 | -my $cxn = Cxn->new( |
3518 | - dsn_string => $dsn, |
3519 | - OptionParser => $o, |
3520 | - DSNParser => $dp, |
3521 | -); |
3522 | - |
3523 | -Percona::Toolkit->import(qw(Dumper)); |
3524 | -Percona::WebAPI::Representation->import(qw(as_hashref)); |
3525 | - |
3526 | -# Running the agent is going to cause it to schedule the services, |
3527 | -# i.e. write a real crontab. The test box/user shouldn't have a |
3528 | -# crontab, so we'll warn and clobber it if there is one. |
3529 | -my $crontab = `crontab -l 2>/dev/null`; |
3530 | -if ( $crontab ) { |
3531 | - warn "Removing crontab: $crontab\n"; |
3532 | - `crontab -r`; |
3533 | -} |
3534 | - |
3535 | -# Fake --lib and --spool dirs. |
3536 | -my $tmpdir = tempdir("/tmp/pt-agent.$PID.XXXXXX"); #, CLEANUP => 1); |
3537 | -mkdir "$tmpdir/spool" or die "Error making $tmpdir/spool: $OS_ERROR"; |
3538 | - |
3539 | -my @log; |
3540 | -my $logger = Percona::Test::Mock::AgentLogger->new(log => \@log); |
3541 | -pt_agent::_logger($logger); |
3542 | - |
3543 | -# ############################################################################# |
3544 | -# Create mock client and Agent |
3545 | -# ############################################################################# |
3546 | - |
3547 | -# These aren't the real tests yet: to run_agent, first we need |
3548 | -# a client and Agent, so create mock ones. |
3549 | - |
3550 | -my $output; |
3551 | -my $json = JSON->new->canonical([1])->pretty; |
3552 | -$json->allow_blessed([]); |
3553 | -$json->convert_blessed([]); |
3554 | - |
3555 | -my $ua = Percona::Test::Mock::UserAgent->new( |
3556 | - encode => sub { my $c = shift; return $json->encode($c || {}) }, |
3557 | -); |
3558 | - |
3559 | -my $client = eval { |
3560 | - Percona::WebAPI::Client->new( |
3561 | - api_key => '123', |
3562 | - ua => $ua, |
3563 | - ); |
3564 | -}; |
3565 | - |
3566 | -is( |
3567 | - $EVAL_ERROR, |
3568 | - '', |
3569 | - 'Create mock client' |
3570 | -) or die; |
3571 | - |
3572 | -my $agent = Percona::WebAPI::Resource::Agent->new( |
3573 | - uuid => '123', |
3574 | - hostname => 'host', |
3575 | - username => 'user', |
3576 | - links => { |
3577 | - self => '/agents/123', |
3578 | - config => '/agents/123/config', |
3579 | - }, |
3580 | -); |
3581 | - |
3582 | -my $daemon = Daemon->new( |
3583 | - daemonzie => 0, |
3584 | -); |
3585 | - |
3586 | -my @wait; |
3587 | -my $interval = sub { |
3588 | - my $t = shift; |
3589 | - push @wait, $t; |
3590 | - print "interval=" . (defined $t ? $t : 'undef') . "\n"; |
3591 | -}; |
3592 | - |
3593 | -# ############################################################################# |
3594 | -# Test run_agent |
3595 | -# ############################################################################# |
3596 | - |
3597 | -my $config = Percona::WebAPI::Resource::Config->new( |
3598 | - ts => 1363720060, |
3599 | - name => 'Default', |
3600 | - options => { |
3601 | - 'lib' => $tmpdir, # required |
3602 | - 'spool' => "$tmpdir/spool", # required |
3603 | - 'check-interval' => "11", |
3604 | - }, |
3605 | - links => { |
3606 | - self => '/agents/123/config', |
3607 | - services => '/agents/123/services', |
3608 | - }, |
3609 | -); |
3610 | - |
3611 | -my $run0 = Percona::WebAPI::Resource::Task->new( |
3612 | - name => 'query-history', |
3613 | - number => '0', |
3614 | - program => 'pt-query-digest', |
3615 | - options => '--output json', |
3616 | - output => 'spool', |
3617 | -); |
3618 | - |
3619 | -my $svc0 = Percona::WebAPI::Resource::Service->new( |
3620 | - ts => 100, |
3621 | - name => 'query-history', |
3622 | - run_schedule => '1 * * * *', |
3623 | - spool_schedule => '2 * * * *', |
3624 | - tasks => [ $run0 ], |
3625 | - links => { |
3626 | - self => '/query-history', |
3627 | - data => '/query-history/data', |
3628 | - }, |
3629 | -); |
3630 | - |
3631 | -my $run1 = Percona::WebAPI::Resource::Task->new( |
3632 | - name => 'start-query-history', |
3633 | - number => '0', |
3634 | - program => 'echo "start-qh"', |
3635 | -); |
3636 | - |
3637 | -my $start_qh = Percona::WebAPI::Resource::Service->new( |
3638 | - ts => '100', |
3639 | - name => 'start-query-history', |
3640 | - meta => 1, |
3641 | - tasks => [ $run1 ], |
3642 | - links => { |
3643 | - self => '/query-history', |
3644 | - data => '/query-history/data', |
3645 | - }, |
3646 | -); |
3647 | - |
3648 | -$ua->{responses}->{get} = [ |
3649 | - { |
3650 | - headers => { 'X-Percona-Resource-Type' => 'Config' }, |
3651 | - content => as_hashref($config, with_links => 1), |
3652 | - }, |
3653 | - { |
3654 | - headers => { 'X-Percona-Resource-Type' => 'Service' }, |
3655 | - content => [ |
3656 | - as_hashref($start_qh, with_links => 1), |
3657 | - as_hashref($svc0, with_links => 1), |
3658 | - ], |
3659 | - }, |
3660 | -]; |
3661 | - |
3662 | -my $safeguards = Safeguards->new( |
3663 | - disk_bytes_free => 1024, |
3664 | - disk_pct_free => 1, |
3665 | -); |
3666 | - |
3667 | -# The only thing pt-agent must have is the API key in the config file, |
3668 | -# everything else relies on defaults until the first Config is gotten |
3669 | -# from Percona. |
3670 | -my $config_file = pt_agent::get_config_file(); |
3671 | -unlink $config_file if -f $config_file; |
3672 | - |
3673 | -like( |
3674 | - $config_file, |
3675 | - qr/$ENV{LOGNAME}\/\.pt-agent.conf$/, |
3676 | - "Default config file is ~/.pt-agent.config" |
3677 | -); |
3678 | - |
3679 | -pt_agent::write_config( |
3680 | - config => $config |
3681 | -); |
3682 | - |
3683 | -diag(`echo 'api-key=123' >> $config_file`); |
3684 | - |
3685 | -is( |
3686 | - `cat $config_file`, |
3687 | - "check-interval=11\nlib=$tmpdir\nspool=$tmpdir/spool\napi-key=123\n", |
3688 | - "Write Config to config file" |
3689 | -); |
3690 | - |
3691 | -pt_agent::save_agent( |
3692 | - agent => $agent, |
3693 | - lib_dir => $tmpdir, |
3694 | -); |
3695 | - |
3696 | -my @ok_code = (); # callbacks |
3697 | -my @oktorun = ( |
3698 | - 1, # 1st main loop check |
3699 | - 0, # 2nd main loop check |
3700 | -); |
3701 | -my $oktorun = sub { |
3702 | - my $ok = shift @oktorun; |
3703 | - print "oktorun=" . (defined $ok ? $ok : 'undef') . "\n"; |
3704 | - my $code = shift @ok_code; |
3705 | - $code->() if $code; |
3706 | - return $ok |
3707 | -}; |
3708 | - |
3709 | -@wait = (); |
3710 | - |
3711 | -$output = output( |
3712 | - sub { |
3713 | - pt_agent::run_agent( |
3714 | - # Required args |
3715 | - agent => $agent, |
3716 | - client => $client, |
3717 | - daemon => $daemon, |
3718 | - interval => $interval, |
3719 | - lib_dir => $tmpdir, |
3720 | - safeguards => $safeguards, |
3721 | - Cxn => $cxn, |
3722 | - # Optional args, for testing |
3723 | - oktorun => $oktorun, |
3724 | - json => $json, |
3725 | - bin_dir => "$trunk/bin", |
3726 | - ); |
3727 | - }, |
3728 | - stderr => 1, |
3729 | -); |
3730 | - |
3731 | -is( |
3732 | - scalar @wait, |
3733 | - 1, |
3734 | - "Called interval once" |
3735 | -); |
3736 | - |
3737 | -is( |
3738 | - $wait[0], |
3739 | - 11, |
3740 | - "... used Config->options->check-interval" |
3741 | -); |
3742 | - |
3743 | -ok( |
3744 | - -f "$tmpdir/services/query-history", |
3745 | - "Created services/query-history" |
3746 | -) or diag($output); |
3747 | - |
3748 | -chomp(my $n_files = `ls -1 $tmpdir/services| wc -l | awk '{print \$1}'`); |
3749 | -is( |
3750 | - $n_files, |
3751 | - 2, |
3752 | - "... created services/query-history and services/start-query-history" |
3753 | -); |
3754 | - |
3755 | -ok( |
3756 | - no_diff( |
3757 | - "cat $tmpdir/services/query-history", |
3758 | - "t/pt-agent/samples/service001", |
3759 | - ), |
3760 | - "query-history service file" |
3761 | -); |
3762 | - |
3763 | -$crontab = `crontab -l 2>/dev/null`; |
3764 | -like( |
3765 | - $crontab, |
3766 | - qr/pt-agent --run-service query-history$/m, |
3767 | - "Scheduled --run-service with crontab" |
3768 | -) or diag(Dumper(\@log)); |
3769 | - |
3770 | -like( |
3771 | - $crontab, |
3772 | - qr/pt-agent --send-data query-history$/m, |
3773 | - "Scheduled --send-data with crontab" |
3774 | -) or diag(Dumper(\@log)); |
3775 | -exit; |
3776 | -# ############################################################################# |
3777 | -# Run run_agent again, like the agent had been stopped and restarted. |
3778 | -# ############################################################################# |
3779 | - |
3780 | -$ua->{responses}->{get} = [ |
3781 | - # First check, fail |
3782 | - { |
3783 | - code => 500, |
3784 | - }, |
3785 | - # interval |
3786 | - # 2nd check, init with latest Config and Services |
3787 | - { |
3788 | - headers => { 'X-Percona-Resource-Type' => 'Config' }, |
3789 | - content => as_hashref($config, with_links => 1), |
3790 | - }, |
3791 | - { |
3792 | - headers => { 'X-Percona-Resource-Type' => 'Service' }, |
3793 | - content => [ as_hashref($svc0, with_links => 1) ], |
3794 | - }, |
3795 | - # interval |
3796 | - # 3rd check, same Config and Services so nothing to do |
3797 | - { |
3798 | - headers => { 'X-Percona-Resource-Type' => 'Config' }, |
3799 | - content => as_hashref($config, with_links => 1), |
3800 | - }, |
3801 | - { |
3802 | - headers => { 'X-Percona-Resource-Type' => 'Service' }, |
3803 | - content => [ as_hashref($svc0, with_links => 1) ], |
3804 | - }, |
3805 | - # interval, oktorun=0 |
3806 | -]; |
3807 | - |
3808 | -@oktorun = ( |
3809 | - 1, # 1st main loop check |
3810 | - # First check, error 500 |
3811 | - 1, # 2nd main loop check |
3812 | - # Init with latest Config and Services |
3813 | - 1, # 3rd main loop check |
3814 | - # Same Config and services |
3815 | - 0, # 4th main loop check |
3816 | -); |
3817 | - |
3818 | -# Before the 3rd check, remove the config file (~/.pt-agent.conf) and |
3819 | -# query-history service file. When the tool re-GETs these, they'll be |
3820 | -# the same so it won't recreate them. A bug here will cause these files to |
3821 | -# exist again after running. |
3822 | -$ok_code[2] = sub { |
3823 | - unlink "$config_file"; |
3824 | - unlink "$tmpdir/services/query-history"; |
3825 | - Percona::Test::wait_until(sub { ! -f "$config_file" }); |
3826 | - Percona::Test::wait_until(sub { ! -f "$tmpdir/services/query-history" }); |
3827 | -}; |
3828 | - |
3829 | -@wait = (); |
3830 | - |
3831 | -$output = output( |
3832 | - sub { |
3833 | - pt_agent::run_agent( |
3834 | - # Required args |
3835 | - agent => $agent, |
3836 | - client => $client, |
3837 | - daemon => $daemon, |
3838 | - interval => $interval, |
3839 | - lib_dir => $tmpdir, |
3840 | - Cxn => $cxn, |
3841 | - # Optional args, for testing |
3842 | - oktorun => $oktorun, |
3843 | - json => $json, |
3844 | - ); |
3845 | - }, |
3846 | - stderr => 1, |
3847 | -); |
3848 | - |
3849 | -is_deeply( |
3850 | - \@wait, |
3851 | - [ 60, 11, 11 ], |
3852 | - "Got Config after error" |
3853 | -) or diag(Dumper(\@wait)); |
3854 | - |
3855 | -ok( |
3856 | - ! -f "$config_file", |
3857 | - "No Config diff, no config file change" |
3858 | -); |
3859 | - |
3860 | -ok( |
3861 | - ! -f "$tmpdir/services/query-history", |
3862 | - "No Service diff, no service file changes" |
3863 | -); |
3864 | - |
3865 | -my $new_crontab = `crontab -l 2>/dev/null`; |
3866 | -is( |
3867 | - $new_crontab, |
3868 | - $crontab, |
3869 | - "Crontab is the same" |
3870 | -); |
3871 | - |
3872 | -# ############################################################################# |
3873 | -# Test a run_once_on_start service |
3874 | -# ############################################################################# |
3875 | - |
3876 | -diag(`rm -f $tmpdir/* >/dev/null 2>&1`); |
3877 | -diag(`rm -rf $tmpdir/services/*`); |
3878 | -diag(`rm -rf $tmpdir/spool/*`); |
3879 | - |
3880 | -# When pt-agent manually runs --run-service test-run-at-start, it's going |
3881 | -# to need an API key because it doesn't call its own run_service(), it runs |
3882 | -# another instance of itself with system(). So put the fake API key in |
3883 | -# the default config file. |
3884 | -unlink $config_file if -f $config_file; |
3885 | -diag(`echo "api-key=123" > $config_file`); |
3886 | - |
3887 | -$config = Percona::WebAPI::Resource::Config->new( |
3888 | - ts => 1363720060, |
3889 | - name => 'Test run_once_on_start', |
3890 | - options => { |
3891 | - 'check-interval' => "15", |
3892 | - 'lib' => $tmpdir, |
3893 | - 'spool' => "$tmpdir/spool", |
3894 | - 'pid' => "$tmpdir/pid", |
3895 | - 'log' => "$tmpdir/log" |
3896 | - }, |
3897 | - links => { |
3898 | - self => '/agents/123/config', |
3899 | - services => '/agents/123/services', |
3900 | - }, |
3901 | -); |
3902 | - |
3903 | -$run0 = Percona::WebAPI::Resource::Task->new( |
3904 | - name => 'run-at-start', |
3905 | - number => '0', |
3906 | - program => 'date', |
3907 | - output => 'spool', |
3908 | -); |
3909 | - |
3910 | -$svc0 = Percona::WebAPI::Resource::Service->new( |
3911 | - ts => 100, |
3912 | - name => 'test-run-at-start', |
3913 | - run_schedule => '0 0 1 1 *', |
3914 | - run_once => 1, # here's the magic |
3915 | - tasks => [ $run0 ], |
3916 | - links => { |
3917 | - self => '/query-history', |
3918 | - data => '/query-history/data', |
3919 | - }, |
3920 | -); |
3921 | - |
3922 | -$ua->{responses}->{get} = [ |
3923 | - { |
3924 | - headers => { 'X-Percona-Resource-Type' => 'Config' }, |
3925 | - content => as_hashref($config, with_links => 1), |
3926 | - }, |
3927 | - { |
3928 | - headers => { 'X-Percona-Resource-Type' => 'Service' }, |
3929 | - content => [ as_hashref($svc0, with_links => 1) ], |
3930 | - }, |
3931 | - { |
3932 | - headers => { 'X-Percona-Resource-Type' => 'Config' }, |
3933 | - content => as_hashref($config, with_links => 1), |
3934 | - }, |
3935 | - { |
3936 | - headers => { 'X-Percona-Resource-Type' => 'Service' }, |
3937 | - content => [ as_hashref($svc0, with_links => 1) ], |
3938 | - }, |
3939 | -]; |
3940 | - |
3941 | -@wait = (); |
3942 | -@ok_code = (); # callbacks |
3943 | -@oktorun = ( |
3944 | - 1, # 1st main loop check |
3945 | - # Run once |
3946 | - 1, # 2nd main loop check |
3947 | - # Don't run it again |
3948 | - 0, # 3d main loop check |
3949 | -); |
3950 | - |
3951 | -$output = output( |
3952 | - sub { |
3953 | - pt_agent::run_agent( |
3954 | - # Required args |
3955 | - agent => $agent, |
3956 | - client => $client, |
3957 | - daemon => $daemon, |
3958 | - interval => $interval, |
3959 | - lib_dir => $tmpdir, |
3960 | - Cxn => $cxn, |
3961 | - # Optional args, for testing |
3962 | - oktorun => $oktorun, |
3963 | - json => $json, |
3964 | - bin_dir => "$trunk/bin/", |
3965 | - ); |
3966 | - }, |
3967 | - stderr => 1, |
3968 | -); |
3969 | - |
3970 | -Percona::Test::wait_for_files("$tmpdir/spool/test-run-at-start/test-run-at-start"); |
3971 | - |
3972 | -like( |
3973 | - $output, |
3974 | - qr/Starting test-run-at-start service/, |
3975 | - "Ran service on start" |
3976 | -); |
3977 | - |
3978 | -my @runs = $output =~ m/Starting test-run-at-start service/g; |
3979 | - |
3980 | -is( |
3981 | - scalar @runs, |
3982 | - 1, |
3983 | - "... only ran it once" |
3984 | -); |
3985 | - |
3986 | -chomp($output = `cat $tmpdir/spool/test-run-at-start/test-run-at-start 2>/dev/null`); |
3987 | -ok( |
3988 | - $output, |
3989 | - "... service ran at start" |
3990 | -) or diag($output); |
3991 | - |
3992 | -chomp($output = `crontab -l`); |
3993 | -unlike( |
3994 | - $output, |
3995 | - qr/--run-service test-run-at-start/, |
3996 | - "... service was not scheduled" |
3997 | -); |
3998 | - |
3999 | -# ############################################################################# |
4000 | -# Done. |
4001 | -# ############################################################################# |
4002 | - |
4003 | -# This shouldn't cause an error, but if it does, let it show up |
4004 | -# in the results as an error. |
4005 | -`crontab -r`; |
4006 | - |
4007 | -if ( -f $config_file ) { |
4008 | - unlink $config_file |
4009 | - or warn "Error removing $config_file: $OS_ERROR"; |
4010 | -} |
4011 | - |
4012 | -done_testing; |
4013 | |
4014 | === removed file 't/pt-agent/run_service.t' |
4015 | --- t/pt-agent/run_service.t 2013-06-17 00:28:18 +0000 |
4016 | +++ t/pt-agent/run_service.t 1970-01-01 00:00:00 +0000 |
4017 | @@ -1,503 +0,0 @@ |
4018 | -#!/usr/bin/env perl |
4019 | - |
4020 | -BEGIN { |
4021 | - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" |
4022 | - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; |
4023 | - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; |
4024 | -}; |
4025 | - |
4026 | -use strict; |
4027 | -use warnings FATAL => 'all'; |
4028 | -use English qw(-no_match_vars); |
4029 | -use Test::More; |
4030 | -use JSON; |
4031 | -use File::Temp qw(tempdir); |
4032 | - |
4033 | -$ENV{PTTEST_PRETTY_JSON} = 1; |
4034 | - |
4035 | -use Percona::Test; |
4036 | -use Sandbox; |
4037 | -use Percona::Test::Mock::UserAgent; |
4038 | -use Percona::Test::Mock::AgentLogger; |
4039 | -require "$trunk/bin/pt-agent"; |
4040 | - |
4041 | -my $dp = new DSNParser(opts=>$dsn_opts); |
4042 | -my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); |
4043 | -my $dbh = $sb->get_dbh_for('master'); |
4044 | -my $dsn = $sb->dsn_for('master'); |
4045 | -my $o = new OptionParser(); |
4046 | -$o->get_specs("$trunk/bin/pt-agent"); |
4047 | -$o->get_opts(); |
4048 | - |
4049 | -Percona::Toolkit->import(qw(Dumper have_required_args)); |
4050 | -Percona::WebAPI::Representation->import(qw(as_hashref)); |
4051 | - |
4052 | -my @log; |
4053 | -my $logger = Percona::Test::Mock::AgentLogger->new(log => \@log); |
4054 | -pt_agent::_logger($logger); |
4055 | - |
4056 | -my $sample = "t/pt-agent/samples"; |
4057 | - |
4058 | -# Create fake spool and lib dirs. Service-related subs in pt-agent |
4059 | -# automatically add "/services" to the lib dir, but the spool dir is |
4060 | -# used as-is. |
4061 | -my $tmpdir = tempdir("/tmp/pt-agent.$PID.XXXXXX", CLEANUP => 1); |
4062 | -output( |
4063 | - sub { pt_agent::init_lib_dir(lib_dir => $tmpdir) } |
4064 | -); |
4065 | -my $spool_dir = "$tmpdir/spool"; |
4066 | - |
4067 | -sub write_svc_files { |
4068 | - my (%args) = @_; |
4069 | - have_required_args(\%args, qw( |
4070 | - services |
4071 | - )) or die; |
4072 | - my $services = $args{services}; |
4073 | - |
4074 | - my $output = output( |
4075 | - sub { |
4076 | - pt_agent::write_services( |
4077 | - sorted_services => { added => $services }, |
4078 | - lib_dir => $tmpdir, |
4079 | - ); |
4080 | - }, |
4081 | - stderr => 1, |
4082 | - die => 1, |
4083 | - ); |
4084 | -} |
4085 | - |
4086 | -# ############################################################################# |
4087 | -# Create mock client and Agent |
4088 | -# ############################################################################# |
4089 | - |
4090 | -my $json = JSON->new->canonical([1])->pretty; |
4091 | -$json->allow_blessed([]); |
4092 | -$json->convert_blessed([]); |
4093 | - |
4094 | -my $ua = Percona::Test::Mock::UserAgent->new( |
4095 | - encode => sub { my $c = shift; return $json->encode($c || {}) }, |
4096 | -); |
4097 | - |
4098 | -# Create cilent, get entry links |
4099 | -my $links = { |
4100 | - agents => '/agents', |
4101 | - config => '/agents/1/config', |
4102 | - services => '/agents/1/services', |
4103 | - 'query-history' => '/query-history', |
4104 | -}; |
4105 | - |
4106 | -$ua->{responses}->{get} = [ |
4107 | - { |
4108 | - content => $links, |
4109 | - }, |
4110 | -]; |
4111 | - |
4112 | -my $client = eval { |
4113 | - Percona::WebAPI::Client->new( |
4114 | - api_key => '123', |
4115 | - ua => $ua, |
4116 | - ); |
4117 | -}; |
4118 | -is( |
4119 | - $EVAL_ERROR, |
4120 | - '', |
4121 | - 'Create mock client' |
4122 | -) or die; |
4123 | - |
4124 | -my $agent = Percona::WebAPI::Resource::Agent->new( |
4125 | - uuid => '123', |
4126 | - hostname => 'prod1', |
4127 | - links => $links, |
4128 | -); |
4129 | - |
4130 | -is_deeply( |
4131 | - as_hashref($agent), |
4132 | - { |
4133 | - uuid => '123', |
4134 | - hostname => 'prod1', |
4135 | - }, |
4136 | - 'Create mock Agent' |
4137 | -) or die; |
4138 | - |
4139 | -# ############################################################################# |
4140 | -# Simple single task service using a program. |
4141 | -# ############################################################################# |
4142 | - |
4143 | -my $run0 = Percona::WebAPI::Resource::Task->new( |
4144 | - name => 'query-history', |
4145 | - number => '0', |
4146 | - program => "__BIN_DIR__/pt-query-digest --output json $trunk/t/lib/samples/slowlogs/slow008.txt", |
4147 | - output => 'spool', |
4148 | -); |
4149 | - |
4150 | -my $svc0 = Percona::WebAPI::Resource::Service->new( |
4151 | - ts => 100, |
4152 | - name => 'query-history', |
4153 | - run_schedule => '1 * * * *', |
4154 | - spool_schedule => '2 * * * *', |
4155 | - tasks => [ $run0 ], |
4156 | -); |
4157 | - |
4158 | -write_svc_files( |
4159 | - services => [ $svc0 ], |
4160 | -); |
4161 | - |
4162 | -$ua->{responses}->{get} = [ |
4163 | - { |
4164 | - headers => { 'X-Percona-Resource-Type' => 'Agent' }, |
4165 | - content => as_hashref($agent, with_links => 1), |
4166 | - }, |
4167 | -]; |
4168 | - |
4169 | -my $exit_status; |
4170 | -my $output = output( |
4171 | - sub { |
4172 | - $exit_status = pt_agent::run_service( |
4173 | - api_key => '123', |
4174 | - service => 'query-history', |
4175 | - lib_dir => $tmpdir, |
4176 | - spool_dir => $spool_dir, |
4177 | - Cxn => '', |
4178 | - # for testing: |
4179 | - client => $client, |
4180 | - agent => $agent, |
4181 | - entry_links => $links, |
4182 | - prefix => '1', |
4183 | - json => $json, |
4184 | - bin_dir => "$trunk/bin", |
4185 | - ); |
4186 | - }, |
4187 | -); |
4188 | - |
4189 | -ok( |
4190 | - no_diff( |
4191 | - "cat $tmpdir/spool/query-history/1.query-history.data", |
4192 | - "$sample/query-history/data001.json", |
4193 | - post_pipe => 'grep -v \'"name" :\'', |
4194 | - ), |
4195 | - "1 run: spool data (query-history/data001.json)" |
4196 | -) or diag( |
4197 | - `ls -l $tmpdir/spool/query-history/`, |
4198 | - `cat $tmpdir/logs/query-history.run`, |
4199 | - Dumper(\@log) |
4200 | -); |
4201 | - |
4202 | -chomp(my $n_files = `ls -1 $spool_dir/query-history/*.data | wc -l | awk '{print \$1}'`); |
4203 | -is( |
4204 | - $n_files, |
4205 | - 1, |
4206 | - "1 run: only wrote spool data" |
4207 | -) or diag(`ls -l $spool_dir`); |
4208 | - |
4209 | -is( |
4210 | - $exit_status, |
4211 | - 0, |
4212 | - "1 run: exit 0" |
4213 | -); |
4214 | - |
4215 | -ok( |
4216 | - -f "$tmpdir/spool/query-history/1.query-history.meta", |
4217 | - "1 run: .meta file exists" |
4218 | -); |
4219 | - |
4220 | -# ############################################################################# |
4221 | -# Service with two task, both using a program. |
4222 | -# ############################################################################# |
4223 | - |
4224 | -diag(`rm -rf $tmpdir/spool/* $tmpdir/services/*`); |
4225 | -@log = (); |
4226 | - |
4227 | -# The result is the same as the previous single-run test, but instead of |
4228 | -# having pqd read the slowlog directly, we have the first run cat the |
4229 | -# log to a tmp file which pt-agent should auto-create. Then pqd in run1 |
4230 | -# references this tmp file. |
4231 | - |
4232 | -$run0 = Percona::WebAPI::Resource::Task->new( |
4233 | - name => 'cat-slow-log', |
4234 | - number => '0', |
4235 | - program => "cat $trunk/t/lib/samples/slowlogs/slow008.txt", |
4236 | - output => 'tmp', |
4237 | -); |
4238 | - |
4239 | -my $run1 = Percona::WebAPI::Resource::Task->new( |
4240 | - name => 'query-history', |
4241 | - number => '1', |
4242 | - program => "__BIN_DIR__/pt-query-digest --output json __RUN_0_OUTPUT__", |
4243 | - output => 'spool', |
4244 | -); |
4245 | - |
4246 | -$svc0 = Percona::WebAPI::Resource::Service->new( |
4247 | - ts => 100, |
4248 | - name => 'query-history', |
4249 | - run_schedule => '3 * * * *', |
4250 | - spool_schedule => '4 * * * *', |
4251 | - tasks => [ $run0, $run1 ], |
4252 | -); |
4253 | - |
4254 | -write_svc_files( |
4255 | - services => [ $svc0 ], |
4256 | -); |
4257 | - |
4258 | -$ua->{responses}->{get} = [ |
4259 | - { |
4260 | - headers => { 'X-Percona-Resource-Type' => 'Agent' }, |
4261 | - content => as_hashref($agent, with_links => 1), |
4262 | - }, |
4263 | -]; |
4264 | - |
4265 | -$output = output( |
4266 | - sub { |
4267 | - $exit_status = pt_agent::run_service( |
4268 | - api_key => '123', |
4269 | - service => 'query-history', |
4270 | - spool_dir => $spool_dir, |
4271 | - lib_dir => $tmpdir, |
4272 | - Cxn => '', |
4273 | - # for testing: |
4274 | - client => $client, |
4275 | - agent => $agent, |
4276 | - entry_links => $links, |
4277 | - prefix => '2', |
4278 | - json => $json, |
4279 | - bin_dir => "$trunk/bin", |
4280 | - ); |
4281 | - }, |
4282 | -); |
4283 | - |
4284 | -ok( |
4285 | - no_diff( |
4286 | - "cat $tmpdir/spool/query-history/2.query-history.data", |
4287 | - "$sample/query-history/data001.json", |
4288 | - post_pipe => 'grep -v \'"name" :\'', |
4289 | - ), |
4290 | - "2 runs: spool data (query-history/data001.json)" |
4291 | -) or diag( |
4292 | - `ls -l $tmpdir/spool/query-history/`, |
4293 | - `cat $tmpdir/logs/query-history.run`, |
4294 | - Dumper(\@log) |
4295 | -); |
4296 | - |
4297 | -chomp($n_files = `ls -1 $spool_dir/query-history/*.data | wc -l | awk '{print \$1}'`); |
4298 | -is( |
4299 | - $n_files, |
4300 | - 1, |
4301 | - "2 runs: only wrote spool data" |
4302 | -) or diag(`ls -l $spool_dir`); |
4303 | - |
4304 | -is( |
4305 | - $exit_status, |
4306 | - 0, |
4307 | - "2 runs: exit 0" |
4308 | -); |
4309 | - |
4310 | -my @tmp_files = glob "$tmpdir/spool/.tmp/*"; |
4311 | -is_deeply( |
4312 | - \@tmp_files, |
4313 | - [], |
4314 | - "2 runs: temp file removed" |
4315 | -); |
4316 | - |
4317 | -# ############################################################################# |
4318 | -# More realistc: 3 services, multiple tasks, using programs and queries. |
4319 | -# ############################################################################# |
4320 | - |
4321 | -SKIP: { |
4322 | - skip 'Cannot connect to sandbox master', 5 unless $dbh; |
4323 | - skip 'No HOME environment variable', 5 unless $ENV{HOME}; |
4324 | - |
4325 | - diag(`rm -rf $tmpdir/spool/* $tmpdir/services/*`); |
4326 | - @log = (); |
4327 | - |
4328 | - my (undef, $old_genlog) = $dbh->selectrow_array("SHOW VARIABLES LIKE 'general_log_file'"); |
4329 | - |
4330 | - my $new_genlog = "$tmpdir/genlog"; |
4331 | - |
4332 | - # First service: set up |
4333 | - my $task00 = Percona::WebAPI::Resource::Task->new( |
4334 | - name => 'disable-gen-log', |
4335 | - number => '0', |
4336 | - query => "SET GLOBAL general_log=OFF", |
4337 | - ); |
4338 | - my $task01 = Percona::WebAPI::Resource::Task->new( |
4339 | - name => 'set-gen-log-file', |
4340 | - number => '1', |
4341 | - query => "SET GLOBAL general_log_file='$new_genlog'", |
4342 | - ); |
4343 | - my $task02 = Percona::WebAPI::Resource::Task->new( |
4344 | - name => 'enable-gen-log', |
4345 | - number => '2', |
4346 | - query => "SET GLOBAL general_log=ON", |
4347 | - ); |
4348 | - my $svc0 = Percona::WebAPI::Resource::Service->new( |
4349 | - ts => 100, |
4350 | - name => 'enable-gen-log', |
4351 | - run_schedule => '1 * * * *', |
4352 | - spool_schedule => '2 * * * *', |
4353 | - tasks => [ $task00, $task01, $task02 ], |
4354 | - ); |
4355 | - |
4356 | - # Second service: the actual service |
4357 | - my $task10 = Percona::WebAPI::Resource::Task->new( |
4358 | - name => 'query-history', |
4359 | - number => '1', |
4360 | - program => "$trunk/bin/pt-query-digest --output json --type genlog $new_genlog", |
4361 | - output => 'spool', |
4362 | - ); |
4363 | - my $svc1 = Percona::WebAPI::Resource::Service->new( |
4364 | - ts => 100, |
4365 | - name => 'query-history', |
4366 | - run_schedule => '3 * * * *', |
4367 | - spool_schedule => '4 * * * *', |
4368 | - tasks => [ $task10 ], |
4369 | - ); |
4370 | - |
4371 | - # Third service: tear down |
4372 | - my $task20 = Percona::WebAPI::Resource::Task->new( |
4373 | - name => 'disable-gen-log', |
4374 | - number => '0', |
4375 | - query => "SET GLOBAL general_log=OFF", |
4376 | - ); |
4377 | - my $task21 = Percona::WebAPI::Resource::Task->new( |
4378 | - name => 'set-gen-log-file', |
4379 | - number => '1', |
4380 | - query => "SET GLOBAL general_log_file='$old_genlog'", |
4381 | - ); |
4382 | - my $task22 = Percona::WebAPI::Resource::Task->new( |
4383 | - name => 'enable-gen-log', |
4384 | - number => '2', |
4385 | - query => "SET GLOBAL general_log=ON", |
4386 | - ); |
4387 | - my $svc2 = Percona::WebAPI::Resource::Service->new( |
4388 | - ts => 100, |
4389 | - name => 'disable-gen-log', |
4390 | - run_schedule => '5 * * * *', |
4391 | - spool_schedule => '6 * * * *', |
4392 | - tasks => [ $task20, $task21, $task22 ], |
4393 | - ); |
4394 | - |
4395 | - write_svc_files( |
4396 | - services => [ $svc0, $svc1, $svc2 ], |
4397 | - ); |
4398 | - |
4399 | - $ua->{responses}->{get} = [ |
4400 | - { |
4401 | - headers => { 'X-Percona-Resource-Type' => 'Agent' }, |
4402 | - content => as_hashref($agent, with_links => 1), |
4403 | - }, |
4404 | - { |
4405 | - headers => { 'X-Percona-Resource-Type' => 'Agent' }, |
4406 | - content => as_hashref($agent, with_links => 1), |
4407 | - }, |
4408 | - { |
4409 | - headers => { 'X-Percona-Resource-Type' => 'Agent' }, |
4410 | - content => as_hashref($agent, with_links => 1), |
4411 | - }, |
4412 | - ]; |
4413 | - |
4414 | - my $cxn = Cxn->new( |
4415 | - dsn_string => $dsn, |
4416 | - OptionParser => $o, |
4417 | - DSNParser => $dp, |
4418 | - ); |
4419 | - |
4420 | - # Run the first service. |
4421 | - $output = output( |
4422 | - sub { |
4423 | - $exit_status = pt_agent::run_service( |
4424 | - api_key => '123', |
4425 | - service => 'enable-gen-log', |
4426 | - spool_dir => $spool_dir, |
4427 | - lib_dir => $tmpdir, |
4428 | - Cxn => $cxn, |
4429 | - # for testing: |
4430 | - client => $client, |
4431 | - agent => $agent, |
4432 | - entry_links => $links, |
4433 | - prefix => '3', |
4434 | - json => $json, |
4435 | - bin_dir => "$trunk/bin", |
4436 | - ); |
4437 | - }, |
4438 | - ); |
4439 | - |
4440 | - my (undef, $genlog) = $dbh->selectrow_array( |
4441 | - "SHOW VARIABLES LIKE 'general_log_file'"); |
4442 | - is( |
4443 | - $genlog, |
4444 | - $new_genlog, |
4445 | - "Task set MySQL var" |
4446 | - ) or diag($output); |
4447 | - |
4448 | - # Pretend some time passes... |
4449 | - |
4450 | - # The next service doesn't need MySQL, so it shouldn't connect to it. |
4451 | - # To check this, the genlog before running and after running should |
4452 | - # be identical. |
4453 | - `cp $new_genlog $tmpdir/genlog-before`; |
4454 | - |
4455 | - # Run the second service. |
4456 | - $output = output( |
4457 | - sub { |
4458 | - $exit_status = pt_agent::run_service( |
4459 | - api_key => '123', |
4460 | - service => 'query-history', |
4461 | - spool_dir => $spool_dir, |
4462 | - lib_dir => $tmpdir, |
4463 | - Cxn => $cxn, |
4464 | - # for testing: |
4465 | - client => $client, |
4466 | - agent => $agent, |
4467 | - entry_links => $links, |
4468 | - prefix => '4', |
4469 | - json => $json, |
4470 | - bin_dir => "$trunk/bin", |
4471 | - ); |
4472 | - }, |
4473 | - ); |
4474 | - |
4475 | - `cp $new_genlog $tmpdir/genlog-after`; |
4476 | - my $diff = `diff $tmpdir/genlog-before $tmpdir/genlog-after`; |
4477 | - is( |
4478 | - $diff, |
4479 | - '', |
4480 | - "Tasks didn't need MySQL, didn't connect to MySQL" |
4481 | - ) or diag($output); |
4482 | - |
4483 | - # Pretend more time passes... |
4484 | - |
4485 | - # Run the third service. |
4486 | - $output = output( |
4487 | - sub { |
4488 | - $exit_status = pt_agent::run_service( |
4489 | - api_key => '123', |
4490 | - service => 'disable-gen-log', |
4491 | - spool_dir => $spool_dir, |
4492 | - lib_dir => $tmpdir, |
4493 | - Cxn => $cxn, |
4494 | - # for testing: |
4495 | - client => $client, |
4496 | - agent => $agent, |
4497 | - entry_links => $links, |
4498 | - prefix => '5', |
4499 | - json => $json, |
4500 | - bin_dir => "$trunk/bin", |
4501 | - ); |
4502 | - }, |
4503 | - ); |
4504 | - |
4505 | - (undef, $genlog) = $dbh->selectrow_array( |
4506 | - "SHOW VARIABLES LIKE 'general_log_file'"); |
4507 | - is( |
4508 | - $genlog, |
4509 | - $old_genlog, |
4510 | - "Task restored MySQL var" |
4511 | - ) or diag($output); |
4512 | - |
4513 | - $dbh->do("SET GLOBAL general_log=ON"); |
4514 | - $dbh->do("SET GLOBAL general_log_file='$old_genlog'"); |
4515 | -} |
4516 | - |
4517 | -# ############################################################################# |
4518 | -# Done. |
4519 | -# ############################################################################# |
4520 | -done_testing; |
4521 | |
4522 | === removed directory 't/pt-agent/samples' |
4523 | === removed file 't/pt-agent/samples/crontab001.in' |
4524 | === removed file 't/pt-agent/samples/crontab001.out' |
4525 | --- t/pt-agent/samples/crontab001.out 2013-03-19 22:35:37 +0000 |
4526 | +++ t/pt-agent/samples/crontab001.out 1970-01-01 00:00:00 +0000 |
4527 | @@ -1,2 +0,0 @@ |
4528 | -* 8 * * 1,2,3,4,5 pt-agent --run-service query-history |
4529 | -* 9 * * 1,2,3,4,5 pt-agent --send-data query-history |
4530 | |
4531 | === removed file 't/pt-agent/samples/crontab002.in' |
4532 | --- t/pt-agent/samples/crontab002.in 2013-01-08 17:55:58 +0000 |
4533 | +++ t/pt-agent/samples/crontab002.in 1970-01-01 00:00:00 +0000 |
4534 | @@ -1,1 +0,0 @@ |
4535 | -17 3 * * 1 cmd |
4536 | |
4537 | === removed file 't/pt-agent/samples/crontab002.out' |
4538 | --- t/pt-agent/samples/crontab002.out 2013-03-19 22:35:37 +0000 |
4539 | +++ t/pt-agent/samples/crontab002.out 1970-01-01 00:00:00 +0000 |
4540 | @@ -1,3 +0,0 @@ |
4541 | -17 3 * * 1 cmd |
4542 | -* 8 * * 1,2,3,4,5 pt-agent --run-service query-history |
4543 | -* 9 * * 1,2,3,4,5 pt-agent --send-data query-history |
4544 | |
4545 | === removed file 't/pt-agent/samples/crontab003.in' |
4546 | --- t/pt-agent/samples/crontab003.in 2013-01-08 17:55:58 +0000 |
4547 | +++ t/pt-agent/samples/crontab003.in 1970-01-01 00:00:00 +0000 |
4548 | @@ -1,3 +0,0 @@ |
4549 | -17 3 * * 1 cmd |
4550 | -* * * * 1 pt-agent --run-service old-service |
4551 | - |
4552 | |
4553 | === removed file 't/pt-agent/samples/crontab003.out' |
4554 | --- t/pt-agent/samples/crontab003.out 2013-03-19 22:35:37 +0000 |
4555 | +++ t/pt-agent/samples/crontab003.out 1970-01-01 00:00:00 +0000 |
4556 | @@ -1,3 +0,0 @@ |
4557 | -17 3 * * 1 cmd |
4558 | -* 8 * * 1,2,3,4,5 pt-agent --run-service query-history |
4559 | -* 9 * * 1,2,3,4,5 pt-agent --send-data query-history |
4560 | |
4561 | === removed file 't/pt-agent/samples/crontab004.in' |
4562 | --- t/pt-agent/samples/crontab004.in 2013-01-30 20:25:21 +0000 |
4563 | +++ t/pt-agent/samples/crontab004.in 1970-01-01 00:00:00 +0000 |
4564 | @@ -1,2 +0,0 @@ |
4565 | -1 * * * * pt-agent --run-service foo |
4566 | -2 * * * * pt-agent --send-data foo |
4567 | |
4568 | === removed file 't/pt-agent/samples/crontab004.out' |
4569 | --- t/pt-agent/samples/crontab004.out 2013-03-19 22:35:37 +0000 |
4570 | +++ t/pt-agent/samples/crontab004.out 1970-01-01 00:00:00 +0000 |
4571 | @@ -1,2 +0,0 @@ |
4572 | -* 8 * * 1,2,3,4,5 pt-agent --run-service query-history |
4573 | -* 9 * * 1,2,3,4,5 pt-agent --send-data query-history |
4574 | |
4575 | === removed directory 't/pt-agent/samples/query-history' |
4576 | === removed file 't/pt-agent/samples/query-history/data001.json' |
4577 | --- t/pt-agent/samples/query-history/data001.json 2013-11-08 03:03:01 +0000 |
4578 | +++ t/pt-agent/samples/query-history/data001.json 1970-01-01 00:00:00 +0000 |
4579 | @@ -1,152 +0,0 @@ |
4580 | - |
4581 | -{ |
4582 | - "classes" : [ |
4583 | - { |
4584 | - "attribute" : "fingerprint", |
4585 | - "checksum" : "C72BF45D68E35A6E", |
4586 | - "distillate" : "SELECT tbl", |
4587 | - "example" : { |
4588 | - "Query_time" : "0.018799", |
4589 | - "query" : "SELECT MIN(id),MAX(id) FROM tbl", |
4590 | - "ts" : null |
4591 | - }, |
4592 | - "fingerprint" : "select min(id),max(id) from tbl", |
4593 | - "histograms" : { |
4594 | - "Query_time" : [ |
4595 | - 0, |
4596 | - 0, |
4597 | - 0, |
4598 | - 0, |
4599 | - 1, |
4600 | - 0, |
4601 | - 0, |
4602 | - 0 |
4603 | - ] |
4604 | - }, |
4605 | - "metrics" : { |
4606 | - "Lock_time" : { |
4607 | - "avg" : "0.009453", |
4608 | - "max" : "0.009453", |
4609 | - "median" : "0.009453", |
4610 | - "min" : "0.009453", |
4611 | - "pct" : "0.333333", |
4612 | - "pct_95" : "0.009453", |
4613 | - "stddev" : "0.000000", |
4614 | - "sum" : "0.009453" |
4615 | - }, |
4616 | - "Query_length" : { |
4617 | - "avg" : "31", |
4618 | - "max" : "31", |
4619 | - "median" : "31", |
4620 | - "min" : "31", |
4621 | - "pct" : "0", |
4622 | - "pct_95" : "31", |
4623 | - "stddev" : "0", |
4624 | - "sum" : "31" |
4625 | - }, |
4626 | - "Query_time" : { |
4627 | - "avg" : "0.018799", |
4628 | - "max" : "0.018799", |
4629 | - "median" : "0.018799", |
4630 | - "min" : "0.018799", |
4631 | - "pct" : "0.333333", |
4632 | - "pct_95" : "0.018799", |
4633 | - "stddev" : "0.000000", |
4634 | - "sum" : "0.018799" |
4635 | - }, |
4636 | - "Rows_examined" : { |
4637 | - "avg" : "0", |
4638 | - "max" : "0", |
4639 | - "median" : "0", |
4640 | - "min" : "0", |
4641 | - "pct" : "0", |
4642 | - "pct_95" : "0", |
4643 | - "stddev" : "0", |
4644 | - "sum" : "0" |
4645 | - }, |
4646 | - "Rows_sent" : { |
4647 | - "avg" : "0", |
4648 | - "max" : "0", |
4649 | - "median" : "0", |
4650 | - "min" : "0", |
4651 | - "pct" : "0", |
4652 | - "pct_95" : "0", |
4653 | - "stddev" : "0", |
4654 | - "sum" : "0" |
4655 | - }, |
4656 | - "db" : { |
4657 | - "value" : "db2" |
4658 | - }, |
4659 | - "host" : { |
4660 | - "value" : "" |
4661 | - }, |
4662 | - "user" : { |
4663 | - "value" : "meow" |
4664 | - } |
4665 | - }, |
4666 | - "query_count" : 1, |
4667 | - "tables" : [ |
4668 | - { |
4669 | - "create" : "SHOW CREATE TABLE `db2`.`tbl`\\G", |
4670 | - "status" : "SHOW TABLE STATUS FROM `db2` LIKE 'tbl'\\G" |
4671 | - } |
4672 | - ] |
4673 | - } |
4674 | - ], |
4675 | - "global" : { |
4676 | - "files" : [ |
4677 | - { |
4678 | - "size" : 656 |
4679 | - } |
4680 | - ], |
4681 | - "metrics" : { |
4682 | - "Lock_time" : { |
4683 | - "avg" : "0.003151", |
4684 | - "max" : "0.009453", |
4685 | - "median" : "0.000000", |
4686 | - "min" : "0.000000", |
4687 | - "pct_95" : "0.009171", |
4688 | - "stddev" : "0.004323", |
4689 | - "sum" : "0.009453" |
4690 | - }, |
4691 | - "Query_length" : { |
4692 | - "avg" : "24", |
4693 | - "max" : "31", |
4694 | - "median" : "26", |
4695 | - "min" : "14", |
4696 | - "pct_95" : "30", |
4697 | - "stddev" : "6", |
4698 | - "sum" : "72" |
4699 | - }, |
4700 | - "Query_time" : { |
4701 | - "avg" : "0.006567", |
4702 | - "max" : "0.018799", |
4703 | - "median" : "0.000882", |
4704 | - "min" : "0.000002", |
4705 | - "pct_95" : "0.018157", |
4706 | - "stddev" : "0.008359", |
4707 | - "sum" : "0.019700" |
4708 | - }, |
4709 | - "Rows_examined" : { |
4710 | - "avg" : "0", |
4711 | - "max" : "0", |
4712 | - "median" : "0", |
4713 | - "min" : "0", |
4714 | - "pct_95" : "0", |
4715 | - "stddev" : "0", |
4716 | - "sum" : "0" |
4717 | - }, |
4718 | - "Rows_sent" : { |
4719 | - "avg" : "0", |
4720 | - "max" : "0", |
4721 | - "median" : "0", |
4722 | - "min" : "0", |
4723 | - "pct_95" : "0", |
4724 | - "stddev" : "0", |
4725 | - "sum" : "0" |
4726 | - } |
4727 | - }, |
4728 | - "query_count" : 3, |
4729 | - "unique_query_count" : 3 |
4730 | - } |
4731 | -} |
4732 | |
4733 | === removed file 't/pt-agent/samples/query-history/data001.send' |
4734 | --- t/pt-agent/samples/query-history/data001.send 2013-11-08 03:03:01 +0000 |
4735 | +++ t/pt-agent/samples/query-history/data001.send 1970-01-01 00:00:00 +0000 |
4736 | @@ -1,166 +0,0 @@ |
4737 | ---Ym91bmRhcnk |
4738 | -Content-Disposition: form-data; name="agent" |
4739 | - |
4740 | -{ |
4741 | - "hostname" : "prod1", |
4742 | - "uuid" : "123" |
4743 | -} |
4744 | ---Ym91bmRhcnk |
4745 | -Content-Disposition: form-data; name="meta" |
4746 | - |
4747 | - |
4748 | ---Ym91bmRhcnk |
4749 | -Content-Disposition: form-data; name="data" |
4750 | - |
4751 | -{ |
4752 | - "classes" : [ |
4753 | - { |
4754 | - "attribute" : "fingerprint", |
4755 | - "checksum" : "C72BF45D68E35A6E", |
4756 | - "distillate" : "SELECT tbl", |
4757 | - "example" : { |
4758 | - "Query_time" : "0.018799", |
4759 | - "query" : "SELECT MIN(id),MAX(id) FROM tbl", |
4760 | - "ts" : null |
4761 | - }, |
4762 | - "fingerprint" : "select min(id),max(id) from tbl", |
4763 | - "histograms" : { |
4764 | - "Query_time" : [ |
4765 | - 0, |
4766 | - 0, |
4767 | - 0, |
4768 | - 0, |
4769 | - 1, |
4770 | - 0, |
4771 | - 0, |
4772 | - 0 |
4773 | - ] |
4774 | - }, |
4775 | - "metrics" : { |
4776 | - "Lock_time" : { |
4777 | - "avg" : "0.009453", |
4778 | - "max" : "0.009453", |
4779 | - "median" : "0.009453", |
4780 | - "min" : "0.009453", |
4781 | - "pct" : "0.333333", |
4782 | - "pct_95" : "0.009453", |
4783 | - "stddev" : "0.000000", |
4784 | - "sum" : "0.009453" |
4785 | - }, |
4786 | - "Query_length" : { |
4787 | - "avg" : "31", |
4788 | - "max" : "31", |
4789 | - "median" : "31", |
4790 | - "min" : "31", |
4791 | - "pct" : "0", |
4792 | - "pct_95" : "31", |
4793 | - "stddev" : "0", |
4794 | - "sum" : "31" |
4795 | - }, |
4796 | - "Query_time" : { |
4797 | - "avg" : "0.018799", |
4798 | - "max" : "0.018799", |
4799 | - "median" : "0.018799", |
4800 | - "min" : "0.018799", |
4801 | - "pct" : "0.333333", |
4802 | - "pct_95" : "0.018799", |
4803 | - "stddev" : "0.000000", |
4804 | - "sum" : "0.018799" |
4805 | - }, |
4806 | - "Rows_examined" : { |
4807 | - "avg" : "0", |
4808 | - "max" : "0", |
4809 | - "median" : "0", |
4810 | - "min" : "0", |
4811 | - "pct" : "0", |
4812 | - "pct_95" : "0", |
4813 | - "stddev" : "0", |
4814 | - "sum" : "0" |
4815 | - }, |
4816 | - "Rows_sent" : { |
4817 | - "avg" : "0", |
4818 | - "max" : "0", |
4819 | - "median" : "0", |
4820 | - "min" : "0", |
4821 | - "pct" : "0", |
4822 | - "pct_95" : "0", |
4823 | - "stddev" : "0", |
4824 | - "sum" : "0" |
4825 | - }, |
4826 | - "db" : { |
4827 | - "value" : "db2" |
4828 | - }, |
4829 | - "host" : { |
4830 | - "value" : "" |
4831 | - }, |
4832 | - "user" : { |
4833 | - "value" : "meow" |
4834 | - } |
4835 | - }, |
4836 | - "query_count" : 1, |
4837 | - "tables" : [ |
4838 | - { |
4839 | - "create" : "SHOW CREATE TABLE `db2`.`tbl`\\G", |
4840 | - "status" : "SHOW TABLE STATUS FROM `db2` LIKE 'tbl'\\G" |
4841 | - } |
4842 | - ] |
4843 | - } |
4844 | - ], |
4845 | - "global" : { |
4846 | - "files" : [ |
4847 | - { |
4848 | - "size" : 656 |
4849 | - } |
4850 | - ], |
4851 | - "metrics" : { |
4852 | - "Lock_time" : { |
4853 | - "avg" : "0.003151", |
4854 | - "max" : "0.009453", |
4855 | - "median" : "0.000000", |
4856 | - "min" : "0.000000", |
4857 | - "pct_95" : "0.009171", |
4858 | - "stddev" : "0.004323", |
4859 | - "sum" : "0.009453" |
4860 | - }, |
4861 | - "Query_length" : { |
4862 | - "avg" : "24", |
4863 | - "max" : "31", |
4864 | - "median" : "26", |
4865 | - "min" : "14", |
4866 | - "pct_95" : "30", |
4867 | - "stddev" : "6", |
4868 | - "sum" : "72" |
4869 | - }, |
4870 | - "Query_time" : { |
4871 | - "avg" : "0.006567", |
4872 | - "max" : "0.018799", |
4873 | - "median" : "0.000882", |
4874 | - "min" : "0.000002", |
4875 | - "pct_95" : "0.018157", |
4876 | - "stddev" : "0.008359", |
4877 | - "sum" : "0.019700" |
4878 | - }, |
4879 | - "Rows_examined" : { |
4880 | - "avg" : "0", |
4881 | - "max" : "0", |
4882 | - "median" : "0", |
4883 | - "min" : "0", |
4884 | - "pct_95" : "0", |
4885 | - "stddev" : "0", |
4886 | - "sum" : "0" |
4887 | - }, |
4888 | - "Rows_sent" : { |
4889 | - "avg" : "0", |
4890 | - "max" : "0", |
4891 | - "median" : "0", |
4892 | - "min" : "0", |
4893 | - "pct_95" : "0", |
4894 | - "stddev" : "0", |
4895 | - "sum" : "0" |
4896 | - } |
4897 | - }, |
4898 | - "query_count" : 3, |
4899 | - "unique_query_count" : 3 |
4900 | - } |
4901 | -} |
4902 | ---Ym91bmRhcnk |
4903 | |
4904 | === removed file 't/pt-agent/samples/service001' |
4905 | --- t/pt-agent/samples/service001 2013-06-17 04:01:30 +0000 |
4906 | +++ t/pt-agent/samples/service001 1970-01-01 00:00:00 +0000 |
4907 | @@ -1,19 +0,0 @@ |
4908 | -{ |
4909 | - "links" : { |
4910 | - "data" : "/query-history/data", |
4911 | - "self" : "/query-history" |
4912 | - }, |
4913 | - "name" : "query-history", |
4914 | - "run_schedule" : "1 * * * *", |
4915 | - "spool_schedule" : "2 * * * *", |
4916 | - "tasks" : [ |
4917 | - { |
4918 | - "name" : "query-history", |
4919 | - "number" : "0", |
4920 | - "options" : "--output json", |
4921 | - "output" : "spool", |
4922 | - "program" : "pt-query-digest" |
4923 | - } |
4924 | - ], |
4925 | - "ts" : 100 |
4926 | -} |
4927 | |
4928 | === removed file 't/pt-agent/samples/write_services001' |
4929 | --- t/pt-agent/samples/write_services001 2013-06-17 00:28:18 +0000 |
4930 | +++ t/pt-agent/samples/write_services001 1970-01-01 00:00:00 +0000 |
4931 | @@ -1,19 +0,0 @@ |
4932 | -{ |
4933 | - "links" : { |
4934 | - "data" : "/query-history/data", |
4935 | - "self" : "/query-history" |
4936 | - }, |
4937 | - "name" : "query-history", |
4938 | - "run_schedule" : "1 * * * *", |
4939 | - "spool_schedule" : "2 * * * *", |
4940 | - "tasks" : [ |
4941 | - { |
4942 | - "name" : "query-history", |
4943 | - "number" : "0", |
4944 | - "options" : "--report-format profile slow008.txt", |
4945 | - "output" : "spool", |
4946 | - "program" : "pt-query-digest" |
4947 | - } |
4948 | - ], |
4949 | - "ts" : 100 |
4950 | -} |
4951 | |
4952 | === removed file 't/pt-agent/schedule_services.t' |
4953 | --- t/pt-agent/schedule_services.t 2013-06-17 00:28:18 +0000 |
4954 | +++ t/pt-agent/schedule_services.t 1970-01-01 00:00:00 +0000 |
4955 | @@ -1,200 +0,0 @@ |
4956 | -#!/usr/bin/env perl |
4957 | - |
4958 | -BEGIN { |
4959 | - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" |
4960 | - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; |
4961 | - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; |
4962 | -}; |
4963 | - |
4964 | -use strict; |
4965 | -use warnings FATAL => 'all'; |
4966 | -use English qw(-no_match_vars); |
4967 | -use Test::More; |
4968 | -use JSON; |
4969 | -use File::Temp qw(tempfile tempdir); |
4970 | - |
4971 | -use Percona::Test; |
4972 | -use Percona::Test::Mock::AgentLogger; |
4973 | -require "$trunk/bin/pt-agent"; |
4974 | - |
4975 | -my $crontab = `crontab -l 2>/dev/null`; |
4976 | -if ( $crontab ) { |
4977 | - plan skip_all => 'Crontab is not empty'; |
4978 | -} |
4979 | - |
4980 | -Percona::Toolkit->import(qw(have_required_args Dumper)); |
4981 | - |
4982 | -my $sample = "t/pt-agent/samples"; |
4983 | -my $tmpdir = tempdir("/tmp/pt-agent.$PID.XXXXXX", CLEANUP => 1); |
4984 | - |
4985 | -my @log; |
4986 | -my $logger = Percona::Test::Mock::AgentLogger->new(log => \@log); |
4987 | -pt_agent::_logger($logger); |
4988 | - |
4989 | -# ############################################################################# |
4990 | -# Schedule a good crontab. |
4991 | -# ############################################################################# |
4992 | - |
4993 | -my $run0 = Percona::WebAPI::Resource::Task->new( |
4994 | - name => 'query-history', |
4995 | - number => '0', |
4996 | - program => 'pt-query-digest', |
4997 | - options => '--output json', |
4998 | - output => 'spool', |
4999 | -); |
5000 | - |
The diff has been truncated for viewing.