Skip to content

Commit

Permalink
Support wildcard aliases for Drush 8 (#4109)
Browse files Browse the repository at this point in the history
  • Loading branch information
greg-1-anderson committed Jul 3, 2019
1 parent 61c8f45 commit 1a00801
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 0 deletions.
30 changes: 30 additions & 0 deletions examples/example.aliases.drushrc.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,36 @@
* to ignore the site at the cwd and just see default drush status:
*
* $ drush @none status
*
* Wildcard Aliases for Service Providers
*
* Some service providers that manage Drupal sites allow customers to create
* multiple "environments" for a site. It is common for these providers to
* also have a feature to automatically create Drush aliases for all of a
* user's sites. Rather than write one record for every environment in that
* site, it is also possible to write a single "wildcard" alias that represents
* all possible environments. This is possible if the contents of each
* environment alias are identical save for the name of the environment in
* one or more values. The variable `${env-name}` will be substituted with the
* environment name wherever it appears.
*
* Example wildcard record:
*
* @code
* $aliases['remote-example.*'] = array(
* 'remote-host' => '${env-name}.server.domain.com',
* 'remote-user' => 'www-admin',
* 'root' => '/path/to/${env-name}',
* 'uri' => '${env-name}.example.com',
* );
* @endcode
*
* With a wildcard record, any environment name may be used, and will always
* match. This is not desirable in instances where the specified environment
* does not exist (e.g. if the user made a typo). An alias alter hook in a
* policy file may be used to catch these mistakes and report an error.
* @see policy.drush.inc for an example on how to do this.
*
* See `drush help site-alias` for more options for displaying site
* aliases. See `drush topic docs-bastion` for instructions on configuring
Expand Down
16 changes: 16 additions & 0 deletions examples/policy.drush.inc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,22 @@ function policy_drush_sitealias_alter(&$alias_record) {
}
unset($alias_record['parent']);
}

// If the alias is a remote wildcard alias, then test to see if the
// environment exists, and raise an "environment not found" error if
// it does not.
if (isset($alias_record['remote-host'])) {
$host = $alias_record['remote-host'];
if (preg_match('#\.myserver.com$#', $host)) {
$ip = gethostbyname($host);
// If the return value of gethostbyname equals its input parameter,
// that indicates failure.
if ($host == $ip) {
$aliasName = $alias_record['#name'];
return drush_set_error('NO_SUCH_ALIAS', "The alias $aliasName refers to a multidev environment that does not exist.");
}
}
}
}

/**
Expand Down
46 changes: 46 additions & 0 deletions includes/sitealias.inc
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,9 @@ function _drush_sitealias_find_and_load_alias_from_file($aliasname, $alias_files
$aliases[$group_name] = array('site-list' => implode(',', $alias_names), '#group' => $group_name, '#name' => $group_name);
}
}
// Wildcard check if necessary. This will insert a resolved alias
// record into the aliases list, allowing the existing code to match it.
_drush_sitealias_wildcard_check($aliasname, $aliases);
// Store only the named alias into the alias cache
if ((isset($aliases)) && !empty($aliasname) && array_key_exists($aliasname, $aliases)) {
drush_set_config_special_contexts($options); // maybe unnecessary
Expand Down Expand Up @@ -752,6 +755,49 @@ function _drush_sitealias_find_and_load_alias_from_file($aliasname, $alias_files
return $result;
}

/**
* Convert a matching wildcard record into the requested record if needed.
*/
function _drush_sitealias_wildcard_check($aliasname, &$aliases) {
// Don't overwrite a specific alias record with a resolved wildcard record.
if (array_key_exists($aliasname, $aliases) || empty($aliasname)) {
return;
}
// If the alias is 'site.dev', then $alias_env is 'dev'
$alias_env = preg_replace('#^.*\.#', '', $aliasname);
// Check to see if there is a wildcard record.
// e.g. if alias is 'site.dev', then look for a record 'site.*'.
$wildcard_alias_name = preg_replace('#\.[^.]*$#', '.*', $aliasname);
if (($wildcard_alias_name == $aliasname) || empty($alias_env) || !array_key_exists($wildcard_alias_name, $aliases)) {
return;
}

$aliases[$aliasname] = _drush_sitealias_replace_wildcard_values($aliases[$wildcard_alias_name], $alias_env);
$aliases[$aliasname]['#name'] = $aliasname;
}

/**
* Make substitutions in a wildcard alias record.
*/
function _drush_sitealias_replace_wildcard_values($alias_record, $alias_env) {
$result = array();

foreach ($alias_record as $key => $value) {
if (is_array($value)) {
$result[$key] = _drush_sitealias_replace_wildcard_values($value, $alias_env);
}
elseif (is_string($value)) {
// This substitution looks just like a consolidation/config variable,
// although this is the only one we support.
$result[$key] = str_replace('${env-name}', $alias_env, $value);
}
else {
$result[$key] = $value;
}
}
return $result;
}

/**
* Merges two site aliases.
*
Expand Down
32 changes: 32 additions & 0 deletions tests/siteAliasTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,38 @@ public function testBadAlias() {
$this->drush('sa', array('@badalias'), array(), NULL, NULL, self::EXIT_ERROR);
}

/**
* Test wildcard aliases
*/
public function testWildcardAliases() {
$aliasPath = UNISH_SANDBOX . '/site-alias-directory';
file_exists($aliasPath) ?: mkdir($aliasPath);
$aliasFile = $aliasPath . '/wild.aliases.drushrc.php';
$aliasContents = <<<EOD
<?php
// Written by Unish. This file is safe to delete.
\$aliases['foo.*'] = array(
'remote-host' => '\${env-name}.remote-host.com',
'remote-user' => 'www-admin',
'root' => '/path/to/\${env-name}',
'uri' => 'https://\${env-name}.foo.example.com',
);
EOD;
file_put_contents($aliasFile, $aliasContents);
$options = array(
'alias-path' => $aliasPath,
'yes' => NULL,
);
$this->drush('sa', array('@foo.bar'), $options, NULL, NULL, self::EXIT_SUCCESS);
$output = $this->getOutput();
$this->assertEquals("\$aliases[\"foo.bar\"] = array (
'remote-host' => 'bar.remote-host.com',
'remote-user' => 'www-admin',
'root' => '/path/to/bar',
'uri' => 'https://bar.foo.example.com',
);", $output);
}

/**
* Ensure that a --uri on CLI overrides on provided by site alias during a backend invoke.
*/
Expand Down

0 comments on commit 1a00801

Please sign in to comment.