Skip to content

Commit d0cb3d7

Browse files
committed
Merge pull request #152 from pantheon-systems/updater
Mass update function for terminus
2 parents 094e890 + 1ebd6f9 commit d0cb3d7

File tree

3 files changed

+148
-5
lines changed

3 files changed

+148
-5
lines changed

php/Terminus/Helpers/Input.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,26 @@ static function string( $args, $key, $label = "Enter", $default = null) {
138138
}
139139
return $string;
140140
}
141+
142+
/**
143+
* Same as confirm but doesn't exit.
144+
* @param $question string -- question to ask
145+
* @param $assoc_args array -- an input array to parse the answer from
146+
* @param $params array -- args for vsprintf()
147+
*
148+
* @return (bool)
149+
*/
150+
static function yesno($question, $assoc_args = array(), $params = array()) {
151+
if (\Terminus::get_config('yes')) return true;
152+
$question = vsprintf($question, $params);
153+
fwrite( STDOUT, $question . " [y/n] " );
154+
155+
$answer = trim( fgets( STDIN ) );
156+
157+
if ( 'y' != $answer )
158+
return false;
159+
return true;
160+
}
141161

142162
static function optional( $key, $args, $default = null ) {
143163
if (isset($args[$key])) {

php/Terminus/SiteFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ private function hydrate() {
2020
// we need to skip sites that are in the build process still
2121
if (!isset($site_data->information)) continue;
2222
$site_data->id = $site_id;
23-
$this->sites[$site_data->information->name] = $site_data;
23+
$this->sites[$site_data->information->name] = new Site($site_data);
2424
}
2525

2626
return $this;

php/commands/sites.php

Lines changed: 127 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,44 @@ public function show($args, $assoc_args) {
5151
return $toReturn;
5252
}
5353

54+
/**
55+
* Create a site report
56+
*
57+
* ## OPTIONS
58+
*
59+
* [--fields=<field>] :
60+
* A comma-separated list of fields to include, to see available fields use ```terminus site info```
61+
*
62+
* [--filter=<field:value>] :
63+
* Specify a filter on field:value. For instance upstream:.*wordpress.* would filter for sites with upstreams matching wordpress
64+
*
65+
*/
66+
public function report($args, $assoc_args) {
67+
$sites = SiteFactory::instance();
68+
$data = array();
69+
foreach ($sites as $site) {
70+
$report = array(
71+
'name' => $site->getName(),
72+
);
73+
74+
$fields = Input::optional('fields', $assoc_args, false);
75+
if ($fields) {
76+
$fields = explode(',',$fields);
77+
foreach ($fields as $field) {
78+
$report[$field] = $site->info($field);
79+
}
80+
} else {
81+
$info = $site->info();
82+
foreach ($info as $key=>$value) {
83+
$report[$key] = $value;
84+
}
85+
}
86+
87+
$data[] = $report;
88+
}
89+
90+
$this->handleDisplay($data);
91+
}
5492
/**
5593
* Create a new site
5694
*
@@ -81,10 +119,10 @@ public function create($args, $assoc_args) {
81119
$data = array();
82120
$data['label'] = Input::string($assoc_args, 'label', "Human readable label for the site");
83121
$slug = Utils\sanitize_name( $data['label'] );
84-
// 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.
122+
// 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.
85123
if (array_key_exists('name',$assoc_args)) {
86124
$data['site_name'] = $assoc_args['name'];
87-
} elseif (array_key_exists('site',$assoc_args)) {
125+
} elseif (array_key_exists('site',$assoc_args)) {
88126
$data['site_name'] = $assoc_args['site'];
89127
} else {
90128
$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 +143,7 @@ public function create($args, $assoc_args) {
105143
$workflow->refresh();
106144
$details = $workflow->status();
107145
if ($details->result !== 'failed' AND $details->result !== 'aborted') {
108-
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)));
146+
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)));
109147
}
110148
$workflow->wait();
111149
Terminus::success("Pow! You created a new site!");
@@ -189,7 +227,7 @@ function delete($args, $assoc_args) {
189227
}
190228
Terminus::line( sprintf( "Deleting %s ...", $site_to_delete->information->name ) );
191229
$response = \Terminus_Command::request( 'sites', $site_to_delete->id, '', 'DELETE' );
192-
230+
193231
Terminus::success("Deleted %s!", $site_to_delete->information->name);
194232
}
195233

@@ -227,8 +265,93 @@ public function aliases($args, $assoc_args) {
227265
} elseif ($print) {
228266
print $content;
229267
}
268+
}
269+
270+
271+
/**
272+
* Update alls dev sites with an available upstream update.
273+
*
274+
* ## OPTIONS
275+
*
276+
* [--report]
277+
* : If set output will contain list of sites and whether they are up-to-date
278+
*
279+
* [--upstream=<upstream>]
280+
* : Specify a specific upstream to check for updating.
281+
*
282+
* [--no-updatedb]
283+
* : Use flag to skip running update.php after the update has applied
284+
*
285+
* [--xoption=<theirs|ours>]
286+
* : Corresponds to git's -X option, set to 'theirs' by default -- https://www.kernel.org/pub/software/scm/git/docs/git-merge.html
287+
*
288+
* @subcommand mass-update
289+
*/
290+
public function mass_update($args, $assoc_args) {
291+
$sites = SiteFactory::instance();
292+
$env = 'dev';
293+
$upstream = Input::optional('upstream', $assoc_args, false);
294+
$data = array();
295+
$report = Input::optional('report', $assoc_args, false);
296+
$confirm = Input::optional('confirm', $assoc_args, false);
297+
298+
// Start status messages.
299+
if($upstream) Terminus::line('Looking for sites using '.$upstream.'.');
230300

301+
foreach( $sites as $site ) {
231302

303+
$updates = $site->getUpstreamUpdates();
304+
if (!isset($updates->behind)) {
305+
// No updates, go back to start.
306+
continue;
307+
}
308+
// Check for upstream argument and site upstream URL match.
309+
$siteUpstream = $site->info('upstream');
310+
if ( $upstream AND isset($siteUpstream->url)) {
311+
if($siteUpstream->url <> $upstream ) {
312+
// Uptream doesn't match, go back to start.
313+
continue;
314+
}
315+
}
316+
317+
if( $updates->behind > 0 ) {
318+
$data[$site->getName()] = array('site'=> $site->getName(), 'status' => "Needs update");
319+
$noupdatedb = Input::optional($assoc_args, 'updatedb', false);
320+
$update = $noupdatedb ? false : true;
321+
$xoption = Input::optional($assoc_args, 'xoption', 'theirs');
322+
if (!$report) {
323+
$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)));
324+
if( !$confirmed ) continue; // Suer says No, go back to start.
325+
326+
// Backup the DB so the client can restore if something goes wrong.
327+
Terminus::line('Backing up '.$site->getName().'.');
328+
$backup = $site->environment('dev')->createBackup(array('element'=>'all'));
329+
// Only continue if the backup was successful.
330+
if($backup) {
331+
Terminus::success("Backup of ".$site->getName()." created.");
332+
Terminus::line('Updating '.$site->getName().'.');
333+
// Apply the update, failure here would trigger a guzzle exception so no need to validate success.
334+
$response = $site->applyUpstreamUpdates($env, $update, $xoption);
335+
$data[$site->getName()]['status'] = 'Updated';
336+
Terminus::success($site->getName().' is updated.');
337+
} else {
338+
$data[$site->getName()]['status'] = 'Backup failed';
339+
Terminus::error('There was a problem backing up '.$site->getName().'. Update aborted.');
340+
}
341+
}
342+
} else {
343+
if (isset($assoc_args['report'])) {
344+
$data[$site->getName()] = array('site'=> $site->getName(), 'status' => "Up to date");
345+
}
346+
}
347+
}
348+
349+
if (!empty($data)) {
350+
sort($data);
351+
$this->handleDisplay($data);
352+
} else {
353+
Terminus::line('No sites in need up updating.');
354+
}
232355
}
233356
}
234357

0 commit comments

Comments
 (0)