2021-11-30 11:20:42 +01:00
< ? php
namespace AIO\Docker ;
use AIO\Container\Container ;
use AIO\Container\State\IContainerState ;
use AIO\Container\State\ImageDoesNotExistState ;
use AIO\Container\State\StartingState ;
use AIO\Container\State\RunningState ;
2022-03-15 12:45:31 +01:00
use AIO\Container\State\RestartingState ;
use AIO\Container\State\NotRestartingState ;
2021-11-30 11:20:42 +01:00
use AIO\Container\State\VersionDifferentState ;
use AIO\Container\State\StoppedState ;
use AIO\Container\State\VersionEqualState ;
use AIO\Data\ConfigurationManager ;
2022-01-20 13:30:39 +01:00
use GuzzleHttp\Exception\RequestException ;
2021-11-30 11:20:42 +01:00
use AIO\ContainerDefinitionFetcher ;
use http\Env\Response ;
class DockerActionManager
{
private const API_VERSION = 'v1.41' ;
private \GuzzleHttp\Client $guzzleClient ;
private ConfigurationManager $configurationManager ;
private ContainerDefinitionFetcher $containerDefinitionFetcher ;
private DockerHubManager $dockerHubManager ;
public function __construct (
ConfigurationManager $configurationManager ,
ContainerDefinitionFetcher $containerDefinitionFetcher ,
DockerHubManager $dockerHubManager
) {
$this -> configurationManager = $configurationManager ;
$this -> containerDefinitionFetcher = $containerDefinitionFetcher ;
$this -> dockerHubManager = $dockerHubManager ;
$this -> guzzleClient = new \GuzzleHttp\Client (
[
'curl' => [
CURLOPT_UNIX_SOCKET_PATH => '/var/run/docker.sock' ,
],
]
);
}
private function BuildApiUrl ( string $url ) : string {
return sprintf ( 'http://localhost/%s/%s' , self :: API_VERSION , $url );
}
private function BuildImageName ( Container $container ) : string {
2021-12-05 14:03:05 +01:00
return $container -> GetContainerName () . ':' . $this -> GetCurrentChannel ();
2021-11-30 11:20:42 +01:00
}
public function GetContainerRunningState ( Container $container ) : IContainerState
{
$url = $this -> BuildApiUrl ( sprintf ( 'containers/%s/json' , urlencode ( $container -> GetIdentifier ())));
try {
$response = $this -> guzzleClient -> get ( $url );
2022-01-20 13:30:39 +01:00
} catch ( RequestException $e ) {
if ( $e -> getCode () === 404 ) {
2021-11-30 11:20:42 +01:00
return new ImageDoesNotExistState ();
}
2022-01-20 13:30:39 +01:00
throw $e ;
2021-11-30 11:20:42 +01:00
}
$responseBody = json_decode (( string ) $response -> getBody (), true );
if ( $responseBody [ 'State' ][ 'Running' ] === true ) {
return new RunningState ();
} else {
return new StoppedState ();
}
}
2022-03-15 12:45:31 +01:00
public function GetContainerRestartingState ( Container $container ) : IContainerState
{
$url = $this -> BuildApiUrl ( sprintf ( 'containers/%s/json' , urlencode ( $container -> GetIdentifier ())));
try {
$response = $this -> guzzleClient -> get ( $url );
} catch ( RequestException $e ) {
if ( $e -> getCode () === 404 ) {
return new ImageDoesNotExistState ();
}
throw $e ;
}
$responseBody = json_decode (( string ) $response -> getBody (), true );
if ( $responseBody [ 'State' ][ 'Restarting' ] === true ) {
return new RestartingState ();
} else {
return new NotRestartingState ();
}
}
2021-11-30 11:20:42 +01:00
public function GetContainerUpdateState ( Container $container ) : IContainerState
{
2021-12-05 14:03:05 +01:00
$tag = $this -> GetCurrentChannel ();
2021-11-30 11:20:42 +01:00
2022-04-17 13:07:29 +02:00
$runningDigests = $this -> GetRepoDigestsOfContainer ( $container -> GetIdentifier ());
if ( $runningDigests === null ) {
return new VersionDifferentState ();
}
2021-11-30 11:20:42 +01:00
$remoteDigest = $this -> dockerHubManager -> GetLatestDigestOfTag ( $container -> GetContainerName (), $tag );
2022-04-17 13:07:29 +02:00
if ( $remoteDigest === null ) {
return new VersionEqualstate ();
}
2021-11-30 11:20:42 +01:00
2022-04-17 13:07:29 +02:00
foreach ( $runningDigests as $runningDigest ) {
if ( $runningDigest === $remoteDigest ) {
return new VersionEqualState ();
}
2021-11-30 11:20:42 +01:00
}
2022-04-17 13:07:29 +02:00
return new VersionDifferentState ();
2021-11-30 11:20:42 +01:00
}
public function GetContainerStartingState ( Container $container ) : IContainerState
{
$runningState = $this -> GetContainerRunningState ( $container );
if ( $runningState instanceof StoppedState ) {
return new StoppedState ();
} elseif ( $runningState instanceof ImageDoesNotExistState ) {
return new ImageDoesNotExistState ();
}
$containerName = $container -> GetIdentifier ();
if ( $container -> GetInternalPorts () !== null ) {
foreach ( $container -> GetInternalPorts () -> GetInternalPorts () as $internalPort ) {
$connection = @ fsockopen ( $containerName , $internalPort , $errno , $errstr , 0.1 );
if ( $connection ) {
fclose ( $connection );
return new RunningState ();
} else {
return new StartingState ();
}
}
} else {
return new RunningState ();
}
}
2022-03-01 11:44:59 +01:00
public function DeleteContainer ( Container $container ) : void {
2022-01-14 19:02:03 +01:00
$url = $this -> BuildApiUrl ( sprintf ( 'containers/%s?v=true' , urlencode ( $container -> GetIdentifier ())));
2021-11-30 11:20:42 +01:00
try {
$this -> guzzleClient -> delete ( $url );
2022-01-20 13:30:39 +01:00
} catch ( RequestException $e ) {
2022-01-01 16:01:31 +01:00
if ( $e -> getCode () !== 404 ) {
throw $e ;
}
}
2021-11-30 11:20:42 +01:00
}
2022-03-09 16:50:53 +01:00
public function GetLogs ( string $id ) : string
2021-11-30 11:20:42 +01:00
{
$url = $this -> BuildApiUrl (
sprintf (
'containers/%s/logs?stdout=true&stderr=true' ,
2022-03-09 16:50:53 +01:00
urlencode ( $id )
2021-11-30 11:20:42 +01:00
));
$responseBody = ( string ) $this -> guzzleClient -> get ( $url ) -> getBody ();
$response = " " ;
$separator = " \r \n " ;
$line = strtok ( $responseBody , $separator );
$response = substr ( $line , 8 ) . " \n " ;
while ( $line !== false ) {
$line = strtok ( $separator );
$response .= substr ( $line , 8 ) . " \n " ;
}
return $response ;
}
2022-03-01 11:44:59 +01:00
public function StartContainer ( Container $container ) : void {
2021-11-30 11:20:42 +01:00
$url = $this -> BuildApiUrl ( sprintf ( 'containers/%s/start' , urlencode ( $container -> GetIdentifier ())));
$this -> guzzleClient -> post ( $url );
}
2022-03-01 11:44:59 +01:00
public function CreateVolumes ( Container $container ) : void
2021-11-30 11:20:42 +01:00
{
$url = $this -> BuildApiUrl ( 'volumes/create' );
foreach ( $container -> GetVolumes () -> GetVolumes () as $volume ) {
$forbiddenChars = [
'/' ,
];
2022-05-23 17:19:23 +02:00
if ( $volume -> name === 'nextcloud_aio_nextcloud_datadir' || $volume -> name === 'nextcloud_aio_backupdir' ) {
return ;
}
2021-11-30 11:20:42 +01:00
$firstChar = substr ( $volume -> name , 0 , 1 );
2022-05-23 16:41:00 +02:00
if ( ! in_array ( $firstChar , $forbiddenChars )) {
2021-11-30 11:20:42 +01:00
$this -> guzzleClient -> request (
'POST' ,
$url ,
[
'json' => [
2022-05-23 16:41:00 +02:00
'name' => $volume -> name ,
2021-11-30 11:20:42 +01:00
],
]
);
}
}
}
2022-03-01 11:44:59 +01:00
public function CreateContainer ( Container $container ) : void {
2021-11-30 11:20:42 +01:00
$volumes = [];
foreach ( $container -> GetVolumes () -> GetVolumes () as $volume ) {
$volumeEntry = $volume -> name . ':' . $volume -> mountPoint ;
2022-05-23 16:41:00 +02:00
if ( $volume -> isWritable ) {
2021-11-30 11:20:42 +01:00
$volumeEntry = $volumeEntry . ':' . 'rw' ;
} else {
$volumeEntry = $volumeEntry . ':' . 'ro' ;
}
$volumes [] = $volumeEntry ;
}
$exposedPorts = [];
foreach ( $container -> GetPorts () -> GetPorts () as $port ) {
$exposedPorts [ $port ] = null ;
}
$requestBody = [
'Image' => $this -> BuildImageName ( $container ),
];
if ( count ( $volumes ) > 0 ) {
$requestBody [ 'HostConfig' ][ 'Binds' ] = $volumes ;
}
$envs = $container -> GetEnvironmentVariables () -> GetVariables ();
foreach ( $envs as $key => $env ) {
$patterns = [ '/%(.*)%/' ];
if ( preg_match ( $patterns [ 0 ], $env , $out ) === 1 ) {
$replacements = array ();
if ( $out [ 1 ] === 'NC_DOMAIN' ) {
$replacements [ 1 ] = $this -> configurationManager -> GetDomain ();
} elseif ( $out [ 1 ] === 'AIO_TOKEN' ) {
$replacements [ 1 ] = $this -> configurationManager -> GetToken ();
} elseif ( $out [ 1 ] === 'BORGBACKUP_MODE' ) {
$replacements [ 1 ] = $this -> configurationManager -> GetBackupMode ();
} elseif ( $out [ 1 ] === 'AIO_URL' ) {
$replacements [ 1 ] = $this -> configurationManager -> GetAIOURL ();
2021-12-07 19:10:05 +01:00
} elseif ( $out [ 1 ] === 'SELECTED_RESTORE_TIME' ) {
$replacements [ 1 ] = $this -> configurationManager -> GetSelectedRestoreTime ();
2021-12-08 18:12:56 +01:00
} elseif ( $out [ 1 ] === 'APACHE_PORT' ) {
$replacements [ 1 ] = $this -> configurationManager -> GetApachePort ();
2022-06-07 00:43:48 +02:00
} elseif ( $out [ 1 ] === 'TALK_PORT' ) {
$replacements [ 1 ] = $this -> configurationManager -> GetTalkPort ();
2022-03-14 15:35:37 +01:00
} elseif ( $out [ 1 ] === 'NEXTCLOUD_MOUNT' ) {
$replacements [ 1 ] = $this -> configurationManager -> GetNextcloudMount ();
2022-03-21 13:23:17 +01:00
} elseif ( $out [ 1 ] === 'BACKUP_RESTORE_PASSWORD' ) {
$replacements [ 1 ] = $this -> configurationManager -> GetBorgRestorePassword ();
2022-03-15 23:46:58 +01:00
} elseif ( $out [ 1 ] === 'CLAMAV_ENABLED' ) {
if ( $this -> configurationManager -> isClamavEnabled ()) {
$replacements [ 1 ] = 'yes' ;
} else {
$replacements [ 1 ] = '' ;
}
2022-03-17 10:13:21 +01:00
} elseif ( $out [ 1 ] === 'ONLYOFFICE_ENABLED' ) {
if ( $this -> configurationManager -> isOnlyofficeEnabled ()) {
$replacements [ 1 ] = 'yes' ;
} else {
$replacements [ 1 ] = '' ;
}
} elseif ( $out [ 1 ] === 'COLLABORA_ENABLED' ) {
if ( $this -> configurationManager -> isCollaboraEnabled ()) {
$replacements [ 1 ] = 'yes' ;
} else {
$replacements [ 1 ] = '' ;
}
} elseif ( $out [ 1 ] === 'TALK_ENABLED' ) {
if ( $this -> configurationManager -> isTalkEnabled ()) {
$replacements [ 1 ] = 'yes' ;
} else {
$replacements [ 1 ] = '' ;
}
2022-04-04 19:12:07 +02:00
} elseif ( $out [ 1 ] === 'DAILY_BACKUP_RUNNING' ) {
if ( $this -> configurationManager -> isDailyBackupRunning ()) {
$replacements [ 1 ] = 'yes' ;
} else {
$replacements [ 1 ] = '' ;
}
2022-05-18 18:36:51 +02:00
} elseif ( $out [ 1 ] === 'TIMEZONE' ) {
2022-05-26 01:57:31 +02:00
if ( $this -> configurationManager -> GetTimezone () === '' ) {
$replacements [ 1 ] = 'UTC' ;
} else {
$replacements [ 1 ] = $this -> configurationManager -> GetTimezone ();
}
2021-11-30 11:20:42 +01:00
} else {
$replacements [ 1 ] = $this -> configurationManager -> GetSecret ( $out [ 1 ]);
}
$envs [ $key ] = preg_replace ( $patterns , $replacements , $env );
}
}
if ( count ( $envs ) > 0 ) {
$requestBody [ 'Env' ] = $envs ;
}
$requestBody [ 'HostConfig' ][ 'RestartPolicy' ][ 'Name' ] = $container -> GetRestartPolicy ();
if ( count ( $exposedPorts ) > 0 ) {
$requestBody [ 'ExposedPorts' ] = $exposedPorts ;
foreach ( $container -> GetPorts () -> GetPorts () as $port ) {
$portNumber = explode ( " / " , $port );
$requestBody [ 'HostConfig' ][ 'PortBindings' ][ $port ] = [
[
'HostPort' => $portNumber [ 0 ],
]
];
}
}
// Special things for the backup container which should not be exposed in the containers.json
if ( $container -> GetIdentifier () === 'nextcloud-aio-borgbackup' ) {
$requestBody [ 'HostConfig' ][ 'CapAdd' ] = [ " SYS_ADMIN " ];
$requestBody [ 'HostConfig' ][ 'Devices' ] = [[ " PathOnHost " => " /dev/fuse " , " PathInContainer " => " /dev/fuse " , " CgroupPermissions " => " rwm " ]];
$requestBody [ 'HostConfig' ][ 'SecurityOpt' ] = [ " apparmor:unconfined " ];
}
$url = $this -> BuildApiUrl ( 'containers/create?name=' . $container -> GetIdentifier ());
2022-03-09 18:25:03 +01:00
try {
$this -> guzzleClient -> request (
'POST' ,
$url ,
[
'json' => $requestBody
]
);
} catch ( RequestException $e ) {
throw $e ;
}
2021-11-30 11:20:42 +01:00
}
2022-03-01 11:44:59 +01:00
public function PullContainer ( Container $container ) : void
2021-11-30 11:20:42 +01:00
{
2022-03-09 16:37:31 +01:00
$url = $this -> BuildApiUrl ( sprintf ( 'images/create?fromImage=%s' , urlencode ( $this -> BuildImageName ( $container ))));
try {
$this -> guzzleClient -> post ( $url );
} catch ( RequestException $e ) {
2022-03-14 17:20:45 +01:00
error_log ( 'Could not get image ' . $this -> BuildImageName ( $container ) . ' from docker hub. Probably due to rate limits. ' . $e -> getMessage ());
2022-03-09 16:37:31 +01:00
// Don't exit here because it is possible that the image is already present
// and we ran into docker hub limits.
// We will exit later if not image should be available.
2021-11-30 11:20:42 +01:00
}
}
private function isContainerUpdateAvailable ( string $id ) : string
{
$container = $this -> containerDefinitionFetcher -> GetContainerById ( $id );
$updateAvailable = " " ;
if ( $container -> GetUpdateState () instanceof VersionDifferentState ) {
$updateAvailable = '1' ;
}
foreach ( $container -> GetDependsOn () as $dependency ) {
$updateAvailable .= $this -> isContainerUpdateAvailable ( $dependency );
}
return $updateAvailable ;
}
2022-03-01 11:44:59 +01:00
public function isAnyUpdateAvailable () : bool {
2021-11-30 11:20:42 +01:00
$id = 'nextcloud-aio-apache' ;
if ( $this -> isContainerUpdateAvailable ( $id ) !== " " ) {
return true ;
} else {
return false ;
}
}
2022-04-17 13:07:29 +02:00
private function GetRepoDigestsOfContainer ( string $containerName ) : ? array {
2021-11-30 11:20:42 +01:00
try {
$containerUrl = $this -> BuildApiUrl ( sprintf ( 'containers/%s/json' , $containerName ));
$containerOutput = json_decode ( $this -> guzzleClient -> get ( $containerUrl ) -> getBody () -> getContents (), true );
$imageName = $containerOutput [ 'Image' ];
$imageUrl = $this -> BuildApiUrl ( sprintf ( 'images/%s/json' , $imageName ));
$imageOutput = json_decode ( $this -> guzzleClient -> get ( $imageUrl ) -> getBody () -> getContents (), true );
2022-04-17 13:07:29 +02:00
if ( ! isset ( $imageOutput [ 'RepoDigests' ])) {
error_log ( 'RepoDigests is not set of container ' . $containerName );
return null ;
}
2021-11-30 11:20:42 +01:00
2022-04-17 13:07:29 +02:00
if ( ! is_array ( $imageOutput [ 'RepoDigests' ])) {
error_log ( 'RepoDigests of ' . $containerName . ' is not an array which is not allowed!' );
return null ;
}
$repoDigestArray = [];
$oneDigestGiven = false ;
foreach ( $imageOutput [ 'RepoDigests' ] as $repoDigest ) {
$digestPosition = strpos ( $repoDigest , '@' );
if ( $digestPosition === false ) {
error_log ( 'Somehow the RepoDigest of ' . $containerName . ' does not contain a @.' );
return null ;
}
$repoDigestArray [] = substr ( $repoDigest , $digestPosition + 1 );
$oneDigestGiven = true ;
}
if ( $oneDigestGiven ) {
return $repoDigestArray ;
2021-11-30 11:20:42 +01:00
}
return null ;
} catch ( \Exception $e ) {
return null ;
}
}
public function GetCurrentChannel () : string {
$cacheKey = 'aio-ChannelName' ;
$channelName = apcu_fetch ( $cacheKey );
if ( $channelName !== false && is_string ( $channelName )) {
return $channelName ;
}
$containerName = 'nextcloud-aio-mastercontainer' ;
$url = $this -> BuildApiUrl ( sprintf ( 'containers/%s/json' , $containerName ));
try {
$output = json_decode ( $this -> guzzleClient -> get ( $url ) -> getBody () -> getContents (), true );
$containerChecksum = $output [ 'Image' ];
$tagArray = explode ( ':' , $output [ 'Config' ][ 'Image' ]);
$tag = $tagArray [ 1 ];
apcu_add ( $cacheKey , $tag );
2022-06-11 14:52:49 +02:00
/**
* @ psalm - suppress TypeDoesNotContainNull
*/
2022-06-11 14:45:46 +02:00
if ( $tag === null ) {
error_log ( " No tag was found when getting the current channel. You probably did not follow the documentation correctly. Changing the channel to the default 'latest'. " );
$tag = 'latest' ;
}
2021-11-30 11:20:42 +01:00
return $tag ;
2022-01-20 13:30:39 +01:00
} catch ( \Exception $e ) {
2022-03-09 18:25:03 +01:00
error_log ( 'Could not get current channel ' . $e -> getMessage ());
2021-11-30 11:20:42 +01:00
}
return 'latest' ;
}
public function IsMastercontainerUpdateAvailable () : bool
{
$imageName = 'nextcloud/all-in-one' ;
$containerName = 'nextcloud-aio-mastercontainer' ;
2021-12-05 14:03:05 +01:00
$tag = $this -> GetCurrentChannel ();
2021-11-30 11:20:42 +01:00
2022-04-17 13:07:29 +02:00
$runningDigests = $this -> GetRepoDigestsOfContainer ( $containerName );
if ( $runningDigests === null ) {
return true ;
}
2021-11-30 11:20:42 +01:00
$remoteDigest = $this -> dockerHubManager -> GetLatestDigestOfTag ( $imageName , $tag );
2022-04-17 13:07:29 +02:00
if ( $remoteDigest === null ) {
2021-11-30 11:20:42 +01:00
return false ;
}
2022-04-17 13:07:29 +02:00
foreach ( $runningDigests as $runningDigest ) {
if ( $remoteDigest === $runningDigest ) {
return false ;
}
}
return true ;
2021-11-30 11:20:42 +01:00
}
2022-03-01 11:44:59 +01:00
public function sendNotification ( Container $container , string $subject , string $message ) : void
2021-11-30 13:11:19 +01:00
{
if ( $this -> GetContainerStartingState ( $container ) instanceof RunningState ) {
$containerName = $container -> GetIdentifier ();
// schedule the exec
2021-11-30 14:25:10 +01:00
$url = $this -> BuildApiUrl ( sprintf ( 'containers/%s/exec' , urlencode ( $containerName )));
2021-11-30 13:11:19 +01:00
$response = json_decode (
$this -> guzzleClient -> request (
'POST' ,
$url ,
[
'json' => [
'AttachStdout' => true ,
'Tty' => true ,
'Cmd' => [
'bash' ,
'/notify.sh' ,
$subject ,
$message
],
],
]
2021-11-30 14:25:10 +01:00
) -> getBody () -> getContents (),
true
2021-11-30 13:11:19 +01:00
);
// get the id from the response
$id = $response [ 'Id' ];
// start the exec
2021-11-30 14:25:10 +01:00
$url = $this -> BuildApiUrl ( sprintf ( 'exec/%s/start' , $id ));
2021-11-30 13:11:19 +01:00
$this -> guzzleClient -> request (
'POST' ,
$url ,
[
'json' => [
'Detach' => false ,
'Tty' => true ,
],
]
);
}
}
2022-03-01 11:44:59 +01:00
public function DisconnectContainerFromNetwork ( Container $container ) : void
2021-11-30 11:20:42 +01:00
{
$url = $this -> BuildApiUrl (
sprintf ( 'networks/%s/disconnect' , 'nextcloud-aio' )
);
try {
$this -> guzzleClient -> request (
'POST' ,
$url ,
[
'json' => [
'container' => $container -> GetIdentifier (),
],
]
);
2022-01-20 13:30:39 +01:00
} catch ( RequestException $e ) {
2022-03-09 18:25:03 +01:00
error_log ( 'Could not disconnect container from network ' . $e -> getMessage ());
2022-01-20 13:30:39 +01:00
}
2021-11-30 11:20:42 +01:00
}
2022-03-01 11:44:59 +01:00
private function ConnectContainerIdToNetwork ( string $id ) : void
2021-11-30 11:20:42 +01:00
{
$url = $this -> BuildApiUrl ( 'networks/create' );
try {
$this -> guzzleClient -> request (
'POST' ,
$url ,
[
'json' => [
2022-05-20 16:10:57 +02:00
'Name' => 'nextcloud-aio' ,
'CheckDuplicate' => true ,
'Driver' => 'bridge' ,
2022-05-24 18:50:57 +02:00
'Internal' => false ,
2022-05-20 16:10:57 +02:00
'Options' => [
'com.docker.network.bridge.enable_icc' => 'true'
]
2021-11-30 11:20:42 +01:00
]
]
);
2022-01-20 13:30:39 +01:00
} catch ( RequestException $e ) {
2022-01-21 14:25:29 +01:00
// 409 is undocumented and gets thrown if the network already exists.
if ( $e -> getCode () !== 409 ) {
throw $e ;
}
2021-11-30 11:20:42 +01:00
}
$url = $this -> BuildApiUrl (
sprintf ( 'networks/%s/connect' , 'nextcloud-aio' )
);
try {
$this -> guzzleClient -> request (
'POST' ,
$url ,
[
'json' => [
'container' => $id ,
]
]
);
2022-01-20 13:30:39 +01:00
} catch ( RequestException $e ) {
2022-01-21 14:36:43 +01:00
// 403 is undocumented and gets thrown if a specific container is already part of a network
if ( $e -> getCode () !== 403 ) {
throw $e ;
}
2021-11-30 11:20:42 +01:00
}
}
2022-03-01 11:44:59 +01:00
public function ConnectMasterContainerToNetwork () : void
2021-11-30 11:20:42 +01:00
{
$this -> ConnectContainerIdToNetwork ( 'nextcloud-aio-mastercontainer' );
}
2022-03-01 11:44:59 +01:00
public function ConnectContainerToNetwork ( Container $container ) : void
2021-11-30 11:20:42 +01:00
{
$this -> ConnectContainerIdToNetwork ( $container -> GetIdentifier ());
}
2022-03-01 11:44:59 +01:00
public function StopContainer ( Container $container ) : void {
2021-11-30 11:20:42 +01:00
$url = $this -> BuildApiUrl ( sprintf ( 'containers/%s/stop?t=%s' , urlencode ( $container -> GetIdentifier ()), $container -> GetMaxShutdownTime ()));
2022-01-01 16:01:31 +01:00
try {
$this -> guzzleClient -> post ( $url );
2022-01-20 13:30:39 +01:00
} catch ( RequestException $e ) {
2022-01-10 18:27:20 +01:00
if ( $e -> getCode () !== 404 && $e -> getCode () !== 304 ) {
throw $e ;
}
}
2021-11-30 11:20:42 +01:00
}
public function GetBackupcontainerExitCode () : int
{
$containerName = 'nextcloud-aio-borgbackup' ;
$url = $this -> BuildApiUrl ( sprintf ( 'containers/%s/json' , urlencode ( $containerName )));
try {
$response = $this -> guzzleClient -> get ( $url );
2022-01-20 13:30:39 +01:00
} catch ( RequestException $e ) {
if ( $e -> getCode () === 404 ) {
2021-11-30 11:20:42 +01:00
return - 1 ;
}
2022-01-20 13:30:39 +01:00
throw $e ;
2021-11-30 11:20:42 +01:00
}
$responseBody = json_decode (( string ) $response -> getBody (), true );
$exitCode = $responseBody [ 'State' ][ 'ExitCode' ];
if ( is_int ( $exitCode )) {
return $exitCode ;
} else {
return - 1 ;
}
}
2021-12-30 14:57:49 +01:00
2022-03-04 15:36:08 +01:00
public function GetDatabasecontainerExitCode () : int
{
$containerName = 'nextcloud-aio-database' ;
$url = $this -> BuildApiUrl ( sprintf ( 'containers/%s/json' , urlencode ( $containerName )));
try {
$response = $this -> guzzleClient -> get ( $url );
} catch ( RequestException $e ) {
if ( $e -> getCode () === 404 ) {
return - 1 ;
}
throw $e ;
}
$responseBody = json_decode (( string ) $response -> getBody (), true );
$exitCode = $responseBody [ 'State' ][ 'ExitCode' ];
if ( is_int ( $exitCode )) {
return $exitCode ;
} else {
return - 1 ;
}
}
2021-12-30 14:57:49 +01:00
public function isLoginAllowed () : bool {
$id = 'nextcloud-aio-apache' ;
$apacheContainer = $this -> containerDefinitionFetcher -> GetContainerById ( $id );
if ( $this -> GetContainerStartingState ( $apacheContainer ) instanceof RunningState ) {
return false ;
}
return true ;
}
2022-03-30 17:50:09 +02:00
public function isBackupContainerRunning () : bool {
$id = 'nextcloud-aio-borgbackup' ;
$backupContainer = $this -> containerDefinitionFetcher -> GetContainerById ( $id );
if ( $this -> GetContainerRunningState ( $backupContainer ) instanceof RunningState ) {
return true ;
}
return false ;
}
2021-11-30 11:20:42 +01:00
}