From 4ea6fd762234b7a6d7be09f2d510a9112f82d445 Mon Sep 17 00:00:00 2001 From: Erik Mathy Date: Thu, 19 Feb 2015 00:14:03 -0800 Subject: [PATCH 1/9] Changing upstream updates argument to be > 0 vs == 1. The returned int value is actually the # of updates the site is behind, rather than a 0|1 False|True. -EHM --- php/commands/site.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/commands/site.php b/php/commands/site.php index b65a132aa..779ba2e62 100755 --- a/php/commands/site.php +++ b/php/commands/site.php @@ -1228,7 +1228,7 @@ public function upstream_updates($args, $assoc_args) { if(isset($upstream->remote_url) && isset($upstream->behind)) { // The $upstream object returns a value of [behind] -> 1 if there is an // upstream update that has not been applied to Dev. - $data[$upstream->remote_url] = ($upstream->behind == 1 ? "Updates Available":"Up-to-date"); + $data[$upstream->remote_url] = ($upstream->behind > 0 ? "Updates Available":"Up-to-date"); $this->_constructTableForResponse($data, array('Upstream','Status') ); if (!isset($upstream) OR empty($upstream->update_log)) Terminus::success("No updates to show"); From 7e35379e03e5f68436737b3bc20cf6d5583114bb Mon Sep 17 00:00:00 2001 From: Mike Van Winkle Date: Fri, 20 Feb 2015 00:35:10 +0000 Subject: [PATCH 2/9] Updater --- php/Terminus/SiteFactory.php | 2 +- php/commands/sites.php | 56 +++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/php/Terminus/SiteFactory.php b/php/Terminus/SiteFactory.php index 107c7c021..15cf43873 100755 --- a/php/Terminus/SiteFactory.php +++ b/php/Terminus/SiteFactory.php @@ -20,7 +20,7 @@ private function hydrate() { // we need to skip sites that are in the build process still if (!isset($site_data->information)) continue; $site_data->id = $site_id; - $this->sites[$site_data->information->name] = $site_data; + $this->sites[$site_data->information->name] = new Site($site_data); } return $this; diff --git a/php/commands/sites.php b/php/commands/sites.php index 9df651993..f9873c1f2 100755 --- a/php/commands/sites.php +++ b/php/commands/sites.php @@ -222,8 +222,62 @@ public function aliases($args, $assoc_args) { } elseif ($print) { print $content; } + } + - +/** + * Update alls dev sites with an upstream update available. + * + * ## OPTIONS + * + * [--confirm] + * : Run the updates in interactive mode + * + * [--report] + * : If set output will contain list of sites and whether they are up-to-date + * + * [--framework=] + * : Specify drupal or wordpress + * + * [--no-updatedb] + * : Use flag to skip running update.php after the update has applied + * + * [--xoption=] + * : Corresponds to git's -X option, set to 'theirs' by default -- https://www.kernel.org/pub/software/scm/git/docs/git-merge.html + * + * @subcommand mass-update + */ + public function mass_update($args, $assoc_args) { + $sites = SiteFactory::instance(); + $framework = Input::optional($assoc_args, 'framework', false); + $data = array(); + $report = Input::optional($assoc_args, 'report', false); + $confirm = Input::optional($assoc_args, 'confirm', false); +var_dump(get_defined_vars()); + foreach( $sites as $site ) { + if ( $framework AND $site->info('framework') !== $framework ) continue; + $updates = $site->getUpstreamUpdates(); + if( $updates->behind > 0 ) { + $data[$site->getName()] = array('site'=> $site->getName(), 'status' => "Needs update"); + $noupdatedb = Input::optional($assoc_args, 'updatedb', false); + $update = $noupdatedb ? false : true; + $xoption = Input::optional($assoc_args, 'xoption', 'theirs'); + if (!$report) { + if( $confirm ) { + Terminus::confirm("Apply upstream updatefs to %s ( run update.php:%s, xoption:%s ) ", $assoc_args, array($site->getName(), var_export($update,1), var_export($xoption,1))); + } + } + } else { + if (isset($assoc_args['report'])) { + $data[$site->getName()] = array('site'=> $site->getName(), 'status' => "Up to date"); + } + } + } + + if (!empty($data)) { + sort($data); + $this->handleDisplay($data); + } } private function getIdFromName($name) { From 1ac5da854392227a742e6399de8f36ab7af49a56 Mon Sep 17 00:00:00 2001 From: Mike Van Winkle Date: Fri, 20 Feb 2015 22:57:29 +0000 Subject: [PATCH 3/9] Mass update function --- php/commands/sites.php | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/php/commands/sites.php b/php/commands/sites.php index d4de98a6e..cf4f9ae5b 100755 --- a/php/commands/sites.php +++ b/php/commands/sites.php @@ -254,11 +254,11 @@ public function aliases($args, $assoc_args) { */ public function mass_update($args, $assoc_args) { $sites = SiteFactory::instance(); - $framework = Input::optional($assoc_args, 'framework', false); + $env = 'dev'; + $framework = Input::optional('framework', $assoc_args, false); $data = array(); - $report = Input::optional($assoc_args, 'report', false); - $confirm = Input::optional($assoc_args, 'confirm', false); -var_dump(get_defined_vars()); + $report = Input::optional('report', $assoc_args, false); + $confirm = Input::optional('confirm', $assoc_args, false); foreach( $sites as $site ) { if ( $framework AND $site->info('framework') !== $framework ) continue; $updates = $site->getUpstreamUpdates(); @@ -269,13 +269,19 @@ public function mass_update($args, $assoc_args) { $xoption = Input::optional($assoc_args, 'xoption', 'theirs'); if (!$report) { if( $confirm ) { - Terminus::confirm("Apply upstream updatefs to %s ( run update.php:%s, xoption:%s ) ", $assoc_args, array($site->getName(), var_export($update,1), var_export($xoption,1))); - } + // skip if we don't confirm + $confirmed = Input::yesno("Apply upstream updatefs to %s ( run update.php:%s, xoption:%s ) ", $assoc_args, array($site->getName(), var_export($update,1), var_export($xoption,1))); + if( !$confirmed ) continue; + } + + // apply the update, failure here would trigger a guzzle exception so no need to validate success. + $response = $site->applyUpstreamUpdates($env, $update, $xoption); + $data[$site->getName()]['status'] = 'Updated'; } } else { if (isset($assoc_args['report'])) { $data[$site->getName()] = array('site'=> $site->getName(), 'status' => "Up to date"); - } + } } } From 9f6332cbf3f0a3448a5c786243d8e5c83e54bea2 Mon Sep 17 00:00:00 2001 From: Mike Van Winkle Date: Fri, 20 Feb 2015 23:32:39 +0000 Subject: [PATCH 4/9] Skip if no value set for behind --- php/commands/sites.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/php/commands/sites.php b/php/commands/sites.php index cf4f9ae5b..629bb071c 100755 --- a/php/commands/sites.php +++ b/php/commands/sites.php @@ -262,6 +262,9 @@ public function mass_update($args, $assoc_args) { foreach( $sites as $site ) { if ( $framework AND $site->info('framework') !== $framework ) continue; $updates = $site->getUpstreamUpdates(); + if (!isset($updates->behind)) { + continue; + } if( $updates->behind > 0 ) { $data[$site->getName()] = array('site'=> $site->getName(), 'status' => "Needs update"); $noupdatedb = Input::optional($assoc_args, 'updatedb', false); From 73af3b2458faba8afc60236f477409761bf1c99d Mon Sep 17 00:00:00 2001 From: Mike Van Winkle Date: Fri, 20 Feb 2015 23:33:32 +0000 Subject: [PATCH 5/9] Added Input::yesno() function to the input helper --- php/Terminus/Helpers/Input.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/php/Terminus/Helpers/Input.php b/php/Terminus/Helpers/Input.php index 0c55a80bc..37481fe19 100755 --- a/php/Terminus/Helpers/Input.php +++ b/php/Terminus/Helpers/Input.php @@ -138,6 +138,26 @@ static function string( $args, $key, $label = "Enter", $default = null) { } return $string; } + + /** + * Same as confirm but doesn't exit. + * @param $question string -- question to ask + * @param $assoc_args array -- an input array to parse the answer from + * @param $params array -- args for vsprintf() + * + * @return (bool) + */ + static function yesno($question, $assoc_args = array(), $params = array()) { + if (\Terminus::get_config('yes')) return true; + $question = vsprintf($question, $params); + fwrite( STDOUT, $question . " [y/n] " ); + + $answer = trim( fgets( STDIN ) ); + + if ( 'y' != $answer ) + return false; + return true; + } static function optional( $key, $args, $default = null ) { if (isset($args[$key])) { From b878c5a4a169aaa092198612a4ce588cc980ad72 Mon Sep 17 00:00:00 2001 From: Erik Mathy Date: Wed, 25 Feb 2015 13:01:55 -0800 Subject: [PATCH 6/9] Making confirm before update default behavior. Adding full site backup prior to upstream update, stops process if backup fails. Adding in process informational output. - EHM --- php/commands/sites.php | 64 ++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/php/commands/sites.php b/php/commands/sites.php index 629bb071c..506146254 100755 --- a/php/commands/sites.php +++ b/php/commands/sites.php @@ -81,10 +81,10 @@ public function create($args, $assoc_args) { $data = array(); $data['label'] = Input::string($assoc_args, 'label', "Human readable label for the site"); $slug = Utils\sanitize_name( $data['label'] ); - // this ugly logic is temporarily if to handle the deprecated --name flag and preserve backward compatibility. it can be removed in the next major release. + // this ugly logic is temporarily if to handle the deprecated --name flag and preserve backward compatibility. it can be removed in the next major release. if (array_key_exists('name',$assoc_args)) { $data['site_name'] = $assoc_args['name']; - } elseif (array_key_exists('site',$assoc_args)) { + } elseif (array_key_exists('site',$assoc_args)) { $data['site_name'] = $assoc_args['site']; } else { $data['site_name'] = Input::string($assoc_args, 'site', "Machine name of the site; used as part of the default URL [ if left blank will be $slug]", $slug); @@ -105,7 +105,7 @@ public function create($args, $assoc_args) { $workflow->refresh(); $details = $workflow->status(); if ($details->result !== 'failed' AND $details->result !== 'aborted') { - Terminus\Loggers\Regular::coloredOutput('%G'.vsprintf('New "site" %s now building with "UUID" %s', array($details->waiting_for_task->params->site_name, $details->waiting_for_task->params->site_id))); + Terminus\Loggers\Regular::coloredOutput('%G'.vsprintf('New "site" %s now building with "UUID" %s', array($details->waiting_for_task->params->site_name, $details->waiting_for_task->params->site_id))); } $workflow->wait(); Terminus::success("Pow! You created a new site!"); @@ -189,7 +189,7 @@ function delete($args, $assoc_args) { } Terminus::line( sprintf( "Deleting %s ...", $site_to_delete->information->name ) ); $response = \Terminus_Command::request( 'sites', $site_to_delete->id, '', 'DELETE' ); - + Terminus::success("Deleted %s!", $site_to_delete->information->name); } @@ -228,22 +228,19 @@ public function aliases($args, $assoc_args) { print $content; } } - + /** - * Update alls dev sites with an upstream update available. - * + * Update alls dev sites with an available upstream update. + * * ## OPTIONS - * - * [--confirm] - * : Run the updates in interactive mode * - * [--report] + * [--report] * : If set output will contain list of sites and whether they are up-to-date - * + * * [--framework=] * : Specify drupal or wordpress - * + * * [--no-updatedb] * : Use flag to skip running update.php after the update has applied * @@ -266,32 +263,45 @@ public function mass_update($args, $assoc_args) { continue; } if( $updates->behind > 0 ) { - $data[$site->getName()] = array('site'=> $site->getName(), 'status' => "Needs update"); + $data[$site->getName()] = array('site'=> $site->getName(), 'status' => "Needs update"); $noupdatedb = Input::optional($assoc_args, 'updatedb', false); $update = $noupdatedb ? false : true; $xoption = Input::optional($assoc_args, 'xoption', 'theirs'); if (!$report) { - if( $confirm ) { - // skip if we don't confirm - $confirmed = Input::yesno("Apply upstream updatefs to %s ( run update.php:%s, xoption:%s ) ", $assoc_args, array($site->getName(), var_export($update,1), var_export($xoption,1))); - if( !$confirmed ) continue; - } - - // apply the update, failure here would trigger a guzzle exception so no need to validate success. - $response = $site->applyUpstreamUpdates($env, $update, $xoption); - $data[$site->getName()]['status'] = 'Updated'; + $confirmed = Input::yesno("Apply upstream updatefs to %s ( run update.php:%s, xoption:%s ) ", $assoc_args, array($site->getName(), var_export($update,1), var_export($xoption,1))); + if( !$confirmed ) continue; + + // Backup the DB so the client can restore if something goes wrong. + echo 'Backing up '.$site->getName().'.'; + echo PHP_EOL; + $backup = $site->environment('dev')->createBackup(array('element'=>'all')); + // Only continue if the backup was successful. + if($backup) { + Terminus::success("Backup of ".$site->getName()." created."); + echo 'Updating '.$site->getName(); + echo PHP_EOL; + // Apply the update, failure here would trigger a guzzle exception so no need to validate success. + $response = $site->applyUpstreamUpdates($env, $update, $xoption); + $data[$site->getName()]['status'] = 'Updated'; + Terminus::success($site->getName().' is updated.'); + echo PHP_EOL; + } else { + Terminus::error("Couldn't create backup of ".$site->getName().". Please check your site Dashboard for errors and try again."); + echo 'There was a problem backing up '.$site->getName().'. Update aborted.'; + echo PHP_EOL; + } } } else { if (isset($assoc_args['report'])) { - $data[$site->getName()] = array('site'=> $site->getName(), 'status' => "Up to date"); - } + $data[$site->getName()] = array('site'=> $site->getName(), 'status' => "Up to date"); + } } } - + if (!empty($data)) { sort($data); $this->handleDisplay($data); - } + } } private function getIdFromName($name) { From 6479c3623879454c07b295ecf334326b2a74a638 Mon Sep 17 00:00:00 2001 From: Erik Mathy Date: Wed, 25 Feb 2015 16:07:36 -0800 Subject: [PATCH 7/9] Replacing echo & EOL with Terminus::line. -EHM --- php/commands/sites.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/php/commands/sites.php b/php/commands/sites.php index 506146254..201ae496b 100755 --- a/php/commands/sites.php +++ b/php/commands/sites.php @@ -272,23 +272,19 @@ public function mass_update($args, $assoc_args) { if( !$confirmed ) continue; // Backup the DB so the client can restore if something goes wrong. - echo 'Backing up '.$site->getName().'.'; - echo PHP_EOL; + Terminus::line('Backing up '.$site->getName().'.'); $backup = $site->environment('dev')->createBackup(array('element'=>'all')); // Only continue if the backup was successful. if($backup) { Terminus::success("Backup of ".$site->getName()." created."); - echo 'Updating '.$site->getName(); - echo PHP_EOL; + Terminus::line('Updating '.$site->getName().'.'); // Apply the update, failure here would trigger a guzzle exception so no need to validate success. $response = $site->applyUpstreamUpdates($env, $update, $xoption); $data[$site->getName()]['status'] = 'Updated'; Terminus::success($site->getName().' is updated.'); - echo PHP_EOL; } else { Terminus::error("Couldn't create backup of ".$site->getName().". Please check your site Dashboard for errors and try again."); - echo 'There was a problem backing up '.$site->getName().'. Update aborted.'; - echo PHP_EOL; + Terminus::line('There was a problem backing up '.$site->getName().'. Update aborted.'); } } } else { From 65ca24b498d9070a10bc9091c1bdd9afd3bbf15b Mon Sep 17 00:00:00 2001 From: Erik Mathy Date: Thu, 26 Feb 2015 15:54:03 -0800 Subject: [PATCH 8/9] Removed framework argument. Added upstream argument and checks to match site upstreams against that argument. Added backup fail msg to , process start msg to CLI status outputs. -EHM --- php/commands/sites.php | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/php/commands/sites.php b/php/commands/sites.php index 201ae496b..7efb876a4 100755 --- a/php/commands/sites.php +++ b/php/commands/sites.php @@ -238,8 +238,8 @@ public function aliases($args, $assoc_args) { * [--report] * : If set output will contain list of sites and whether they are up-to-date * - * [--framework=] - * : Specify drupal or wordpress + * [--upstream=] + * : Specify a specific upstream to check for updating. * * [--no-updatedb] * : Use flag to skip running update.php after the update has applied @@ -252,16 +252,31 @@ public function aliases($args, $assoc_args) { public function mass_update($args, $assoc_args) { $sites = SiteFactory::instance(); $env = 'dev'; - $framework = Input::optional('framework', $assoc_args, false); + $upstream = Input::optional('upstream', $assoc_args, false); $data = array(); $report = Input::optional('report', $assoc_args, false); $confirm = Input::optional('confirm', $assoc_args, false); + + // Start status messages. + Terminus::line('Starting mass-update.'); + if($upstream) Terminus::line('Looking for sites using '.$upstream.'.'); + foreach( $sites as $site ) { - if ( $framework AND $site->info('framework') !== $framework ) continue; + $updates = $site->getUpstreamUpdates(); if (!isset($updates->behind)) { + // No updates, go back to start. continue; } + // Check for upstream argument and site upstream URL match. + $siteUpstream = $site->info('upstream'); + if ( $upstream AND isset($siteUpstream->url)) { + if($siteUpstream->url <> $upstream ) { + // Uptream doesn't match, go back to start. + continue; + } + } + if( $updates->behind > 0 ) { $data[$site->getName()] = array('site'=> $site->getName(), 'status' => "Needs update"); $noupdatedb = Input::optional($assoc_args, 'updatedb', false); @@ -269,7 +284,7 @@ public function mass_update($args, $assoc_args) { $xoption = Input::optional($assoc_args, 'xoption', 'theirs'); if (!$report) { $confirmed = Input::yesno("Apply upstream updatefs to %s ( run update.php:%s, xoption:%s ) ", $assoc_args, array($site->getName(), var_export($update,1), var_export($xoption,1))); - if( !$confirmed ) continue; + if( !$confirmed ) continue; // Suer says No, go back to start. // Backup the DB so the client can restore if something goes wrong. Terminus::line('Backing up '.$site->getName().'.'); @@ -279,12 +294,12 @@ public function mass_update($args, $assoc_args) { Terminus::success("Backup of ".$site->getName()." created."); Terminus::line('Updating '.$site->getName().'.'); // Apply the update, failure here would trigger a guzzle exception so no need to validate success. - $response = $site->applyUpstreamUpdates($env, $update, $xoption); + // $response = $site->applyUpstreamUpdates($env, $update, $xoption); $data[$site->getName()]['status'] = 'Updated'; Terminus::success($site->getName().' is updated.'); } else { - Terminus::error("Couldn't create backup of ".$site->getName().". Please check your site Dashboard for errors and try again."); - Terminus::line('There was a problem backing up '.$site->getName().'. Update aborted.'); + $data[$site->getName()]['status'] = 'Backup failed'; + Terminus::error('There was a problem backing up '.$site->getName().'. Update aborted.'); } } } else { @@ -297,6 +312,8 @@ public function mass_update($args, $assoc_args) { if (!empty($data)) { sort($data); $this->handleDisplay($data); + } else { + Terminus::line('No sites in need up updating.'); } } From 1ebd6f93884f0181c7058a06bda65ea52e646deb Mon Sep 17 00:00:00 2001 From: Mike Van Winkle Date: Thu, 5 Mar 2015 22:02:13 +0000 Subject: [PATCH 9/9] Add a report function so customers can actually see what upstreams they are using --- php/commands/sites.php | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/php/commands/sites.php b/php/commands/sites.php index 7efb876a4..eb470b715 100755 --- a/php/commands/sites.php +++ b/php/commands/sites.php @@ -51,6 +51,44 @@ public function show($args, $assoc_args) { return $toReturn; } + /** + * Create a site report + * + * ## OPTIONS + * + * [--fields=] : + * A comma-separated list of fields to include, to see available fields use ```terminus site info``` + * + * [--filter=] : + * Specify a filter on field:value. For instance upstream:.*wordpress.* would filter for sites with upstreams matching wordpress + * + */ + public function report($args, $assoc_args) { + $sites = SiteFactory::instance(); + $data = array(); + foreach ($sites as $site) { + $report = array( + 'name' => $site->getName(), + ); + + $fields = Input::optional('fields', $assoc_args, false); + if ($fields) { + $fields = explode(',',$fields); + foreach ($fields as $field) { + $report[$field] = $site->info($field); + } + } else { + $info = $site->info(); + foreach ($info as $key=>$value) { + $report[$key] = $value; + } + } + + $data[] = $report; + } + + $this->handleDisplay($data); + } /** * Create a new site * @@ -258,7 +296,6 @@ public function mass_update($args, $assoc_args) { $confirm = Input::optional('confirm', $assoc_args, false); // Start status messages. - Terminus::line('Starting mass-update.'); if($upstream) Terminus::line('Looking for sites using '.$upstream.'.'); foreach( $sites as $site ) { @@ -294,7 +331,7 @@ public function mass_update($args, $assoc_args) { Terminus::success("Backup of ".$site->getName()." created."); Terminus::line('Updating '.$site->getName().'.'); // Apply the update, failure here would trigger a guzzle exception so no need to validate success. - // $response = $site->applyUpstreamUpdates($env, $update, $xoption); + $response = $site->applyUpstreamUpdates($env, $update, $xoption); $data[$site->getName()]['status'] = 'Updated'; Terminus::success($site->getName().' is updated.'); } else {