Skip to content

Commit

Permalink
Add donut graphs to deployments, replica sets, daemon sets and stateful
Browse files Browse the repository at this point in the history
sets
  • Loading branch information
jhoxhaa committed Aug 8, 2023
1 parent a35e0d0 commit 2fbc0ff
Show file tree
Hide file tree
Showing 6 changed files with 319 additions and 79 deletions.
94 changes: 94 additions & 0 deletions library/Kubernetes/Donut.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

/* Icinga Kubernetes Web | (c) 2023 Icinga GmbH | GPLv2 */

namespace Icinga\Module\Kubernetes;

use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\Html;
use ipl\Html\HtmlElement;
use ipl\Html\HtmlString;
use ipl\Html\Table;
use ipl\Html\Text;

class Donut extends BaseHtmlElement
{
protected $tag = 'section';

protected $defaultAttributes = ['class' => 'donut'];

/**
* The donut data
*
* @var iterable
*/
protected $data = [];

/**
* @var string
*/
protected $heading;

/**
* @var int
*/
protected $headingLevel = 2;

/**
* @var callable
*/
protected $labelCallback;

/**
* Set the data to display
*
* @param iterable $data
*
* @return $this
*/
public function setData(iterable $data): self
{
$this->data = $data;

return $this;
}

public function setHeading(string $heading, int $level): self
{
$this->heading = $heading;
$this->headingLevel = $level;

return $this;
}

public function setLabelCallback(callable $callback): self
{
$this->labelCallback = $callback;

return $this;
}

public function assemble()
{
$donut = new \Icinga\Chart\Donut();
$legend = new Table();

foreach ($this->data as $index => $value) {
$donut->addSlice((int) $value, ['class' => 'segment-' . $index]);
$legend->add(
[
New HtmlElement('span', new Attributes(['class' => 'badge badge-' . $index])),
call_user_func($this->labelCallback, $index),
$value
]
);
}

if ($this->heading !== null) {
$this->addHtml(new HtmlElement("h{$this->headingLevel}", null, new Text($this->heading)));
}

$this->addHtml(new HtmlString($donut->render()), $legend);
}
}
26 changes: 21 additions & 5 deletions library/Kubernetes/Web/DaemonSetDetail.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,15 @@

namespace Icinga\Module\Kubernetes\Web;

use Icinga\Module\Kubernetes\Common\Database;
use Icinga\Module\Kubernetes\Donut;
use Icinga\Module\Kubernetes\Model\DaemonSet;
use Icinga\Module\Kubernetes\Model\Event;
use Icinga\Module\Kubernetes\Model\Label;
use Icinga\Module\Kubernetes\Model\ReplicaSet;
use Icinga\Module\Kubernetes\Model\ReplicaSetCondition;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\HtmlElement;
use ipl\Html\Text;
use ipl\Stdlib\Filter;
use ipl\Stdlib\Str;
use ipl\Web\Widget\HorizontalKeyValue;
use ipl\Web\Widget\TimeAgo;

class DaemonSetDetail extends BaseHtmlElement
Expand Down Expand Up @@ -55,6 +51,26 @@ protected function assemble()
new Labels($this->daemonSet->label),
new ConditionTable($this->daemonSet, (new ReplicaSetCondition())->getColumnDefinitions())
);
$data = [
$this->daemonSet->number_available,
$this->daemonSet->number_ready - $this->daemonSet->number_available,
$this->daemonSet->desired_number_scheduled - $this->daemonSet->number_ready,
$this->daemonSet->number_unavailable
];
$labels = [
t('Available'),
t('Ready but not yet available'),
t('Not yet ready'),
t('Not yet scheduled or failing')
];
$donut = (new Donut())
->setData($data)
->setLabelCallback(function ($index) use ($labels) {
return new HtmlElement('span', null, new Text($labels[$index]));
});
$this->addHtml($donut);

$this->addHtml(new ConditionTable($this->daemonSet, (new ReplicaSetCondition())->getColumnDefinitions()));

$this->addHtml(new HtmlElement(
'section',
Expand Down
66 changes: 46 additions & 20 deletions library/Kubernetes/Web/DeploymentDetail.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Icinga\Module\Kubernetes\Web;

use Icinga\Module\Kubernetes\Donut;
use Icinga\Module\Kubernetes\Model\Deployment;
use Icinga\Module\Kubernetes\Model\DeploymentCondition;
use Icinga\Module\Kubernetes\Model\Label;
Expand Down Expand Up @@ -33,31 +34,56 @@ public function __construct(Deployment $deployment)

protected function assemble()
{
$this->addHtml(new Details([
t('Name') => $this->deployment->name,
t('Namespace') => $this->deployment->namespace,
t('UID') => $this->deployment->uid,
t('Strategy') => ucfirst(Str::camel($this->deployment->strategy)),
t('Min Ready Seconds') => $this->deployment->min_ready_seconds,
t('Desired Replicas') => $this->deployment->desired_replicas,
t('Actual Replicas') => $this->deployment->actual_replicas,
t('Updated Replicas') => $this->deployment->updated_replicas,
t('Ready Replicas') => $this->deployment->ready_replicas,
t('Available Replicas') => $this->deployment->available_replicas,
t('Unavailable Replicas') => $this->deployment->unavailable_replicas,
t('Created') => new TimeAgo($this->deployment->created->getTimestamp())
]));
$this->addHtml(
new Details([
t('Name') => $this->deployment->name,
t('Namespace') => $this->deployment->namespace,
t('UID') => $this->deployment->uid,
t('Strategy') => ucfirst(Str::camel($this->deployment->strategy)),
t('Min Ready Seconds') => $this->deployment->min_ready_seconds,
t('Desired Replicas') => $this->deployment->desired_replicas,
t('Actual Replicas') => $this->deployment->actual_replicas,
t('Updated Replicas') => $this->deployment->updated_replicas,
t('Ready Replicas') => $this->deployment->ready_replicas,
t('Available Replicas') => $this->deployment->available_replicas,
t('Unavailable Replicas') => $this->deployment->unavailable_replicas,
t('Created') => new TimeAgo($this->deployment->created->getTimestamp())
])
);

$this->addHtml(
new Labels($this->deployment->label),
new ConditionTable($this->deployment, (new DeploymentCondition())->getColumnDefinitions())
);
$data = [
$this->deployment->available_replicas,
$this->deployment->desired_replicas - $this->deployment->actual_replicas,
$this->deployment->actual_replicas - $this->deployment->ready_replicas,
$this->deployment->unavailable_replicas,
];

$donut = (new Donut())
->setData($data)
->setLabelCallback(function ($index) {
$labels = [
t('Available'),
t('Ready but not yet available'),
t('Not yet ready'),
t('Not yet scheduled or failing')
];
return new HtmlElement('span', null, new Text($labels[$index]));
});
$this->addHtml($donut);

$this->addHtml(new HtmlElement(
'section',
new Attributes(['class' => 'resource-replica-sets']),
new HtmlElement('h2', null, new Text(t('Replica Sets'))),
new ReplicaSetList($this->deployment->replica_sets)
));
$this->addHtml(new ConditionTable($this->deployment, (new DeploymentCondition())->getColumnDefinitions()));

$this->addHtml(
new HtmlElement(
'section',
new Attributes(['class' => 'resource-replica-sets']),
new HtmlElement('h2', null, new Text(t('Replica Sets'))),
new ReplicaSetList($this->deployment->replica_sets)
)
);
}
}
91 changes: 61 additions & 30 deletions library/Kubernetes/Web/ReplicaSetDetail.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Icinga\Module\Kubernetes\Model\Label;
use Icinga\Module\Kubernetes\Model\ReplicaSet;
use Icinga\Module\Kubernetes\Model\replicaSetCondition;
use Icinga\Module\Kubernetes\Donut;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\HtmlElement;
Expand All @@ -35,42 +36,72 @@ public function __construct($replicaSet)

protected function assemble()
{
$this->addHtml(new Details([
t('Name') => $this->replicaSet->name,
t('Namespace') => $this->replicaSet->namespace,
t('UID') => $this->replicaSet->uid,
t('Min Ready Seconds') => $this->replicaSet->min_ready_seconds,
t('Desired Replicas') => $this->replicaSet->desired_replicas,
t('Actual Replicas') => $this->replicaSet->actual_replicas,
t('Fully Labeled Replicas') => $this->replicaSet->fully_labeled_replicas,
t('Ready Replicas') => $this->replicaSet->ready_replicas,
t('Available Replicas') => $this->replicaSet->available_replicas,
t('Created') => new TimeAgo($this->replicaSet->created->getTimestamp())
]));
$this->addHtml(
new Details([
t('Name') => $this->replicaSet->name,
t('Namespace') => $this->replicaSet->namespace,
t('UID') => $this->replicaSet->uid,
t('Min Ready Seconds') => $this->replicaSet->min_ready_seconds,
t('Desired Replicas') => $this->replicaSet->desired_replicas,
t('Actual Replicas') => $this->replicaSet->actual_replicas,
t('Fully Labeled Replicas') => $this->replicaSet->fully_labeled_replicas,
t('Ready Replicas') => $this->replicaSet->ready_replicas,
t('Available Replicas') => $this->replicaSet->available_replicas,
t('Created') => new TimeAgo($this->replicaSet->created->getTimestamp())
])
);

$this->addHtml(
new Labels($this->replicaSet->label),
new ConditionTable($this->replicaSet, (new ReplicaSetCondition())->getColumnDefinitions())
);
$data = [
$this->replicaSet->available_replicas,
$this->replicaSet->ready_replicas - $this->replicaSet->available_replicas,
$this->replicaSet->actual_replicas - $this->replicaSet->ready_replicas,
$this->replicaSet->desired_replicas - $this->replicaSet->actual_replicas,
];

$this->addHtml(new HtmlElement(
'section',
new Attributes(['class' => 'resource-pods']),
new HtmlElement('h2', null, new Text(t('Pods'))),
new PodList($this->replicaSet->pods->with(['node']))
));
$labels = [
t('Available'),
t('Ready but not yet available'),
t('Not yet ready'),
t('Not yet scheduled or failing')
];
$donut = (new Donut())
->setData($data)
->setLabelCallback(function ($index) use ($labels) {
return new HtmlElement('span', null, new Text($labels[$index]));
});
$this->addHtml($donut);

$this->addHtml(new HtmlElement(
'section',
new Attributes(['class' => 'resource-events']),
new HtmlElement('h2', null, new Text(t('Events'))),
new EventList(Event::on(Database::connection())
->filter(Filter::all(
Filter::equal('reference_kind', 'ReplicaSet'),
Filter::equal('reference_namespace', $this->replicaSet->namespace),
Filter::equal('reference_name', $this->replicaSet->name)
)))
));
}
$this->addHtml(new ConditionTable($this->replicaSet, (new ReplicaSetCondition())->getColumnDefinitions()));

$this->addHtml(
new HtmlElement(
'section',
new Attributes(['class' => 'resource-pods']),
new HtmlElement('h2', null, new Text(t('Pods'))),
new PodList($this->replicaSet->pods->with(['node']))
)
);

$this->addHtml(
new HtmlElement(
'section',
new Attributes(['class' => 'resource-events']),
new HtmlElement('h2', null, new Text(t('Events'))),
new EventList(
Event::on(Database::connection())
->filter(
Filter::all(
Filter::equal('reference_kind', 'ReplicaSet'),
Filter::equal('reference_namespace', $this->replicaSet->namespace),
Filter::equal('reference_name', $this->replicaSet->name)
)
)
)
)
);
}
}
Loading

0 comments on commit 2fbc0ff

Please sign in to comment.