Skip to content

Commit

Permalink
AL-885, AL-911 - Added backup:info command, expiry to backup:list (#1676
Browse files Browse the repository at this point in the history
)

* Added backup:info command, expiry to backup:list

* Covered new material with unit tests

* Added functional test
  • Loading branch information
TeslaDethray authored Apr 4, 2017
1 parent d585e40 commit fe6abd6
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 63 deletions.
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
* 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

0 comments on commit fe6abd6

Please sign in to comment.