Add more accommodations for standalone mode.

This commit is contained in:
Buster "Silver Eagle" Neece 2021-06-23 03:33:22 -05:00
parent f9221fb335
commit 825a122cb9
No known key found for this signature in database
GPG Key ID: 6D9E12FF03411F4E
13 changed files with 107 additions and 61 deletions

View File

@ -119,13 +119,13 @@ jobs :
cp docker-compose.testing.yml docker-compose.override.yml
docker-compose build web
docker-compose run --rm --user="azuracast" web azuracast_install
docker-compose up -d
- name : Run functional test suite.
run : |
chmod 777 tests/_output/
chmod 777 tests/_support/_generated
docker-compose run --rm --user="azuracast" web composer codeception-no-coverage
docker-compose exec --user="azuracast" web composer codeception-no-coverage
- name : Stop all running containers.
run : |

View File

@ -128,7 +128,7 @@
"@codeception-no-coverage"
],
"phplint": "parallel-lint . --exclude vendor",
"phpstan": "phpstan analyze",
"phpstan": "phpstan analyze --memory-limit=-1",
"phpcs": "phpcs",
"phpcbf": "phpcbf",
"codeception": "codecept run --no-interaction --coverage --coverage-xml --fail-fast",

View File

@ -430,20 +430,19 @@ return [
// Supervisor manager
Supervisor\Supervisor::class => function (Environment $settings, Psr\Log\LoggerInterface $logger) {
$host = (!$settings->isDocker() || $settings->isDockerStandaloneMode())
? '127.0.0.1'
: 'stations';
$client = new fXmlRpc\Client(
'http://' . ($settings->isDocker() ? 'stations' : '127.0.0.1') . ':9001/RPC2',
'http://' . $host . ':9001/RPC2',
new fXmlRpc\Transport\PsrTransport(
new Http\Factory\Guzzle\RequestFactory,
new GuzzleHttp\Client
)
);
$supervisor = new Supervisor\Supervisor($client, $logger);
if (!$supervisor->isConnected()) {
throw new \App\Exception(sprintf('Could not connect to supervisord.'));
}
return $supervisor;
return new Supervisor\Supervisor($client, $logger);
},
// Image Manager

View File

@ -2,16 +2,41 @@
namespace App\Console\Command;
use App\Entity\Repository\SettingsRepository;
use Doctrine\ORM\EntityManagerInterface;
use Redis;
use Symfony\Component\Console\Style\SymfonyStyle;
class ClearCacheCommand extends CommandAbstract
{
public function __invoke(SymfonyStyle $io, Redis $redis): int
{
public function __invoke(
SymfonyStyle $io,
Redis $redis,
EntityManagerInterface $em,
SettingsRepository $settingsRepo,
): int {
// Flush all Redis entries.
$redis->flushAll();
// Clear "Now Playing" cache on all station rows.
$em->createQuery(
<<<'DQL'
UPDATE App\Entity\Station s SET s.nowplaying=null
DQL
)->execute();
// Clear cached system settings.
$settings = $settingsRepo->readSettings();
$settings->setNowplaying(null);
$settings->updateUpdateLastRun();
$settings->setUpdateResults(null);
if ('127.0.0.1' !== $settings->getExternalIp()) {
$settings->setExternalIp(null);
}
$settingsRepo->writeSettings($settings);
$io->success('Local cache flushed.');
return 0;
}

View File

@ -4,7 +4,6 @@ namespace App\Console\Command;
use App\Entity;
use App\Environment;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
@ -14,9 +13,6 @@ class InitializeCommand extends CommandAbstract
SymfonyStyle $io,
OutputInterface $output,
Environment $environment,
ContainerInterface $di,
Entity\Repository\SettingsRepository $settingsRepo,
Entity\Repository\StationRepository $stationRepo,
Entity\Repository\StorageLocationRepository $storageLocationRepo
): int {
$io->title(__('Initialize AzuraCast'));
@ -51,20 +47,7 @@ class InitializeCommand extends CommandAbstract
$this->runCommand($output, 'cache:clear');
$this->runCommand($output, 'queue:clear');
$stationRepo->clearNowPlaying();
// Clear settings that should be reset upon update.
$settings = $settingsRepo->readSettings();
$settings->setNowplaying(null);
$settings->updateUpdateLastRun();
$settings->setUpdateResults(null);
if ('127.0.0.1' !== $settings->getExternalIp()) {
$settings->setExternalIp(null);
}
$settingsRepo->writeSettings($settings);
// Ensure default storage locations exist.
$storageLocationRepo->createDefaultStorageLocations();
$io->newLine();

View File

@ -2,6 +2,7 @@
namespace App\Console\Command;
use App\Entity\Repository\SettingsRepository;
use App\Environment;
use App\Service\AzuraCastCentral;
use Psr\Container\ContainerInterface;
@ -16,6 +17,7 @@ class SetupCommand extends CommandAbstract
Environment $environment,
ContainerInterface $di,
AzuraCastCentral $acCentral,
SettingsRepository $settingsRepo,
bool $update = false,
bool $loadFixtures = false
): int {
@ -38,6 +40,11 @@ class SetupCommand extends CommandAbstract
$io->newLine();
// Update system setting logging when updates were last run.
$settings = $settingsRepo->readSettings();
$settings->updateUpdateLastRun();
$settingsRepo->writeSettings($settings);
if ($update) {
$io->success(
[

View File

@ -235,18 +235,6 @@ class StationRepository extends Repository
$this->em->flush();
}
/**
* Clear the now-playing cache from all stations.
*/
public function clearNowPlaying(): void
{
$this->em->createQuery(
<<<'DQL'
UPDATE App\Entity\Station s SET s.nowplaying=null
DQL
)->execute();
}
/**
* Return the URL to use for songs with no specified album artwork, when artwork is displayed.
*

View File

@ -31,6 +31,7 @@ class Environment
public const ASSET_URL = 'ASSETS_URL';
public const DOCKER_STANDALONE_MODE = 'AZURACAST_DOCKER_STANDALONE_MODE';
public const DOCKER_REVISION = 'AZURACAST_DC_REVISION';
public const LANG = 'LANG';
@ -98,6 +99,17 @@ class Environment
$this->data = array_merge($this->defaults, $elements);
}
protected function envToBool(string|bool $value): bool
{
if (is_bool($value)) {
return $value;
}
return str_starts_with(strtolower($value), 'y')
|| 'true' === strtolower($value)
|| '1' === $value;
}
public function getAppEnvironment(): string
{
return $this->data[self::APP_ENV] ?? self::ENV_PRODUCTION;
@ -120,7 +132,22 @@ class Environment
public function isDocker(): bool
{
return (bool)($this->data[self::IS_DOCKER] ?? true);
return $this->envToBool($this->data[self::IS_DOCKER] ?? true);
}
public function isDockerStandaloneMode(): bool
{
return $this->envToBool($this->data[self::DOCKER_STANDALONE_MODE] ?? false);
}
public function isDockerRevisionAtLeast(int $version): bool
{
if (!$this->isDocker()) {
return false;
}
$compareVersion = (int)($this->data[self::DOCKER_REVISION] ?? 0);
return ($compareVersion >= $version);
}
public function isCli(): bool
@ -186,16 +213,6 @@ class Environment
return $this->getParentDirectory() . '/stations';
}
public function isDockerRevisionAtLeast(int $version): bool
{
if (!$this->isDocker()) {
return false;
}
$compareVersion = (int)($this->data[self::DOCKER_REVISION] ?? 0);
return ($compareVersion >= $version);
}
public function getLang(): ?string
{
return $this->data[self::LANG];
@ -297,12 +314,12 @@ class Environment
public function isProfilingExtensionEnabled(): bool
{
return (1 === (int)($this->data[self::PROFILING_EXTENSION_ENABLED] ?? 0));
return $this->envToBool($this->data[self::PROFILING_EXTENSION_ENABLED] ?? false);
}
public function isProfilingExtensionAlwaysOn(): bool
{
return (1 === (int)($this->data[self::PROFILING_EXTENSION_ALWAYS_ON] ?? 0));
return $this->envToBool($this->data[self::PROFILING_EXTENSION_ALWAYS_ON] ?? false);
}
public function getProfilingExtensionHttpKey(): string

View File

@ -34,7 +34,10 @@ class Icecast extends AbstractFrontend
$radioPort = $feConfig->getPort();
/** @noinspection HttpUrlsUsage */
$baseUrl = 'http://' . ($this->environment->isDocker() ? 'stations' : 'localhost') . ':' . $radioPort;
$baseUrlHost = (!$this->environment->isDocker() || $this->environment->isDockerStandaloneMode())
? 'localhost'
: 'stations';
$baseUrl = 'http://' . $baseUrlHost . ':' . $radioPort;
$npAdapter = $this->adapterFactory->getIcecastAdapter($baseUrl);

View File

@ -61,7 +61,10 @@ class SHOUTcast extends AbstractFrontend
$radioPort = $feConfig->getPort();
/** @noinspection HttpUrlsUsage */
$baseUrl = 'http://' . ($this->environment->isDocker() ? 'stations' : 'localhost') . ':' . $radioPort;
$baseUrlHost = (!$this->environment->isDocker() || $this->environment->isDockerStandaloneMode())
? 'localhost'
: 'stations';
$baseUrl = 'http://' . $baseUrlHost . ':' . $radioPort;
$npAdapter = $this->adapterFactory->getShoutcast2Adapter($baseUrl);
$npAdapter->setAdminPassword($feConfig->getAdminPassword());

View File

@ -132,19 +132,25 @@ server {
proxy_read_timeout 21600;
proxy_set_header Host localhost:$1;
{{if eq .Env.STANDALONE "1"}}
proxy_pass http://127.0.0.1:$1/$3?$args;
{{else}}
proxy_pass http://stations:$1/$3?$args;
{{end}}
}
# Reverse proxy the Liquidsoap harbor inputs to allow for streaming.
location ~ ^/radio/(8[0-9][0-9]5)(/?)(.*)$ {
resolver 127.0.0.11;
proxy_buffering off;
proxy_ignore_client_abort off;
proxy_send_timeout 21600;
proxy_read_timeout 21600;
{{if eq .Env.STANDALONE "1"}}
proxy_pass http://127.0.0.1:$1/$3;
{{else}}
proxy_pass http://stations:$1/$3;
{{end}}
}
# pub/sub endpoints

View File

@ -1,4 +1,19 @@
#!/bin/bash
bool() {
case "$1" in
Y* | y* | true | TRUE | 1) return 0 ;;
esac
return 1
}
STANDALONE_MODE=${AZURACAST_DOCKER_STANDALONE_MODE:-0}
if bool "$STANDALONE_MODE"; then
STANDALONE=1
else
STANDALONE=0
fi
# Copy the nginx template to its destination.
dockerize -template "/etc/nginx/azuracast.conf.tmpl:/etc/nginx/conf.d/azuracast.conf"
STANDALONE=${STANDALONE} dockerize -template "/etc/nginx/azuracast.conf.tmpl:/etc/nginx/conf.d/azuracast.conf"

View File

@ -12,7 +12,7 @@ STANDALONE_MODE=${AZURACAST_DOCKER_STANDALONE_MODE:-0}
if bool "$STANDALONE_MODE"; then
echo "Running in standalone mode; enabling optional services..."
cp /etc/service_standalone/. /etc/service/
cp -R /etc/service_standalone/. /etc/service/
else
echo "Not running in standalone mode; skipping optional services."
fi