Skip to content

Commit

Permalink
Merge pull request #1994 from acelaya-forks/feature/docker-compose-se…
Browse files Browse the repository at this point in the history
…crets

Support loading env vars from secret files
  • Loading branch information
acelaya authored Feb 10, 2024
2 parents deef938 + a8611f5 commit 17792a1
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this

## [Unreleased]
### Added
* *Nothing*
* [#1868](https://github.com/shlinkio/shlink/issues/1868) Add support for [docker compose secrets](https://docs.docker.com/compose/use-secrets/) to the docker image.

### Changed
* [#1935](https://github.com/shlinkio/shlink/issues/1935) Replace dependency on abandoned `php-middleware/request-id` with userland simple middleware.
Expand Down
6 changes: 4 additions & 2 deletions bin/test/run-api-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ echo 'Starting server...'
[ "$TEST_RUNTIME" = 'openswoole' ] && vendor/bin/laminas mezzio:swoole:start -d
[ "$TEST_RUNTIME" = 'rr' ] && bin/rr serve -p -c=config/roadrunner/.rr.dev.yml \
-o=http.address=0.0.0.0:9999 \
-o=http.pool.debug=false \
-o=jobs.pool.debug=false \
-o=logs.encoding=json \
-o=logs.channels.http.encoding=json \
-o=logs.channels.server.encoding=json \
Expand All @@ -29,10 +31,10 @@ echo 'Starting server...'
sleep 2 # Let's give the server a couple of seconds to start

vendor/bin/phpunit --order-by=random -c phpunit-api.xml --testdox --colors=always --log-junit=build/coverage-api/junit.xml $*
testsExitCode=$?
TESTS_EXIT_CODE=$?

[ "$TEST_RUNTIME" = 'openswoole' ] && vendor/bin/laminas mezzio:swoole:stop
[ "$TEST_RUNTIME" = 'rr' ] && bin/rr stop -c config/roadrunner/.rr.dev.yml -o=http.address=0.0.0.0:9999

# Exit this script with the same code as the tests. If tests failed, this script has to fail
exit $testsExitCode
exit $TESTS_EXIT_CODE
23 changes: 22 additions & 1 deletion module/Core/src/Config/EnvVars.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

namespace Shlinkio\Shlink\Core\Config;

use function file_get_contents;
use function is_file;
use function Shlinkio\Shlink\Config\env;
use function Shlinkio\Shlink\Config\parseEnvVar;
use function sprintf;

enum EnvVars: string
{
Expand Down Expand Up @@ -77,7 +81,24 @@ enum EnvVars: string

public function loadFromEnv(mixed $default = null): mixed
{
return env($this->value, $default);
return env($this->value) ?? $this->loadFromFileEnv() ?? $default;
}

/**
* Checks if an equivalent environment variable exists with the `_FILE` suffix. If so, it loads its value as a file,
* reads it, and returns its contents.
* This is useful when loading Shlink with docker compose and using secrets.
* See https://docs.docker.com/compose/use-secrets/
*/
private function loadFromFileEnv(): string|int|bool|null
{
$file = env(sprintf('%s_FILE', $this->value));
if ($file === null || ! is_file($file)) {
return null;
}

$content = file_get_contents($file);
return $content ? parseEnvVar($content) : null;
}

public function existsInEnv(): bool
Expand Down
10 changes: 10 additions & 0 deletions module/Core/test/Config/EnvVarsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@ protected function setUp(): void
{
putenv(EnvVars::BASE_PATH->value . '=the_base_path');
putenv(EnvVars::DB_NAME->value . '=shlink');

$envFilePath = __DIR__ . '/../DB_PASSWORD.env';
putenv(EnvVars::DB_PASSWORD->value . '_FILE=' . $envFilePath);
}

protected function tearDown(): void
{
putenv(EnvVars::BASE_PATH->value . '=');
putenv(EnvVars::DB_NAME->value . '=');
putenv(EnvVars::DB_PASSWORD->value . '_FILE=');
}

#[Test, DataProvider('provideExistingEnvVars')]
Expand Down Expand Up @@ -54,4 +58,10 @@ public static function provideEnvVarsValues(): iterable
yield 'DB_DRIVER without default' => [EnvVars::DB_DRIVER, null, null];
yield 'DB_DRIVER with default' => [EnvVars::DB_DRIVER, 'foobar', 'foobar'];
}

#[Test]
public function fallsBackToReadEnvVarsFromFile(): void
{
self::assertEquals('this_is_the_password', EnvVars::DB_PASSWORD->loadFromEnv());
}
}
1 change: 1 addition & 0 deletions module/Core/test/DB_PASSWORD.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
this_is_the_password

0 comments on commit 17792a1

Please sign in to comment.