diff --git a/README.md b/README.md index fcf572b..1926539 100644 --- a/README.md +++ b/README.md @@ -302,6 +302,17 @@ terminus secret:site:delete . [notice] Success ``` +#### Generate file for local development + +The secrets `local-generate` command will generate a json file useful for local development emulation of secrets. + +**Run the command below to get a json file:** + +``` +terminus secret:site:local-generate --filepath=./secrets.json +[notice] Secrets file written to: ./secrets.json. Please review this file and adjust accordingly for your local usage. +``` + ### Organization secrets Commands #### Set a secret diff --git a/src/Commands/SiteLocalGenerateCommand.php b/src/Commands/SiteLocalGenerateCommand.php new file mode 100644 index 0000000..5c56a20 --- /dev/null +++ b/src/Commands/SiteLocalGenerateCommand.php @@ -0,0 +1,93 @@ + Generate json file with secrets for local usage. + * @usage --filepath=/my/path/filename.json Generate json file in given location with secrets for local usage. + * + * @param string $site_id The name or UUID of a site to retrieve information on + * @param array $options + * + * @return RowsOfFields + * @throws \GuzzleHttp\Exception\GuzzleException + * @throws \Pantheon\Terminus\Exceptions\TerminusException + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface + */ + public function localGenerateSecrets($site_id, array $options = ['filepath' => 'secrets.json',]) + { + $env_name = ''; + if (strpos($site_id, '.') !== false) { + list($site_id, $env_name) = explode('.', $site_id, 2); + } + $site = $this->getSite($site_id); + $this->setupRequest(); + $result = $this->secretsApi->fetchSecrets($site->id); + if ($result->getStatusCode() != 200) { + throw new TerminusException($result->getData()); + } + $data = $result->getData(); + $json_contents = json_encode($data, JSON_PRETTY_PRINT); + $filepath = $options['filepath']; + $ret = file_put_contents($filepath, $json_contents); + if ($ret === false) { + throw new TerminusException('Unable to write to file: ' . $filepath); + } + $this->log()->notice(sprintf("Secrets file written to: %s. Please review this file and adjust accordingly for your local usage.", $filepath)); + } + + /** + * @param array $secrets Complete secret data + * @param string $env_name Name of environment to pull secrets from + * + * @return array Secret data containing only secrets with overrides + * in the specified environment. + */ + protected function secretsForEnv(array $secrets, $env_name) + { + $result = []; + + foreach ($secrets as $key => $data) { + if (array_key_exists($env_name, $data['env-values'] ?? [])) { + $result[$key] = [ + 'name' => $key, + 'type' => $data['type'], + 'value' => $data['env-values'][$env_name], + 'scopes' => $data['scopes'], + ]; + } + } + + return $result; + } + +} diff --git a/src/SecretsApi/SecretsApi.php b/src/SecretsApi/SecretsApi.php index 1f7028a..e3ab5da 100644 --- a/src/SecretsApi/SecretsApi.php +++ b/src/SecretsApi/SecretsApi.php @@ -46,7 +46,7 @@ private function getBaseURI() } /** - * List secrets for a given site. + * Fetch secrets for a given site. * * @param string $workspaceId * Site/org id to get secrets for. @@ -55,13 +55,13 @@ private function getBaseURI() * @param string $workspaceType * Whether to return the secrets for a site or org. * - * @return array|Pantheon\Terminus\Request\RequestOperationResult - * Secrets for given site or the operation result in case of error. + * @return Pantheon\Terminus\Request\RequestOperationResult + * Request operation result. * * @throws \GuzzleHttp\Exception\GuzzleException * @throws \Pantheon\Terminus\Exceptions\TerminusException */ - public function listSecrets(string $workspaceId, bool $debug = false, string $workspaceType = "sites") + public function fetchSecrets(string $workspaceId, bool $debug = false, string $workspaceType = "sites") { if (getenv('TERMINUS_PLUGIN_TESTING_MODE')) { if (file_exists('/tmp/secrets.json')) { @@ -84,7 +84,28 @@ public function listSecrets(string $workspaceId, bool $debug = false, string $wo ], 'debug' => $debug, ]; - $result = $this->request()->request($url, $options); + return $this->request()->request($url, $options); + } + + /** + * List secrets for a given site. + * + * @param string $workspaceId + * Site/org id to get secrets for. + * @param bool $debug + * Whether to return the secrets in debug mode. + * @param string $workspaceType + * Whether to return the secrets for a site or org. + * + * @return array|Pantheon\Terminus\Request\RequestOperationResult + * Secrets for given site or the operation result in case of error. + * + * @throws \GuzzleHttp\Exception\GuzzleException + * @throws \Pantheon\Terminus\Exceptions\TerminusException + */ + public function listSecrets(string $workspaceId, bool $debug = false, string $workspaceType = "sites") + { + $result = $this->fetchSecrets($workspaceId, $debug, $workspaceType); if ($result->getStatusCode() !== 200) { return $result; }