From b0cd5ca748ede77c7c083a923a4d7bbf37cda993 Mon Sep 17 00:00:00 2001 From: Adam Malone Date: Sat, 4 Apr 2020 17:08:49 +1100 Subject: [PATCH] Fixes #48: Allows all configuration to be overwritten with environment variables and refactors the setup commands. --- src/Cli/CloudApi.php | 5 -- src/Cli/Config.php | 25 +++++++- src/Commands/SetupCommand.php | 77 +++++++++++++++++----- tests/AcquiaCliApplicationTest.php | 38 ++++++++++- tests/AcquiaCliTestCase.php | 6 -- tests/Commands/SetupCommandTest.php | 99 +++++++++++++++++++++++++++++ 6 files changed, 221 insertions(+), 29 deletions(-) create mode 100644 tests/Commands/SetupCommandTest.php diff --git a/src/Cli/CloudApi.php b/src/Cli/CloudApi.php index 41c1d75..472c285 100644 --- a/src/Cli/CloudApi.php +++ b/src/Cli/CloudApi.php @@ -34,11 +34,6 @@ public static function createClient(Config $config) { $acquia = $config->get('acquia'); - - if (getenv('ACQUIACLI_KEY') && getenv('ACQUIACLI_SECRET')) { - $acquia['key'] = getenv('ACQUIACLI_KEY'); - $acquia['secret'] = getenv('ACQUIACLI_SECRET'); - } $connector = new Connector( [ diff --git a/src/Cli/Config.php b/src/Cli/Config.php index 6050726..79e0d90 100644 --- a/src/Cli/Config.php +++ b/src/Cli/Config.php @@ -26,12 +26,35 @@ public function __construct($root) $globalConfig = join(DIRECTORY_SEPARATOR, [$homeDir, '.acquiacli', 'acquiacli.yml']); $projectConfig = join(DIRECTORY_SEPARATOR, [$root, 'acquiacli.yml']); + $environment = []; + if (getenv('ACQUIACLI_KEY')) { + $environment['acquia']['key'] = getenv('ACQUIACLI_KEY'); + } + if (getenv('ACQUIACLI_SECRET')) { + $environment['acquia']['secret'] = getenv('ACQUIACLI_SECRET'); + } + if (getenv('ACQUIACLI_TIMEZONE')) { + $environment['extraconfig']['timezone'] = getenv('ACQUIACLI_TIMEZONE'); + } + if (getenv('ACQUIACLI_FORMAT')) { + $environment['extraconfig']['format'] = getenv('ACQUIACLI_FORMAT'); + } + if (getenv('ACQUIACLI_TASKWAIT')) { + $environment['extraconfig']['taskwait'] = getenv('ACQUIACLI_TASKWAIT'); + } + if (getenv('ACQUIACLI_TIMEOUT')) { + $environment['extraconfig']['timeout'] = getenv('ACQUIACLI_TIMEOUT'); + } + $processor->extend($loader->load($defaultConfig)); $processor->extend($loader->load($globalConfig)); $processor->extend($loader->load($projectConfig)); + $processor->add($environment); $this->import($processor->export()); - $this->set('config.project', $projectConfig); + $this->set('config.default', $defaultConfig); $this->set('config.global', $globalConfig); + $this->set('config.project', $projectConfig); + $this->set('config.environment', $environment); } } diff --git a/src/Commands/SetupCommand.php b/src/Commands/SetupCommand.php index 6771346..0ebdb59 100644 --- a/src/Commands/SetupCommand.php +++ b/src/Commands/SetupCommand.php @@ -30,25 +30,67 @@ public function setup(Config $config) } foreach ($configFiles as $type => $location) { - $this->say(sprintf('Checking %s configuration at %s', $type, $location)); - if (file_exists($location)) { - $this->yell(sprintf('%s configuration file found', $type)); - if (!is_readable($location) && !@chmod($location, 0644)) { - $this->yell(sprintf('%s configuration is not readable', $type), 40, 'red'); + $this->yell(sprintf('%s configuration (%s)', ucfirst($type), $location)); + + if ( + file_exists($location) && $this->confirm( + sprintf('Would you like to regenerate the %s configuration file', $type) + ) + ) { + $this->createConfigYaml($location); + } elseif ( + $this->confirm( + sprintf('%s configuration file not found. Would you like to add one?', ucfirst($type)) + ) + ) { + $this->createConfigYaml($location); + } + } + } + + /** + * Allows users to view the configuration that they have on their system. + * + * This provides a view of default, global, project, and environment variable based configuration. + * + * @command setup:config:view + */ + public function configView(Config $config) + { + $configFiles = [ + 'default' => $config->get('config.default'), + 'global' => $config->get('config.global'), + 'environment' => $config->get('config.environment') + ]; + + // Do not include project configuration if this is running in a Phar. + if (!\Phar::running()) { + $configFiles['project'] = $config->get('config.project'); + } + + foreach ($configFiles as $type => $data) { + $contents = ''; + if (is_array($data)) { + if (empty($data)) { continue; } - if ($this->confirm('Would you like to view the contents of this file?')) { - if ($contents = file_get_contents($location)) { - $this->say($contents); - } - } - if ($this->confirm("Would you like to delete and regenerate the acquiacli.yml file at ${location}?")) { - $this->createConfigYaml($location); - } - } elseif ($this->confirm(sprintf('No file found. Would you like to add a file at %s?', $location))) { - $this->createConfigYaml($location); + $contents = Yaml::dump($data); + } elseif (file_exists($data) && is_readable($data)) { + $contents = file_get_contents($data); + } else { + continue; } + $this->yell(sprintf('%s configuration', ucfirst($type))); + $this->writeln($contents); } + + $this->yell('Running configuration'); + $running = [ + 'acquia' => $config->get('acquia'), + 'extraconfig' => $config->get('extraconfig') + ]; + + $this->writeln(Yaml::dump($running)); } /** @@ -78,7 +120,10 @@ private function createConfigYaml($location) if (!is_dir(dirname($location))) { mkdir(dirname($location), 700); } - if (file_put_contents($location, $yaml)) { + + if (!is_writable($location) && !@chmod($location, 0644)) { + $this->yell(sprintf('%s is not writeable', ucfirst($location)), 40, 'red'); + } elseif (file_put_contents($location, $yaml)) { $this->say(sprintf('Configuration file written to %s', $location)); } else { $this->say('Unable to write configuration file.'); diff --git a/tests/AcquiaCliApplicationTest.php b/tests/AcquiaCliApplicationTest.php index 833faa4..8ebcc20 100644 --- a/tests/AcquiaCliApplicationTest.php +++ b/tests/AcquiaCliApplicationTest.php @@ -23,7 +23,7 @@ public function setUp() parent::setUp(); } - public function testConfig() + public function testDefaultConfig() { $config = new Config($this->root); @@ -43,6 +43,42 @@ public function testConfig() $this->assertEquals($defaultExtraConfig, $config->get('extraconfig')); } + public function testEnvironmentConfig() + { + // Set environment variables so we can test configuration overrides. + putenv('ACQUIACLI_KEY=16fd1cde-1e66-b113-8e98-5ff9d444d54f'); + putenv('ACQUIACLI_SECRET=SDtg0o83TrZm5gVckpaZynCxpikMqcht9u3fexWIHm7'); + putenv('ACQUIACLI_TIMEZONE=Australia/Hobart'); + putenv('ACQUIACLI_FORMAT=Y-m-d H:i:s (U)'); + putenv('ACQUIACLI_TASKWAIT=2'); + putenv('ACQUIACLI_TIMEOUT=400'); + + $config = new Config($this->root); + + $environmentAcquiaConfig = [ + 'key' => '16fd1cde-1e66-b113-8e98-5ff9d444d54f', + 'secret' => 'SDtg0o83TrZm5gVckpaZynCxpikMqcht9u3fexWIHm7' + ]; + + $environmentExtraConfig = [ + 'timezone' => 'Australia/Hobart', + 'format' => 'Y-m-d H:i:s (U)', + 'taskwait' => 2, + 'timeout' => 400 + ]; + + $this->assertEquals($environmentAcquiaConfig, $config->get('acquia')); + $this->assertEquals($environmentExtraConfig, $config->get('extraconfig')); + + // Remove them at the end of the test so they do not interfere with other tests. + putenv('ACQUIACLI_KEY='); + putenv('ACQUIACLI_SECRET='); + putenv('ACQUIACLI_TIMEZONE='); + putenv('ACQUIACLI_FORMAT='); + putenv('ACQUIACLI_TASKWAIT='); + putenv('ACQUIACLI_TIMEOUT='); + } + public function testVersion() { $versionFile = sprintf('%s/VERSION', $this->root); diff --git a/tests/AcquiaCliTestCase.php b/tests/AcquiaCliTestCase.php index 213427d..ac223b9 100644 --- a/tests/AcquiaCliTestCase.php +++ b/tests/AcquiaCliTestCase.php @@ -5,8 +5,6 @@ use AcquiaCloudApi\Connector\Client; use Symfony\Component\Console\Input\ArgvInput; use AcquiaCli\Cli\Config; -use Consolidation\Config\Loader\ConfigProcessor; -use Consolidation\Config\Loader\YamlConfigLoader; use AcquiaCli\Cli\AcquiaCli; use Symfony\Component\Console\Output\BufferedOutput; use Consolidation\AnnotatedCommand\CommandData; @@ -150,10 +148,6 @@ public function execute($command) // Create an instance of the application and use some default parameters. $root = dirname(dirname(__DIR__)); $config = new Config($root); - $loader = new YamlConfigLoader(); - $processor = new ConfigProcessor(); - $processor->extend($loader->load(dirname(__DIR__) . '/default.acquiacli.yml')); - $config->import($processor->export()); array_unshift($command, 'acquiacli', '--no-wait', '--yes'); $input = new ArgvInput($command); diff --git a/tests/Commands/SetupCommandTest.php b/tests/Commands/SetupCommandTest.php new file mode 100644 index 0000000..d3154b2 --- /dev/null +++ b/tests/Commands/SetupCommandTest.php @@ -0,0 +1,99 @@ +execute($command); + $this->assertSame($defaultConfiguration, $actualResponse); + } + + public function testSetupConfigViewOverwritten() + { + $command = ['setup:config:view']; + $overwrittenConfiguration = <<< OVERWRITTEN + + Default configuration + +acquia: + key: 'd0697bfc-7f56-4942-9205-b5686bf5b3f5' + secret: 'D5UfO/4FfNBWn4+0cUwpLOoFzfP7Qqib4AoY+wYGsKE=' +extraconfig: + timezone: 'Australia/Sydney' + format: 'Y-m-d H:i:s' + taskwait: 5 + timeout: 300 + + + Environment configuration + +extraconfig: + timezone: Australia/Melbourne + format: U + + + Running configuration + +acquia: + key: d0697bfc-7f56-4942-9205-b5686bf5b3f5 + secret: D5UfO/4FfNBWn4+0cUwpLOoFzfP7Qqib4AoY+wYGsKE= +extraconfig: + timezone: Australia/Melbourne + format: U + taskwait: 5 + timeout: 300 + + +OVERWRITTEN; + + putenv('ACQUIACLI_TIMEZONE=Australia/Melbourne'); + putenv('ACQUIACLI_FORMAT=U'); + + $actualResponse = $this->execute($command); + $this->assertSame($overwrittenConfiguration, $actualResponse); + + putenv('ACQUIACLI_TIMEZONE='); + putenv('ACQUIACLI_FORMAT='); + } +}