Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AL-885, AL-911 - Added backup:info command, expiry to backup:list #1676

Merged
merged 3 commits into from
Apr 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# Change Log
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org)

## MASTER
### Changed
- `Backup::getDate()` now returns a Unix datetime instead of a formatted date. (#1676)

### Added
- The `backup:info` command has been added. (#1676)
- Added expiration dates to backups in `backup:list`. (#1676)
- `Backup::getExpiry()` calculates the Unix datetime of a backup's expiry. (#1676)

## 1.1.2 - 2017-03-31
### Changed
- Reenabled the `self:console` command in PHP 7.1. (#1664)
Expand Down
23 changes: 3 additions & 20 deletions src/Commands/Backup/GetCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@

use Pantheon\Terminus\Request\RequestAwareInterface;
use Pantheon\Terminus\Request\RequestAwareTrait;
use Pantheon\Terminus\Exceptions\TerminusNotFoundException;

/**
* Class GetCommand
* @package Pantheon\Terminus\Commands\Backup
*/
class GetCommand extends BackupCommand implements RequestAwareInterface
class GetCommand extends SingleBackupCommand implements RequestAwareInterface
{
use RequestAwareTrait;

Expand All @@ -33,25 +32,9 @@ class GetCommand extends BackupCommand implements RequestAwareInterface
* @usage <site>.<env> --to=<path> Saves the most recent backup of any type in <site>'s <env> environment to <path>.
* @usage <site>.<env> --to=<path> Saves the most recent <element> backup in <site>'s <env> environment to <path>.
*/
public function getBackup($site_env, array $options = ['file' => null, 'element' => 'all', 'to' => null,])
public function get($site_env, array $options = ['file' => null, 'element' => 'all', 'to' => null,])
{
list($site, $env) = $this->getSiteEnv($site_env);

if (isset($options['file']) && !is_null($file_name = $options['file'])) {
$backup = $env->getBackups()->getBackupByFileName($file_name);
} else {
$element = isset($options['element']) ? $this->getElement($options['element']) : null;
$backups = $env->getBackups()->getFinishedBackups($element);
if (empty($backups)) {
throw new TerminusNotFoundException(
'No backups available. Create one with `terminus backup:create {site}.{env}`',
['site' => $site->get('name'), 'env' => $env->id,]
);
}
$backup = array_shift($backups);
}

$backup_url = $backup->getUrl();
$backup_url = $this->getBackup($site_env, $options)->getUrl();
if (!isset($options['to']) || is_null($save_path = $options['to'])) {
return $backup_url;
}
Expand Down
42 changes: 42 additions & 0 deletions src/Commands/Backup/InfoCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Pantheon\Terminus\Commands\Backup;

use Consolidation\OutputFormatters\StructuredData\PropertyList;

/**
* Class InfoCommand
* @package Pantheon\Terminus\Commands\Backup
*/
class InfoCommand extends SingleBackupCommand
{
/**
* Displays information about a specific backup or the latest backup.
*
* @authorize
*
* @command backup:info
*
* @field-labels
* file: Filename
* size: Size
* date: Date
* expiry: Expiry
* initiator: Initiator
* url: URL
* @return PropertyList
*
* @param string $site_env Site & environment in the format `site-name.env`
* @option string $file [filename.tgz] Name of backup file
* @option string $element [all|code|files|database|db] Backup element to retrieve
*
* @usage <site>.<env> Displays information about the most recent backup of any type in <site>'s <env> environment.
* @usage <site>.<env> --file=<file_name> Displays information about the backup with the file name <file_name> in <site>'s <env> environment.
* @usage <site>.<env> --element=<element> Displays information about the most recent <element> backup in <site>'s <env> environment.
*/
public function info($site_env, array $options = ['file' => null, 'element' => 'all',])
{
$backup = $this->getBackup($site_env, $options);
return new PropertyList(array_merge($backup->serialize(), ['url' => $backup->getUrl(),]));
}
}
1 change: 1 addition & 0 deletions src/Commands/Backup/ListCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class ListCommand extends BackupCommand
* file: Filename
* size: Size
* date: Date
* expiry: Expiry
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I personally like this, I believe US english prefers 'expiration'. But I'm 1/10 on this because expiry is shorter and way classier because it is true uncorrupted queens english :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it too, so let's ask @kimby77 to weigh in. What do you think?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no opinion :)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whatever you guys think is best here!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* initiator: Initiator
* @return RowsOfFields
*
Expand Down
18 changes: 2 additions & 16 deletions src/Commands/Backup/RestoreCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
namespace Pantheon\Terminus\Commands\Backup;

use Pantheon\Terminus\Exceptions\TerminusException;
use Pantheon\Terminus\Exceptions\TerminusNotFoundException;

/**
* Class RestoreCommand
* @package Pantheon\Terminus\Commands\Backup
*/
class RestoreCommand extends BackupCommand
class RestoreCommand extends SingleBackupCommand
{
/**
* Restores a specific backup or the latest backup.
Expand All @@ -30,20 +29,7 @@ class RestoreCommand extends BackupCommand
public function restoreBackup($site_env, array $options = ['file' => null, 'element' => 'all',])
{
list($site, $env) = $this->getSiteEnv($site_env);

if (isset($options['file']) && !is_null($file_name = $options['file'])) {
$backup = $env->getBackups()->getBackupByFileName($file_name);
} else {
$element = isset($options['element']) ? $this->getElement($options['element']) : null;
$backups = $env->getBackups()->getFinishedBackups($this->getElement($element));
if (empty($backups)) {
throw new TerminusNotFoundException(
'No backups available. Create one with `terminus backup:create {site}.{env}`',
['site' => $site->get('name'), 'env' => $env->id,]
);
}
$backup = array_shift($backups);
}
$backup = $this->getBackup($site_env, $options);

$tr = ['site' => $site->getName(), 'env' => $env->getName()];
if (!$this->confirm('Are you sure you want to restore to {env} on {site}?', $tr)) {
Expand Down
35 changes: 35 additions & 0 deletions src/Commands/Backup/SingleBackupCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Pantheon\Terminus\Commands\Backup;

use Pantheon\Terminus\Exceptions\TerminusNotFoundException;

abstract class SingleBackupCommand extends BackupCommand
{

/**
* @param $site_env
* @param array $options
* @return Backup
* @throws TerminusNotFoundException
*/
protected function getBackup($site_env, array $options = ['file' => null, 'element' => 'all',])
{
list($site, $env) = $this->getSiteEnv($site_env);

if (isset($options['file']) && !is_null($file_name = $options['file'])) {
$backup = $env->getBackups()->getBackupByFileName($file_name);
} else {
$element = isset($options['element']) ? $this->getElement($options['element']) : null;
$backups = $env->getBackups()->getFinishedBackups($element);
if (empty($backups)) {
throw new TerminusNotFoundException(
'No backups available. Create one with `terminus backup:create {site}.{env}`',
['site' => $site->get('name'), 'env' => $env->id,]
);
}
$backup = array_shift($backups);
}
return $backup;
}
}
30 changes: 22 additions & 8 deletions src/Models/Backup.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,26 @@ public function getBucket()
*/
public function getDate()
{
if (!is_null($this->get('finish_time'))) {
$datetime = $this->get('finish_time');
} elseif (!is_null($this->get('timestamp'))) {
$datetime = $this->get('timestamp');
} else {
return 'Pending';
if (!is_null($finish_time = $this->get('finish_time'))) {
return $finish_time;
}
return date($this->getConfig()->get('date_format'), $datetime);
if (!is_null($timestamp = $this->get('timestamp'))) {
return $timestamp;
}
return 'Pending';
}

/**
* Returns the backup expiry datetime
*
* @return string Expiry datetime or null
*/
public function getExpiry()
{
if (is_numeric($datetime = $this->getDate())) {
return $datetime + $this->get('ttl');
}
return null;
}

/**
Expand Down Expand Up @@ -168,10 +180,12 @@ public function restore()
*/
public function serialize()
{
$date_format = $this->getConfig()->get('date_format');
return [
'file' => $this->get('filename'),
'size' => $this->getSizeInMb(),
'date' => $this->getDate(),
'date' => date($date_format, $this->getDate()),
'expiry' => date($date_format, $this->getExpiry()),
'initiator' => $this->getInitiator(),
];
}
Expand Down
38 changes: 38 additions & 0 deletions tests/features/backup-info.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Feature: Get a particular backup for a site
In order to secure my site against failures
As a user
I need to be able to get information about a backup that has been made

Background: I am authenticated and have a site named [[test_site_name]]
Given I am authenticated
And a site named "[[test_site_name]]"

@vcr backup-get-file.yml
Scenario: Gets information about the latest code backup made
When I run "terminus backup:info [[test_site_name]].dev --element=code"
Then I should get: "----------- -----------------------------------------------------"
And I should get: "Filename [[test_site_name]]_dev_2016-08-18T23-16-20_UTC_code.tar.gz"
And I should get: "Size 31.8MB"
And I should get: "Date 2016-08-18 23:16:30"
And I should get: "Expiry 2017-08-19 05:02:06"
And I should get: "Initiator manual"
And I should get: "----------- -----------------------------------------------------"

@vcr backup-get-file.yml
Scenario: Gets informtion about a backup selected by filename
When I run "terminus backup:info [[test_site_name]].dev --file=[[test_site_name]]_dev_2016-08-18T23-16-20_UTC_code.tar.gz"
Then I should get: "----------- -----------------------------------------------------"
And I should get: "Filename [[test_site_name]]_dev_2016-08-18T23-16-20_UTC_code.tar.gz"
And I should get: "Size 31.8MB"
And I should get: "Date 2016-08-18 23:16:30"
And I should get: "Expiry 2017-08-19 05:02:06"
And I should get: "Initiator manual"
And I should get: "----------- -----------------------------------------------------"

@vcr backup-get-none.yml
Scenario: Failing to find a matching backup
When I run "terminus backup:info [[test_site_name]].test --element=database"
Then I should get:
"""
No backups available. Create one with `terminus backup:create [[test_site_name]].test`
"""
10 changes: 5 additions & 5 deletions tests/unit_tests/Commands/Backup/GetCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function testGetBackupWithFile()
->method('getUrl')
->willReturn($test_download_url);

$output = $this->command->getBackup('mysite.dev', ['file' => $test_filename,]);
$output = $this->command->get('mysite.dev', ['file' => $test_filename,]);
$this->assertEquals($output, $test_download_url);
}

Expand All @@ -61,7 +61,7 @@ public function testGetBackupWithElement()
->method('getUrl')
->willReturn('http://download');

$output = $this->command->getBackup('mysite.dev', ['element' => 'db',]);
$output = $this->command->get('mysite.dev', ['element' => 'db',]);
$this->assertEquals($output, 'http://download');
}

Expand All @@ -79,7 +79,7 @@ public function testGetBackupWithInvalidFile()

$this->setExpectedException(TerminusNotFoundException::class);

$out = $this->command->getBackup('mysite.dev', ['file' => $bad_file_name,]);
$out = $this->command->get('mysite.dev', ['file' => $bad_file_name,]);
$this->assertNull($out);
}

Expand Down Expand Up @@ -107,7 +107,7 @@ public function testGetBackupNoBackups()
"No backups available. Create one with `terminus backup:create $site.{$this->environment->id}`"
);

$out = $this->command->getBackup("$site.{$this->environment->id}", compact('element'));
$out = $this->command->get("$site.{$this->environment->id}", compact('element'));
$this->assertNull($out);
}

Expand Down Expand Up @@ -138,7 +138,7 @@ public function testGetBackupToFile()
);

$this->command->setRequest($request);
$out = $this->command->getBackup('mysite.dev', ['file' => $test_filename, 'to' => $test_save_path,]);
$out = $this->command->get('mysite.dev', ['file' => $test_filename, 'to' => $test_save_path,]);
$this->assertNull($out);
}
}
77 changes: 77 additions & 0 deletions tests/unit_tests/Commands/Backup/InfoCommandTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

namespace Pantheon\Terminus\UnitTests\Commands\Backup;

use Consolidation\OutputFormatters\StructuredData\PropertyList;
use Pantheon\Terminus\Commands\Backup\InfoCommand;

/**
* Class InfoCommandTest
* Testing class for Pantheon\Terminus\Commands\Backup\InfoCommand
* @package Pantheon\Terminus\UnitTests\Commands\Backup
*/
class InfoCommandTest extends BackupCommandTest
{
/**
* @var array
*/
protected $expected_data;

/**
* Sets up the fixture, for example, open a network connection.
* This method is called before a test is executed.
*/
protected function setUp()
{
parent::setUp();

$sample_data = [
'file' => 'file name',
'size' => 'file size',
'date' => 459880805,
'expiry' => 3615640805,
'initiator' => 'backup initiator',
];
$url = 'https://url.to/backup.tgz';
$this->expected_data = array_merge($sample_data, compact('url'));

$this->backup->method('serialize')->willReturn($sample_data);
$this->backup->method('getUrl')->willReturn($url);

$this->command = new InfoCommand($this->sites);
$this->command->setLogger($this->logger);
$this->command->setSites($this->sites);
}

/**
* Tests the backup:info command with file
*/
public function testInfoBackupWithFile()
{
$test_filename = 'test.tar.gz';

$this->backups->expects($this->once())
->method('getBackupByFileName')
->with($test_filename)
->willReturn($this->backup);

$output = $this->command->info('mysite.dev', ['file' => $test_filename,]);
$this->assertInstanceOf(PropertyList::class, $output);
$this->assertEquals($this->expected_data, $output->getArrayCopy());
}

/**
* Tests the backup:info command with an element
*/
public function testInfoBackupWithElement()
{
$this->backups->expects($this->once())
->method('getFinishedBackups')
->with('database')
->willReturn([$this->backup,]);

$output = $this->command->info('mysite.dev', ['element' => 'db',]);
$this->assertInstanceOf(PropertyList::class, $output);
$this->assertEquals($this->expected_data, $output->getArrayCopy());
}
}
Loading