Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dashboard #104

Merged
merged 25 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c79647c
configuration.php: Add dashboard url to menu section
jhoxhaa Dec 11, 2024
3213034
module.less: Add `kubernetes-dashboard` styling
jhoxhaa Dec 11, 2024
92b9934
icons.less: Add event icon style
jhoxhaa Dec 11, 2024
7b7b50e
Add event icon font
jhoxhaa Dec 11, 2024
7e74ff8
common.less: Remove box-shadow style
jhoxhaa Dec 11, 2024
b1eb53d
Resize SVG icon to smaller dimensions
jhoxhaa Dec 12, 2024
ad72ea0
Introduce new class `DashboardController`
jhoxhaa Dec 12, 2024
4fad4d2
Introduce new `Dashboard` and `Dashlet` classes
jhoxhaa Dec 12, 2024
216414b
Introduce new trait `BeforeAssemble.php`
jhoxhaa Dec 16, 2024
05863e6
Introduce new class `FormatString.php`
jhoxhaa Dec 16, 2024
1da4259
Rename function from `createUrl` to `createDetailUrl`
jhoxhaa Dec 16, 2024
325d634
Factory.php: Add new `createListUrl` function
jhoxhaa Dec 16, 2024
37317fb
Factory.php: Add new `createModel` function
jhoxhaa Dec 16, 2024
745611a
Introduce new class `IcingaStateDashlet`
jhoxhaa Dec 16, 2024
3f2628f
Introduce new class `KubernetesPhaseDashlet`
jhoxhaa Dec 16, 2024
2ff420a
Refactor `DashboardController.php`
jhoxhaa Dec 16, 2024
2ee30b2
Refactor `Dashboard.php`
jhoxhaa Dec 16, 2024
f0590c0
Refactor `Dashlet.php`
jhoxhaa Dec 16, 2024
8997968
Refactor `*.Dashboard` classes
jhoxhaa Dec 16, 2024
13cdd68
Delete unnecessary classes
jhoxhaa Dec 16, 2024
83f966f
Introduce new Form `ClusterForm.php`
jhoxhaa Dec 16, 2024
8e08edc
Add multi-cluster support
jhoxhaa Dec 16, 2024
4471bc7
module.less: Enhance layout and style for form controls
jhoxhaa Dec 16, 2024
24dbb50
Auth.php: Update Kubernetes resources to lowercase in permissions array
jhoxhaa Dec 16, 2024
2d28cc0
Apply restrictions to model queries
jhoxhaa Dec 16, 2024
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
64 changes: 64 additions & 0 deletions application/controllers/DashboardController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

/* Icinga for Kubernetes Web | (c) 2024 Icinga GmbH | AGPLv3 */

namespace Icinga\Module\Kubernetes\Controllers;

use GuzzleHttp\Psr7\ServerRequest;
use Icinga\Module\Kubernetes\Common\Database;
use Icinga\Module\Kubernetes\Dashboard\ClusterManagementDashboard;
use Icinga\Module\Kubernetes\Dashboard\ConfigurationDashboard;
use Icinga\Module\Kubernetes\Dashboard\NetworkingDashboard;
use Icinga\Module\Kubernetes\Dashboard\ObservabilityDashboard;
use Icinga\Module\Kubernetes\Dashboard\StorageDashboard;
use Icinga\Module\Kubernetes\Dashboard\WorkloadsDashboard;
use Icinga\Module\Kubernetes\Model\Cluster;
use Icinga\Module\Kubernetes\Web\ClusterForm;
use Icinga\Module\Kubernetes\Web\Controller;
use Icinga\Web\Session;

class DashboardController extends Controller
{
public function indexAction(): void
{
$this->addTitleTab($this->translate('Kubernetes'));

$cluster = (new ClusterForm())
->populate(
[
'cluster_uuid' => Session::getSession()
->getNamespace('kubernetes')
->get('cluster_uuid', ClusterForm::ALL_CLUSTERS)
]
)
->on(ClusterForm::ON_SUCCESS, function (ClusterForm $form) {
$session = Session::getSession()
->getNamespace('kubernetes');
$clusterUuid = $form->getElement('cluster_uuid')->getValue();
if ($clusterUuid === ClusterForm::ALL_CLUSTERS) {
$session->set('cluster_uuid', null);
} else {
$session->set('cluster_uuid', $clusterUuid);
}
})
->handleRequest(ServerRequest::fromGlobals());

if ($this->isMultiCluster()) {
$this->addContent($cluster);
}

$this->content->addHtml(
new ClusterManagementDashboard(),
new WorkloadsDashboard(),
new StorageDashboard(),
new NetworkingDashboard(),
new ConfigurationDashboard(),
new ObservabilityDashboard(),
);
}

protected function isMultiCluster(): bool
{
return Cluster::on(Database::connection())->count() > 1;
}
}
7 changes: 4 additions & 3 deletions assets/Icinga-Kubernetes.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/Icinga-Kubernetes.ttf
Binary file not shown.
Binary file modified assets/Icinga-Kubernetes.woff
Binary file not shown.
3 changes: 2 additions & 1 deletion configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
$section = $this->menuSection(
'Kubernetes',
[
'icon' => 'globe'
'icon' => 'globe',
'url' => 'kubernetes/dashboard',
]
);

Expand Down
32 changes: 16 additions & 16 deletions library/Kubernetes/Common/Auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,22 @@ class Auth
public const SHOW_STATEFUL_SETS = 'kubernetes/stateful-sets/show';

public const PERMISSIONS = [
'ConfigMap' => self::SHOW_CONFIG_MAPS,
'CronJob' => self::SHOW_CRON_JOBS,
'DaemonSet' => self::SHOW_DAEMON_SETS,
'Deployment' => self::SHOW_DEPLOYMENTS,
'Event' => self::SHOW_EVENTS,
'Ingress' => self::SHOW_INGRESSES,
'Job' => self::SHOW_JOBS,
'Namespace' => self::SHOW_NAMESPACES,
'Node' => self::SHOW_NODES,
'PersistentVolume' => self::SHOW_PERSISTENT_VOLUMES,
'PersistentVolumeClaim' => self::SHOW_PERSISTENT_VOLUME_CLAIMS,
'Pod' => self::SHOW_PODS,
'ReplicaSet' => self::SHOW_REPLICA_SETS,
'Secret' => self::SHOW_SECRETS,
'Service' => self::SHOW_SERVICES,
'StatefulSet' => self::SHOW_STATEFUL_SETS,
'configmap' => self::SHOW_CONFIG_MAPS,
'cronjob' => self::SHOW_CRON_JOBS,
'daemonset' => self::SHOW_DAEMON_SETS,
'deployment' => self::SHOW_DEPLOYMENTS,
'event' => self::SHOW_EVENTS,
'ingress' => self::SHOW_INGRESSES,
'job' => self::SHOW_JOBS,
'namespace' => self::SHOW_NAMESPACES,
'node' => self::SHOW_NODES,
'persistentvolume' => self::SHOW_PERSISTENT_VOLUMES,
'persistentvolumeclaim' => self::SHOW_PERSISTENT_VOLUME_CLAIMS,
'pod' => self::SHOW_PODS,
'replicaset' => self::SHOW_REPLICA_SETS,
'secret' => self::SHOW_SECRETS,
'service' => self::SHOW_SERVICES,
'statefulset' => self::SHOW_STATEFUL_SETS,
];

protected IcingaAuth $auth;
Expand Down
30 changes: 30 additions & 0 deletions library/Kubernetes/Common/BeforeAssemble.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/* Icinga for Kubernetes Web | (c) 2024 Icinga GmbH | AGPLv3 */

namespace Icinga\Module\Kubernetes\Common;

/**
* Trait to perform actions before assembling {@see HtmlDocument}s.
*/
trait BeforeAssemble
{
private bool $beforeAssemble = false;

public function ensureAssembled(): static
{
if ($this->hasBeenAssembled === false && ! $this->beforeAssemble) {
$this->beforeAssemble = true;
$this->beforeAssemble();
}

return parent::ensureAssembled();
}

/**
* Hook method to perform actions before assembling the object.
*/
protected function beforeAssemble(): void
{
}
}
48 changes: 48 additions & 0 deletions library/Kubernetes/Common/FormatString.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

/* Icinga for Kubernetes Web | (c) 2024 Icinga GmbH | AGPLv3 */

namespace Icinga\Module\Kubernetes\Common;

use Stringable;

/**
* Format strings with support for both named placeholders and sprintf-style arguments.
*/
class FormatString implements Stringable
{
protected array $args = [];

/**
* Constructor for the FormatString class.
*
* @param string $format The format string containing named placeholders and/or sprintf-style arguments.
*/
public function __construct(protected string $format)
{
}

/**
* Add arguments for formatting the string.
*
* @param array $args An associative array for named placeholders and/or an indexed array for sprintf arguments.
*
* @return static Returns the instance of the FormatString for method chaining.
*/
public function addArgs(array $args): static
{
$this->args = array_merge($this->args, $args);

return $this;
}

/**
* Convert the format string to a formatted string using the provided arguments.
*
* @return string The formatted string.
*/
public function __toString(): string
{
return ! empty($this->args) ? vsprintf(strtr($this->format, $this->args), $this->args) : $this->format;
}
}
34 changes: 34 additions & 0 deletions library/Kubernetes/Dashboard/ClusterManagementDashboard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

/* Icinga for Kubernetes Web | (c) 2024 Icinga GmbH | AGPLv3 */

namespace Icinga\Module\Kubernetes\Dashboard;

class ClusterManagementDashboard extends Dashboard
{
public function getTitle(): string
{
return $this->translate('Cluster management');
}

protected function assemble(): void
{
$this->addHtml(
new KubernetesPhaseDashlet(
'namespace',
$this->translate('Namespaces'),
$this->translate(
'Out of {total} total Namespaces, {Active} are Active, {Terminating} are Terminating.'
)
),
new IcingaStateDashlet(
'node',
$this->translate('Nodes'),
$this->translate(
'Out of {total} total Nodes, {ok} are in OK state, {critical} are Critical, {warning} are
in Warning state, and {unknown} are Unknown.'
)
)
);
}
}
29 changes: 29 additions & 0 deletions library/Kubernetes/Dashboard/ConfigurationDashboard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/* Icinga for Kubernetes Web | (c) 2024 Icinga GmbH | AGPLv3 */

namespace Icinga\Module\Kubernetes\Dashboard;

class ConfigurationDashboard extends Dashboard
{
public function getTitle(): string
{
return $this->translate('Configuration');
}

protected function assemble(): void
{
$this->addHtml(
new Dashlet(
'configmap',
$this->translate('Config Maps'),
$this->translate('Store configuration data as key-value pairs.')
),
new Dashlet(
'secret',
$this->translate('Secrets'),
$this->translate('Store sensitive data (e.g., passwords, tokens) in an encrypted format.')
)
);
}
}
31 changes: 31 additions & 0 deletions library/Kubernetes/Dashboard/Dashboard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/* Icinga for Kubernetes Web | (c) 2024 Icinga GmbH | AGPLv3 */

namespace Icinga\Module\Kubernetes\Dashboard;

use Icinga\Module\Kubernetes\Common\BeforeAssemble;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\HtmlElement;
use ipl\Html\Text;
use ipl\I18n\Translation;

abstract class Dashboard extends BaseHtmlElement
{
use BeforeAssemble;
use Translation;

protected $tag = 'ul';

abstract protected function getTitle(): string;

protected function beforeAssemble(): void
{
$this->setWrapper(new HtmlElement(
'section',
new Attributes(['class' => 'kubernetes-dashboard']),
new HtmlElement('h2', null, new Text($this->getTitle()))
));
}
}
50 changes: 50 additions & 0 deletions library/Kubernetes/Dashboard/Dashlet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

/* Icinga for Kubernetes Web | (c) 2024 Icinga GmbH | AGPLv3 */

namespace Icinga\Module\Kubernetes\Dashboard;

use Icinga\Module\Kubernetes\Common\BeforeAssemble;
use Icinga\Module\Kubernetes\Common\FormatString;
use Icinga\Module\Kubernetes\Web\Factory;
use ipl\Html\BaseHtmlElement;
use ipl\Html\HtmlElement;
use ipl\Html\Text;
use ipl\I18n\Translation;
use ipl\Web\Widget\Link;

class Dashlet extends BaseHtmlElement
{
use BeforeAssemble;
use Translation;

protected $tag = 'li';

protected FormatString $summary;

public function __construct(
protected string $kind,
protected string $title,
string $summary,
protected ?string $url = null
) {
$this->url = $url !== null ? $url : Factory::createListUrl($kind);
$this->summary = new FormatString($summary);
}

protected function assemble(): void
{
$this->addHtml(new Link(
[
$this->title,
Factory::createIcon($this->kind),
new HtmlElement(
'p',
null,
new Text($this->summary)
)
],
$this->url
));
}
}
Loading
Loading