prod_monitor.drush.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. <?php
  2. /**
  3. * Implementation of hook_drush_command().
  4. */
  5. function prod_monitor_drush_command() {
  6. $items = array();
  7. $items['prod-monitor'] = array(
  8. 'callback' => 'drush_prod_monitor_statusdetail',
  9. 'description' => 'Display the Production Monitor status page',
  10. 'aliases' => array('pmon'),
  11. 'arguments' => array(
  12. 'id' => "ID of the site to view it's status in detail.",
  13. ),
  14. );
  15. $items['prod-monitor-updates'] = array(
  16. 'callback' => '_drush_prod_monitor_updates',
  17. 'description' => 'Display the update module status page',
  18. 'aliases' => array('pmon-up'),
  19. 'arguments' => array(
  20. 'id' => 'ID of the site to view module updates for.',
  21. ),
  22. 'options' => array(
  23. '--check' => 'Check for module updates.'
  24. ),
  25. );
  26. $items['prod-monitor-fetch'] = array(
  27. 'callback' => 'drush_prod_monitor_fetch',
  28. 'description' => 'Fetch the status information from a given remote site.',
  29. 'aliases' => array('pmon-fe'),
  30. 'arguments' => array(
  31. 'id' => 'Space delemited list of site IDs to fetch all data for.',
  32. ),
  33. );
  34. $items['prod-monitor-flush'] = array(
  35. 'callback' => 'drush_prod_monitor_flush',
  36. 'description' => "Remove all fetched data for a given site.",
  37. 'aliases' => array('pmon-fl'),
  38. 'arguments' => array(
  39. 'id' => 'Space delemited list of site IDs to be flushed.',
  40. ),
  41. );
  42. $items['prod-monitor-delete'] = array(
  43. 'callback' => 'drush_prod_monitor_delsite',
  44. 'description' => 'Completemy remove a site and all its data.',
  45. 'aliases' => array('pmon-rm'),
  46. 'arguments' => array(
  47. 'id' => 'Space delemited list of site IDs to be deleted.',
  48. ),
  49. );
  50. return $items;
  51. }
  52. /**
  53. * Fetch data callback.
  54. */
  55. function drush_prod_monitor_fetch() {
  56. $args = func_get_args();
  57. foreach($args as $arg) {
  58. $site = _prod_monitor_get_site($arg);
  59. if (!empty($site['url'])) {
  60. $result = _prod_monitor_retrieve_data($arg, $site);
  61. $site['url'] = _prod_monitor_sanitize_url(rtrim($site['url'], '/'));
  62. if ($result === FALSE) {
  63. drush_print("\033[1;31m".dt('Error:')." \033[0m".dt('Unable to fetch data for').' '.$site['url'].'!');
  64. }
  65. else {
  66. drush_print(dt('Sucessfully fetched data for').' '.$site['url'].'.');
  67. }
  68. }
  69. else {
  70. drush_print("\033[1;31m".dt('Error:')." \033[0m".dt('No site found with ID').' '.$arg.'!');
  71. }
  72. }
  73. }
  74. /**
  75. * Flush data callback.
  76. */
  77. function drush_prod_monitor_flush() {
  78. $args = func_get_args();
  79. foreach ($args as $arg) {
  80. $url = _prod_monitor_get_url($arg);
  81. if (!empty($url)) {
  82. if (!drush_confirm(dt('Do you really want to flush all data for').' '.$url.'?')) {
  83. drush_die('Aborting.');
  84. }
  85. $result = _prod_monitor_flush_data($arg);
  86. if ($result === FALSE) {
  87. drush_print("\033[1;31m".dt('Error:')." \033[0m".dt('Unable to flush data!'));
  88. }
  89. else {
  90. drush_print(dt('Stored data successfully flushed.'));
  91. }
  92. }
  93. else {
  94. drush_print("\033[1;31m".dt('Error:')." \033[0m".dt('No site found with ID').' '.$arg.'!');
  95. }
  96. }
  97. }
  98. /**
  99. * Delete site callback.
  100. */
  101. function drush_prod_monitor_delsite() {
  102. $args = func_get_args();
  103. foreach ($args as $arg) {
  104. $url = _prod_monitor_get_url($arg);
  105. if (!empty($url)) {
  106. if (!drush_confirm(dt("Do you really want to delete").' '.$url.' '.dt('and all its data?'))) {
  107. drush_die('Aborting.');
  108. }
  109. $result = _prod_monitor_delete_site($arg);
  110. if ($result === FALSE) {
  111. drush_print("\033[1;31m".dt('Error:')." \033[0m".dt('Unable to delete') . $url .'!');
  112. }
  113. else {
  114. drush_print(dt('Website successfully deleted.'));
  115. }
  116. }
  117. else {
  118. drush_print("\033[1;31m".dt('Error:')." \033[0m".dt('No site found with ID').' '.$arg.'!');
  119. }
  120. }
  121. }
  122. /**
  123. * Status page callback
  124. */
  125. function drush_prod_monitor_statusdetail() {
  126. $args = func_get_args();
  127. if (empty($args)) {
  128. _drush_prod_monitor_overview();
  129. }
  130. else if (is_numeric($args[0])) {
  131. _drush_prod_monitor_detail($args[0]);
  132. }
  133. }
  134. function _drush_prod_monitor_overview() {
  135. $sites = _prod_monitor_get_sites();
  136. // Map error codes to shell colours.
  137. $severity = array (
  138. 'ok' => '1;32',
  139. 'warning' => '1;33',
  140. 'error' => '1;31',
  141. );
  142. $rows = array(array(
  143. dt('ID'),
  144. dt('URL'),
  145. dt('Data'),
  146. dt('Date added'),
  147. dt('Last update'),
  148. dt('Status'),
  149. ));
  150. // TODO: check why the colour coding messes up the tabs for the table
  151. // Worked around this by placing the status column last
  152. foreach ($sites as $id => $site_info) {
  153. $rows[] = array(
  154. $id,
  155. _prod_monitor_sanitize_url(rtrim($site_info['url'], '/')),
  156. (!$site_info['data']) ? dt('Empty') : t('Stored'),
  157. $site_info['added'],
  158. (!$site_info['lastupdate']) ? dt('Not yet updated') : $site_info['lastupdate'],
  159. "\033[".$severity[$site_info['status']].'m'.ucwords($site_info['status'])."\033[0m",
  160. );
  161. }
  162. drush_print("\033[1m".dt('Production Monitor status')."\033[0m\n", 1);
  163. if (count($rows) > 1) {
  164. drush_print_table($rows, TRUE);
  165. drush_print(dt('Use drush prod-monitor [id] to view the details of a specific site.'));
  166. }
  167. else {
  168. drush_print(dt('No sites added yet! Yo can add sites on admin/reports/prod-monitor.'), 1);
  169. }
  170. }
  171. function _drush_prod_monitor_detail($id) {
  172. $site = _prod_monitor_get_site($id, TRUE);
  173. if (!isset($site['url'])) {
  174. drush_print("\033[1;31m".dt('Error:')." \033[0m".dt('No site found with ID').' '.$id.'!');
  175. return;
  176. }
  177. // Overall status block
  178. $block = array();
  179. $modules = _prod_monitor_get_site_modules($id);
  180. if(!empty($modules)) {
  181. $prod_mon = $site['data']['prod_mon'];
  182. $cron = dt('Unknown');
  183. if (isset($prod_mon['prod_check_cron_last'])) {
  184. $cron = format_date($prod_mon['prod_check_cron_last'], 'large');
  185. }
  186. $title = dt('Unknown');
  187. $color = "\033[0m";
  188. if ($modules['updates'] > 0) {
  189. switch ($modules['updates']) {
  190. case 1:
  191. $title = dt('None');
  192. break;
  193. case 2:
  194. $color = "\033[1;33m";
  195. $title = dt('Available');
  196. break;
  197. case 3:
  198. $color = "\033[1;31m";
  199. $title = dt('Security risk!');
  200. break;
  201. }
  202. }
  203. $updates = $color . $title . "\033[0m";
  204. // Construct block
  205. $block[] = array("\033[1m".dt('Overall status')."\033[0m");
  206. $block[] = array(
  207. dt('Drupal core version'),
  208. $modules['projects']['drupal']['info']['version'],
  209. );
  210. $block[] = array(
  211. dt('Last cron run'),
  212. $cron,
  213. );
  214. $block[] = array(
  215. dt('Updates'),
  216. $updates,
  217. );
  218. }
  219. // cleanup
  220. unset($site['data']['prod_mon']);
  221. unset($modules);
  222. $functions = $site['settings']['functions'];
  223. $nodata = dt('No data recieved yet.');
  224. $url = rtrim($site['url'], '/');
  225. // Map error codes to shell colours.
  226. $severity = array (
  227. REQUIREMENT_INFO => '1',
  228. REQUIREMENT_OK => '1;32',
  229. REQUIREMENT_WARNING => '1;33',
  230. REQUIREMENT_ERROR => '1;31',
  231. );
  232. $error = 0;
  233. $rows = array();
  234. foreach ($functions as $set => $data) {
  235. if (isset($site['data'][$set])) {
  236. $rows[] = array('');
  237. $rows[] = array("\033[1m".dt($data['title'])."\033[0m");
  238. if (!empty($site['data'][$set])) {
  239. foreach ($site['data'][$set] as $check => $result) {
  240. $rows[] = array(
  241. $result['title'],
  242. "\033[".$severity[$result['severity']].'m'.strip_tags($result['value'])."\033[0m",
  243. );
  244. if ($error < $result['severity']) {
  245. $error = $result['severity'];
  246. }
  247. }
  248. }
  249. else {
  250. $rows[] = array($nodata);
  251. }
  252. }
  253. }
  254. // Actual printing.
  255. drush_print("\033[1m".dt('Production Monitor status for').' '._prod_monitor_sanitize_url($url)."\033[0m", 1);
  256. if (!empty($block)) {
  257. drush_print_table($block);
  258. }
  259. if (!empty($rows)) {
  260. drush_print_table($rows);
  261. }
  262. else {
  263. drush_print($nodata, 1);
  264. }
  265. if ($error > 0) {
  266. // Would be cool if we could prefix the admin path with http://<host>/ so it
  267. // will become a clickable link in some terminals. Any ideas?
  268. drush_print("\033[1m".dt('Some errors were reported!')."\033[0m ".dt('Check the full status page on')." \033[1m".'admin/reports/prod-monitor/'.$id.'/view'."\033[0m ".dt('for details.'));
  269. }
  270. }
  271. /**
  272. * Update status page callback.
  273. */
  274. function _drush_prod_monitor_updates() {
  275. $id = func_get_args();
  276. if (empty($id)) {
  277. drush_set_error('prod_monitor', dt('You must provide a site ID!'));
  278. return;
  279. }
  280. $id = $id['0'];
  281. // Get module info.
  282. $modules = _prod_monitor_get_site_modules($id);
  283. $url = _prod_monitor_get_url($id);
  284. if (empty($modules)) {
  285. if (empty($url)) {
  286. drush_set_error('prod_monitor', dt('No site found with ID').' '. $id .'!');
  287. return;
  288. }
  289. else {
  290. drush_set_error('prod_monitor', dt('No module data found for') .' '. $url.'!');
  291. return;
  292. }
  293. }
  294. else if (empty($modules['available'])) {
  295. drush_set_error('prod_monitor', dt('No update data found for') .' '. $url.'!');
  296. // No data, ask for refresh.
  297. _drush_prod_monitor_update_refresh($id, $modules);
  298. }
  299. // Refresh if user asked for it.
  300. if (drush_get_option('check')) {
  301. _drush_prod_monitor_update_refresh($id, $modules);
  302. }
  303. $last = $modules['lastupdate'];
  304. module_load_include('inc', 'prod_monitor', 'includes/prod_monitor.update');
  305. $projects = _prod_monitor_calculate_project_data($id, $modules['projects'], $modules['available']);
  306. // Cleanup.
  307. unset($modules);
  308. // Table headers.
  309. $rows[] = array(dt('Name'), dt('Installed version'), dt('Proposed version'), dt('Status'));
  310. // Process releases, notifying user of status and building a list of proposed updates
  311. drush_include_engine('update_info', 'drupal', NULL, DRUSH_BASE_PATH . '/commands/pm/update_info');
  312. drush_include(DRUSH_BASE_PATH . '/commands/pm', 'updatecode.pm');
  313. $updateable = pm_project_filter($projects, $rows);
  314. // Pipe preparation
  315. if (drush_get_context('DRUSH_PIPE')) {
  316. $pipe = "";
  317. foreach($projects as $project){
  318. $pipe .= $project['name']. " ";
  319. $pipe .= $project['existing_version']. " ";
  320. $pipe .= $project['candidate_version']. " ";
  321. $pipe .= str_replace(' ', '-', pm_update_filter($project)). "\n";
  322. }
  323. drush_print_pipe($pipe);
  324. // Automatically curtail update process if in pipe mode
  325. $updateable = FALSE;
  326. }
  327. drush_print("\033[1m".dt('Module update status for').' '.$url."\033[0m", 1);
  328. drush_print(dt('Update information last refreshed:') .' '. ($last ? format_date($last) : dt('Never'))."\n", 1);
  329. drush_print_table($rows, TRUE);
  330. }
  331. /**
  332. * Helper function to refresh update status data.
  333. */
  334. function _drush_prod_monitor_update_refresh($id, &$modules) {
  335. if (!drush_confirm(dt('Would you like to check for module updates now?'))) {
  336. drush_die('Aborting.');
  337. }
  338. else {
  339. drush_print(dt('Refreshing update status information ...'));
  340. module_load_include('inc', 'prod_monitor', 'includes/prod_monitor.update');
  341. $result = _prod_monitor_update_refresh($id, $modules['projects'], $modules['sitekey']);
  342. if (!empty($result)) {
  343. drush_print();
  344. $modules['available'] = $result;
  345. $modules['lastupdate'] = time();
  346. }
  347. else {
  348. drush_set_error('prod_monitor', dt('Failed to refres update status information for') .' '. $url.'!');
  349. drush_die('Aborting.');
  350. }
  351. }
  352. }