Skip to content

Commit

Permalink
Fix wildcard matching for environment IDs that contain a / character
Browse files Browse the repository at this point in the history
Affected commands: `environment:delete` and `user:add`
  • Loading branch information
pjcdawkins committed May 3, 2022
1 parent c7a0a34 commit 230e37f
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 23 deletions.
26 changes: 5 additions & 21 deletions src/Command/Environment/EnvironmentDeleteCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use Platformsh\Cli\Command\CommandBase;
use Platformsh\Cli\Console\ArrayArgument;
use Platformsh\Cli\Util\Wildcard;
use Platformsh\Client\Model\Environment;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -60,7 +61,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
if ($specifiedEnvironmentIds) {
$anythingSpecified = true;
$specifiedEnvironmentIds = $this->findEnvironmentIDsByWildcards($environments, $specifiedEnvironmentIds);
$allIds = \array_map(function (Environment $e) { return $e->id; }, $environments);
$specifiedEnvironmentIds = Wildcard::select($allIds, $specifiedEnvironmentIds);
$notFound = array_diff($specifiedEnvironmentIds, array_keys($environments));
if (!empty($notFound)) {
// Refresh the environments list if any environment is not found.
Expand Down Expand Up @@ -146,7 +148,8 @@ function ($environment) {
// Exclude environment ID(s) specified in --exclude.
$excludeIds = ArrayArgument::getOption($input, 'exclude');
if (!empty($excludeIds)) {
$resolved = $this->findEnvironmentIdsByWildcards($selectedEnvironments, $excludeIds);
$selectedIds = \array_map(function (Environment $e) { return $e->id; }, $selectedEnvironments);
$resolved = Wildcard::select($selectedIds, $excludeIds);
if (count($resolved)) {
$selectedEnvironments = \array_filter($selectedEnvironments, function (Environment $e) use ($resolved) {
return !\in_array($e->id, $resolved, true);
Expand Down Expand Up @@ -234,25 +237,6 @@ function ($environment) {
return $success ? 0 : 1;
}

/**
* Finds environments in a list matching a list of ID wildcards.
*
* @param Environment[] $environments
* @param string[] $wildcards
*
* @return string[]
*/
private function findEnvironmentIDsByWildcards(array $environments, $wildcards)
{
$ids = \array_map(function (Environment $e) { return $e->id; }, $environments);
$found = [];
foreach ($wildcards as $wildcard) {
$pattern = '/^' . str_replace('%', '.*', preg_quote($wildcard)) . '$/';
$found = array_merge($found, \preg_grep($pattern, $ids));
}
return \array_unique($found);
}

/**
* @param array $toDeactivate
* @param array $toDeleteBranch
Expand Down
4 changes: 2 additions & 2 deletions src/Command/User/UserAddCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ private function getSpecifiedEnvironmentRoles(array $roles)
$role = $this->validateEnvironmentRole($role);
// Match environment IDs by wildcard.
if (strpos($id, '%') !== false) {
$pattern = '/^' . str_replace('%', '.*', preg_quote($id)) . '$/';
$pattern = '/^' . str_replace('%', '.*', preg_quote($id, '/')) . '$/';
$matched = preg_grep($pattern, array_keys($environments));
if (empty($matched)) {
throw new InvalidArgumentException('No environment IDs match: ' . $id);
Expand Down Expand Up @@ -856,7 +856,7 @@ private function getSpecifiedEnvironmentTypeRoles(array &$roles)
$role = $this->validateEnvironmentRole($role);
// Match type IDs by wildcard.
if (strpos($id, '%') !== false) {
$pattern = '/^' . str_replace('%', '.*', preg_quote($id)) . '$/';
$pattern = '/^' . str_replace('%', '.*', preg_quote($id, '/')) . '$/';
$matched = preg_grep($pattern, $typeIds);
if (empty($matched)) {
throw new InvalidArgumentException('No environment type IDs match: ' . $id);
Expand Down
24 changes: 24 additions & 0 deletions src/Util/Wildcard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Platformsh\Cli\Util;

class Wildcard
{
/**
* Selects strings in a list matching a list of wildcards.
*
* @param string[] $subjects
* @param string[] $wildcards
*
* @return string[]
*/
public static function select(array $subjects, $wildcards)
{
$found = [];
foreach ($wildcards as $wildcard) {
$pattern = '/^' . \str_replace('%', '.*', \preg_quote($wildcard, '/')) . '$/';
$found = \array_merge($found, \preg_grep($pattern, $subjects));
}
return \array_unique($found);
}
}
31 changes: 31 additions & 0 deletions tests/Util/WildcardTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Platformsh\Cli\Tests\Util;

use Platformsh\Cli\Util\Wildcard;

class WildcardTest extends \PHPUnit_Framework_TestCase
{
public function testSelect()
{
$cases = [
[['a', 'b', 'c'], ['a'], ['a']],
[['foo', 'bar', 'baz'], ['foo'], ['foo']],
[['foo', 'bar', 'baz', 'bazz', 'boz'], ['ba%'], ['bar', 'baz', 'bazz']],
[
['feature/apple', 'feature/pear', 'feature/banana', 'feature/blueberry'],
['feature/banana'],
['feature/banana'],
],
[
['feature/apple', 'feature/pear', 'feature/banana', 'feature/blueberry'],
['f%b%y', 'f%/pear', 'hotfix/%'],
['feature/blueberry', 'feature/pear'],
],
];
foreach ($cases as $i => $case) {
list($subjects, $wildcards, $result) = $case;
$this->assertEquals($result, Wildcard::select($subjects, $wildcards), "Case $i");
}
}
}

0 comments on commit 230e37f

Please sign in to comment.