Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 47 additions & 23 deletions php/src/Controller/DockerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,23 +202,9 @@ public function StartContainer(Request $request, Response $response, array $args
error_log('WARNING: Not pulling container images. Instead, using local ones.');
}

$nonbufResp = $response
->withBody(new NonBufferedBody())
->withHeader('Content-Type', 'text/html; charset=utf-8')
->withHeader('X-Accel-Buffering', 'no')
->withHeader('Cache-Control', 'no-cache');

// Text written into this body is immediately sent to the client, without waiting for later content.
$streamingResponseBody = $nonbufResp->getBody();

$streamingResponseBody->write($this->getStreamingResponseHtmlStart());

// Create a closure to pass around to the code, which should to the logging (because it e.g. decides
// if it'll actually pull an image), but which should not need to know anything about the
// wanted markup or formatting.
$addToStreamingResponseBody = function (Container $container, string $message) use ($streamingResponseBody) : void {
$streamingResponseBody->write("<div>{$container->displayName}: {$message}</div>");
};
// Get streaming response start and closure
$nonbufResp = $this->startStreamingResponse($response);
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);

// Start container
$this->startTopContainer($pullImage, $addToStreamingResponseBody);
Expand All @@ -227,7 +213,8 @@ public function StartContainer(Request $request, Response $response, array $args
// Temporarily disabled as it leads much faster to docker rate limits
// apcu_clear_cache();

$streamingResponseBody->write($this->getStreamingResponseHtmlEnd());
// End streaming response
$this->finalizeStreamingResponse($nonbufResp);
return $nonbufResp;
}

Expand All @@ -243,14 +230,21 @@ public function startTopContainer(bool $pullImage, ?\Closure $addToStreamingResp
}

public function StartWatchtowerContainer(Request $request, Response $response, array $args) : Response {
$this->startWatchtower();
return $response->withStatus(201)->withHeader('Location', '.');
// Get streaming response start and closure
$nonbufResp = $this->startStreamingResponse($response);
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);

$this->startWatchtower($addToStreamingResponseBody);

// End streaming response
$this->finalizeStreamingResponse($nonbufResp);
return $nonbufResp;
}

public function startWatchtower() : void {
public function startWatchtower(?\Closure $addToStreamingResponseBody = null) : void {
$id = 'nextcloud-aio-watchtower';

$this->PerformRecursiveContainerStart($id);
$this->PerformRecursiveContainerStart($id, true, $addToStreamingResponseBody);
}

private function PerformRecursiveContainerStop(string $id, bool $forceStopNextcloud = false) : void
Expand Down Expand Up @@ -354,7 +348,37 @@ private function getStreamingResponseHtmlStart() : string {

END;
}


private function startStreamingResponse(Response $response) : Response {
$nonbufResp = $response
->withBody(new NonBufferedBody())
->withHeader('Content-Type', 'text/html; charset=utf-8')
->withHeader('X-Accel-Buffering', 'no')
->withHeader('Cache-Control', 'no-cache');

// Text written into this body is immediately sent to the client, without waiting for later content.
$streamingResponseBody = $nonbufResp->getBody();

$streamingResponseBody->write($this->getStreamingResponseHtmlStart());

return $nonbufResp;
}

private function getAddToStreamingResponseBody(Response $nonbufResp) : ?\Closure {
// Create a closure to pass around to the code, which should to the logging (because it e.g. decides
// if it'll actually pull an image), but which should not need to know anything about the
// wanted markup or formatting.
$addToStreamingResponseBody = function (Container $container, string $message) use ($nonbufResp) : void {
$nonbufResp->getBody()->write("<div>{$container->displayName}: {$message}</div>");
};

return $addToStreamingResponseBody;
}

private function finalizeStreamingResponse(Response $nonbufResp) : void {
$nonbufResp->getBody()->write($this->getStreamingResponseHtmlEnd());
}

private function getStreamingResponseHtmlEnd() : string {
return "\n </body>\n</html>";
}
Expand Down
4 changes: 2 additions & 2 deletions php/templates/containers.twig
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
{% elseif is_mastercontainer_update_available == true %}
<h2>Mastercontainer update</h2>
<p>⚠️ A mastercontainer update is available. Please click on the button below to update it. Afterwards, you will be able to proceed with the setup.</p>
<form method="POST" action="api/docker/watchtower" class="xhr">
<form method="POST" action="api/docker/watchtower" target="overlay-log">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Update mastercontainer" />
Expand Down Expand Up @@ -332,7 +332,7 @@
{% endif %}
{% if is_mastercontainer_update_available == true %}
<p>⚠️ A mastercontainer update is available. Please click on the button below to update it.</p>
<form method="POST" action="api/docker/watchtower" class="xhr">
<form method="POST" action="api/docker/watchtower" target="overlay-log">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Update mastercontainer" />
Expand Down