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

Download one Acquia backup database at a time. #111

Merged
merged 13 commits into from
Nov 20, 2018
Merged
66 changes: 40 additions & 26 deletions defaults.properties.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,25 +118,24 @@ drupal:
# environment.
services_template: .the-build/drupal.services.build.yml


# Configuration for the database loading utility.
load_db:
# Pattern to match gzipped database dump files.
export_pattern: artifacts/backups/*.sql.gz

# The following two commands are composed to load the database into Drupal:
# $> gunzip -c FILENAME.sql.gz | drush sqlc
#
# Command to extract text contents of the backup file.
contents_command: gunzip -c
# Command to load database contents into Drupal.
mysql_command: drush sqlc

# Load a specific file rather than one matching the `export_pattern`. This can be used
# if your build relies on a seed database that is checked in to the repository.
# Otherwise, you may occasionally want to set this value at run time:
# $> phing load-db -Ddb.load.file=artifacts/foo.sql.gz
#file:
# Configuration for the database loading utility.
load_db:
# Pattern to match gzipped database dump files.
export_pattern: artifacts/backups/*.sql.gz

# The following two commands are composed to load the database into Drupal:
# $> gunzip -c FILENAME.sql.gz | drush sqlc
#
# Command to extract text contents of the backup file.
contents_command: gunzip -c
# Command to load database contents into Drupal.
mysql_command: drush sqlc

# Load a specific file rather than one matching the `export_pattern`. This can be used
# if your build relies on a seed database that is checked in to the repository.
# Otherwise, you may occasionally want to set this value at run time:
# $> phing load-db -Ddb.load.file=artifacts/foo.sql.gz
#file:


# Configuration for tasks/artifact.xml
Expand Down Expand Up @@ -178,16 +177,31 @@ artifact:

# Configuration for tasks/acquia.xml
acquia:
# Directory for storing downloaded database backups.
backups: artifacts/backups

# Machine name of your Acquia site account.
#accountname:
# Max age of the downloaded backup database, in hours.
backup_age_hours: 24

# Acquia SSH host, like `srv-1234.devcloud.hosting.acquia.com` or
# `staging-12345.prod.hosting.acquia.com`
#ssh:
# The Acquia Cloud hosting "realm" where the site is running.
# - Acquia Cloud Enterprise: 'prod'
# - Acquia Cloud Professional: 'devcloud'
realm: ""

# Directory for storing downloaded database backups.
backups: artifacts/backups
# Acquia site/application name.
site: ""

# Acquia database name. This can be left to match the site name unless you're
# using multisites.
database: "${acquia.site}"

# Acquia environment to download backups from.
env: "prod"

# Acquia Cloud API credentials file, downloaded from your Acquia account. Do not check
# this file into your codebase.
cloud:
conf: "${env.HOME}/.acquia/cloudapi.conf"


# Configuration to use the PHP interpreter's built in linter to check for syntax errors
Expand Down
30 changes: 30 additions & 0 deletions docs/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,33 @@ If the `prefix` attribute does not end in a `.`, one will be added.
```xml
<selectpropertykey prefix="drupal.sites." omitKeys="_defaults" propertyName="build.site" message="Select a site to build:" />
```

## Acquia\GetLatestBackupTask [🔗](../src/TheBuild/Acquia/GetLatestBackupTask.php)

Download a recent backup from Acquia Cloud.

### Attributes

| Name | Type | Description | Default | Required |
|---|---|---|---|---|
| dir | directory path | Local backups directory. | | Yes |
| realm | string | Acquia hosting realm, either "devcloud" or "prod". | | Yes |
| site | string | Acquia site name. | | Yes |
| env | string | Acquia environment, generally "dev", "test", or "prod". | | Yes |
| database | string | Acquia database name. | The site name. | No |
| maxAge | int | Maximum age of the backup, in hours. | 24 | No |
| propertyName | string | Name of a property to set to the backup file. | | No |
| credentialsFile | file path | Path to your Acquia Cloud API credentials. (Do not check this file in to your repository) | `~/.acquia/cloudapi.conf` | No |

### Example

```xml
<!-- Provide the <getAcquiaBackup /> task. -->
<taskdef name="getAcquiaBackup" classname="TheBuild\Acquia\GetLatestBackupTask" />

<!-- Required parameters only -->
<getAcquiaBackup dir="artifacts/backups" realm="devcloud" site="mysite" env="prod" />

<!-- More parameters -->
<getAcquiaBackup dir="artifacts/backups" realm="devcloud" site="mysite" env="prod" credentialsFile="artifacts/.acquia/cloudapi.conf" propertyName="drupal.site.load_db.file" />
```
129 changes: 129 additions & 0 deletions src/TheBuild/Acquia/AcquiaTask.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php
/**
* @file AcquiaTask.php
*
* Abastract base task for creating Acquia Cloud API tasks.
*
* Loads the Acquia Cloud credentials from a JSON file and constructs
* authenticated requests against the Cloud API.
*
* This class will use the credentials file at ~/.acquia/cloudapi.conf if none
* is provided in the task call:
*
* @code
* <exampleTask credentialsFile="artifacts/cloudapi.conf" />
* @endcode
*
* Extending classes may also set the 'endpoint' property if it is necessary to
* use the v2 API instead of v1.
*
* @copyright 2018 Palantir.net, Inc.
*/

namespace TheBuild\Acquia;

use BuildException;
use HTTP_Request2;
use PhingFile;

abstract class AcquiaTask extends \Task {

/**
* Required. The Acquia Cloud credentials file containing a json array with
* 'mail' and 'key' values.
* @var \PhingFile
*/
protected $credentialsFile;

/**
* Email address associated with the Acquia Cloud access. This value is set
* from the credentials file.
* @var string
*/
protected $mail;

/**
* Secure key associated with the Acquia Cloud access. This value is set from
* the credentials file.
* @var string
*/
protected $key;

/**
* The Acquia Cloud API endpoint. This code is specific to version 1 of the
* API.
* @var string
*/
protected $endpoint = 'https://cloudapi.acquia.com/v1';

/**
* Load the Acquia Cloud credentials from the cloudapi.conf JSON file.
*
* @throws \IOException
* @throws \NullPointerException
*/
protected function loadCredentials() {
if (empty($this->mail) || empty($this->key)) {
if (empty($this->credentialsFile)) {
$this->credentialsFile = new PhingFile($_SERVER['HOME'] . '/.acquia/cloudapi.conf');
}

if (!file_exists($this->credentialsFile) || !is_readable($this->credentialsFile)) {
throw new BuildException("Acquia Cloud credentials file '{$this->credentialsFile}' is not available.");
}

$contents = file_get_contents($this->credentialsFile);
$creds = json_decode($contents, TRUE);

$this->mail = $creds['mail'];
$this->key = $creds['key'];
}

if (empty($this->mail) || empty($this->key)) {
throw new BuildException('Missing Acquia Cloud API credentials.');
}
}

/**
* Build an HTTP request object against the Acquia Cloud API.
*
* @param $path
* @return HTTP_Request2
*/
protected function createRequest($path) {
$this->loadCredentials();

$uri = $this->endpoint . '/' . ltrim($path, '/');

$request = new HTTP_Request2($uri);
$request->setConfig('follow_redirects', TRUE);
$request->setAuth($this->mail, $this->key);

return $request;
}

/**
* Example of how to query the Acquia Cloud API.
*
* @param $path
* @return string
* @throws \HTTP_Request2_Exception
*/
protected function getApiResponseBody($path) {
$request = $this->createRequest($path);

$this->log('GET ' . $request->getUrl());
$response = $request->send();
return $response->getBody();
}

/**
* @param PhingFile $file
* @throws \IOException
* @throws \NullPointerException
*/
public function setCredentialsFile(PhingFile $file) {
$this->credentialsFile = new PhingFile($file);
}

}
Loading