diff --git a/phpstan.neon b/phpstan.neon
index c02769b3..bc4ce357 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -5,6 +5,7 @@ parameters:
bootstrapFiles:
- ../../stubs/glpi_constants.php
- ../../vendor/autoload.php
+ - stubs/OptionalClass.php.stub
paths:
- src
- front
@@ -17,5 +18,6 @@ parameters:
- ../../src
stubFiles:
- ../../stubs/glpi_constants.php
+ - ./stubs/OptionalClass.php.stub
rules:
- GlpiProject\Tools\PHPStan\Rules\GlobalVarTypeRule
diff --git a/setup.php b/setup.php
index f2aedb35..5bccce42 100644
--- a/setup.php
+++ b/setup.php
@@ -33,6 +33,7 @@
use Config as GlpiConfig;
use CronTask as GlpiCronTask;
use Glpi\Plugin\Hooks;
+use GlpiPlugin\Carbon\CloudInventoryConnector;
use GlpiPlugin\Carbon\Config;
use GlpiPlugin\Carbon\CronTask;
use GlpiPlugin\Carbon\Dashboard\Grid;
@@ -115,6 +116,8 @@ function plugin_carbon_setupHooks()
LcaClientFactory::getSecuredConfigs()
);
+ $PLUGIN_HOOKS[Hooks::POST_INIT]['carbon'] = [CloudInventoryConnector::class, 'checkPluginAvailability'];
+
// add new cards to the dashboard
$PLUGIN_HOOKS[Hooks::DASHBOARD_CARDS]['carbon'] = [Grid::class, 'getDashboardCards'];
$PLUGIN_HOOKS[Hooks::DASHBOARD_TYPES]['carbon'] = [Widget::class, 'WidgetTypes'];
diff --git a/src/CloudInventoryConnector.php b/src/CloudInventoryConnector.php
new file mode 100644
index 00000000..491a8a73
--- /dev/null
+++ b/src/CloudInventoryConnector.php
@@ -0,0 +1,57 @@
+.
+ *
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Carbon;
+
+use Plugin;
+
+/**
+ * Establish the functional bridge between Carbon and the plugin CloudInventory
+ */
+class CloudInventoryConnector
+{
+ public static function checkPluginAvailability(): void
+ {
+ /** @var array $CFG_GLPI */
+ global $CFG_GLPI;
+
+ $CFG_GLPI['plugin:carbon']['use_cloudinventory'] = Plugin::isPluginActive('cloudinventory');
+ }
+
+ public function pluginAvailable(): bool
+ {
+ /** @var array $CFG_GLPI */
+ global $CFG_GLPI;
+
+ return $CFG_GLPI['plugin:carbon']['use_cloudinventory'] ?? false;
+ }
+}
diff --git a/src/ComputerType.php b/src/ComputerType.php
index c20955d7..ce4ede8f 100644
--- a/src/ComputerType.php
+++ b/src/ComputerType.php
@@ -50,6 +50,7 @@ class ComputerType extends AbstractChildDropdown
public const CATEGORY_LAPTOP = 3;
public const CATEGORY_TABLET = 4;
public const CATEGORY_SMARTPHONE = 5;
+ public const CATEGORY_CLOUD = 6;
public static function getCategories(): array
{
@@ -60,6 +61,7 @@ public static function getCategories(): array
self::CATEGORY_LAPTOP => __('Laptop', 'carbon'),
self::CATEGORY_TABLET => __('Tablet', 'carbon'),
self::CATEGORY_SMARTPHONE => __('Smartphone', 'carbon'),
+ self::CATEGORY_CLOUD => __('Cloud server', 'carbon'),
];
}
diff --git a/src/DataSource/Lca/Boaviztapi/Client.php b/src/DataSource/Lca/Boaviztapi/Client.php
index 5eeb0f12..9742a60a 100644
--- a/src/DataSource/Lca/Boaviztapi/Client.php
+++ b/src/DataSource/Lca/Boaviztapi/Client.php
@@ -44,6 +44,7 @@
use GlpiPlugin\Carbon\Zone;
use Override;
use RuntimeException;
+use Session;
class Client extends AbstractClient
{
@@ -257,6 +258,16 @@ public static function getZones()
public function parseResponse(array $response, string $scope): array
{
$impacts = [];
+ if (!isset($response['impacts'])) {
+ if (Session::getLoginUserID(true)) {
+ $message = __('An error occured while processing the response from Boaviztapi', 'carbon');
+ $message .= '
' . ($response['detail'] ?? 'unknown error');
+ Session::addMessageAfterRedirect($message, true, ERROR);
+ }
+ trigger_error('Error parsing the response ' . var_export($response, true), E_USER_WARNING);
+ return $impacts;
+ }
+
$types = Type::getImpactTypes();
foreach ($response['impacts'] as $type => $impact) {
if (!in_array($type, $types)) {
diff --git a/src/Impact/Embodied/Boavizta/Computer.php b/src/Impact/Embodied/Boavizta/Computer.php
index 9d16f684..dfe70c16 100644
--- a/src/Impact/Embodied/Boavizta/Computer.php
+++ b/src/Impact/Embodied/Boavizta/Computer.php
@@ -35,9 +35,17 @@
use CommonDBTM;
use Computer as GlpiComputer;
+use ComputerModel as GlpiComputerModel;
use ComputerType as GlpiComputerType;
+use GlpiPlugin\Carbon\CloudInventoryConnector;
use GlpiPlugin\Carbon\ComputerType;
use GlpiPlugin\Carbon\DataSource\Lca\Boaviztapi\ComputerModelizationAdapterTrait;
+use GlpiPlugin\Cloudinventory\Amazon;
+use GlpiPlugin\Cloudinventory\Azure;
+use GlpiPlugin\Cloudinventory\CloudInstance;
+use GlpiPlugin\Cloudinventory\Google;
+use GlpiPlugin\Cloudinventory\Ovh;
+use GlpiPlugin\Cloudinventory\Scaleway;
use Override;
class Computer extends AbstractAsset
@@ -48,6 +56,12 @@ class Computer extends AbstractAsset
protected string $endpoint = 'server';
+ /**
+ * If the plugin CloudInventory is available, this is an oblect from that
+ * plugin representing the cloud related data of the computer
+ */
+ protected ?CloudInstance $cloud_instance = null;
+
#[Override]
protected function doEvaluation(): ?array
{
@@ -56,26 +70,89 @@ protected function doEvaluation(): ?array
$this->endpoint = $this->getEndpoint($type);
$this->endpoint .= '?' . $this->getCriteriasQueryString();
+ $response = null;
+
// Ask for embodied impact only
$handle_hardware = in_array($type, [
ComputerType::CATEGORY_SERVER,
ComputerType::CATEGORY_DESKTOP,
ComputerType::CATEGORY_UNDEFINED,
]);
+ if ($handle_hardware) {
+ $response = $this->getHarwareBasedEvaluation();
+ }
+
+ if ($type === ComputerType::CATEGORY_CLOUD) {
+ $response = $this->getCloudBasedEvaluation();
+ }
+ if ($response === null) {
+ return null;
+ }
+
+ $impacts = $this->client->parseResponse($response, 'embedded');
+ return $impacts;
+ }
+
+ private function getHarwareBasedEvaluation(): ?array
+ {
$configuration = $this->analyzeHardware();
- if ($handle_hardware && count($configuration) === 0) {
+ if (count($configuration) === 0) {
return null;
}
+
+ // Ask for embodied impact only
$description = [
'configuration' => $configuration,
'usage' => [
'avg_power' => 0,
],
];
- $response = $this->query($description);
- $impacts = $this->client->parseResponse($response, 'embedded');
+ return $this->query($description);
+ }
- return $impacts;
+ private function getCloudBasedEvaluation(): ?array
+ {
+ // Ask for embodied impact only
+ $description = [
+ 'usage' => [
+ 'avg_power' => 0,
+ ],
+ ];
+
+ // Find provider
+ switch ($this->cloud_instance->fields['itemtype']) {
+ case Amazon::class:
+ $description['provider'] = 'aws';
+ break;
+ case Azure::class:
+ $description['provider'] = 'azure';
+ break;
+ case Google::class:
+ $description['provider'] = 'gcp';
+ break;
+ case Ovh::class:
+ $description['provider'] = 'ovhcloud';
+ break;
+ case Scaleway::class:
+ $description['provider'] = 'scaleway';
+ break;
+ }
+
+ $glpi_computer_model = GlpiComputerModel::getById($this->cloud_instance->fields['computermodels_id']);
+
+ // Find model
+ $model = $glpi_computer_model ? $glpi_computer_model->fields['name'] : '';
+ if ($model !== '') {
+ $description['instance_type'] = $model;
+ } else {
+ $configuration = $this->analyzeHardware();
+ if (count($configuration) === 0) {
+ // No model nor hardware configuration
+ return null;
+ }
+ $description['configuration'] = $configuration;
+ }
+ return $this->query($description);
}
/**
@@ -85,6 +162,21 @@ protected function doEvaluation(): ?array
*/
protected function getType(CommonDBTM $item): int
{
+ /** @var array $CFG_GLPI */
+ global $CFG_GLPI;
+
+ $cloudInventory_connector = new CloudInventoryConnector();
+ if ($cloudInventory_connector->pluginAvailable()) {
+ $cloud_instance = new CloudInstance();
+ $cloud_instance->getFromDBByCrit([
+ 'computers_id' => $item->getID(),
+ ]);
+ if (!$cloud_instance->isNewItem()) {
+ $this->cloud_instance = $cloud_instance;
+ return ComputerType::CATEGORY_CLOUD;
+ }
+ }
+
$computer_table = GlpiComputer::getTable();
$computer_type_table = ComputerType::getTable();
$glpi_computer_type_table = GlpiComputerType::getTable();
@@ -129,6 +221,8 @@ protected function getEndpoint(int $type)
return 'terminal/tablet';
case ComputerType::CATEGORY_SMARTPHONE:
return 'terminal/smartphone';
+ case ComputerType::CATEGORY_CLOUD:
+ return 'cloud/instance';
}
// ComputerType::CATEGORY_UNDEFINED
diff --git a/stubs/OptionalClass.php.stub b/stubs/OptionalClass.php.stub
new file mode 100644
index 00000000..6a363cf0
--- /dev/null
+++ b/stubs/OptionalClass.php.stub
@@ -0,0 +1,25 @@
+ */
+ public $fields = [];
+
+ /**
+ * @param array $criteria
+ * @return bool
+ *
+ * @phpstan-impure
+ */
+ public function getFromDBByCrit(array $criteria): bool {}
+
+ public function isNewItem(): bool {}
+}
+
+class Amazon {}
+class Azure {}
+class Google {}
+class Ovh {}
+class Scaleway {}
diff --git a/tests/src/CommonTestCase.php b/tests/src/CommonTestCase.php
index 35abfb7a..97d2e182 100644
--- a/tests/src/CommonTestCase.php
+++ b/tests/src/CommonTestCase.php
@@ -64,7 +64,7 @@ class CommonTestCase extends TestCase
/** @var int $debugMode save state of GLPI debug mode */
private $debugMode = null;
- protected $str = null;
+ protected ?string $str = null;
protected function disableDebug()
{
@@ -115,7 +115,7 @@ protected function setupGLPIFramework(): void
return;
}
- protected function login($name, $password, $noauto = false)
+ protected function login(string $name, string $password, $noauto = false)
{
Session::start();
$auth = new Auth();
@@ -539,7 +539,7 @@ protected function isolateInEntity(): int
*
* @return mixed
*/
- protected function callPrivateMethod($instance, string $methodName, ...$args)
+ protected function callPrivateMethod($instance, string $methodName, mixed ...$args)
{
$method = new ReflectionMethod($instance, $methodName);
if (version_compare(PHP_VERSION, '8.1.0') < 0) {
diff --git a/tests/units/DataSource/CarbonIntensity/ElectricityMaps/ConfigTest.php b/tests/units/DataSource/CarbonIntensity/ElectricityMaps/ConfigTest.php
index da22ef07..034a2347 100644
--- a/tests/units/DataSource/CarbonIntensity/ElectricityMaps/ConfigTest.php
+++ b/tests/units/DataSource/CarbonIntensity/ElectricityMaps/ConfigTest.php
@@ -99,10 +99,6 @@ public function testConfigUpdate(array $input, array $expected)
/** @var array $CFG_GLPI */
global $CFG_GLPI;
- $CFG_GLPI['plugi:carbon']['lca_datasources'] = [
- Client::class,
- ];
-
$instance = new Config();
$result = $instance->configUpdate($input);
$this->assertEquals($expected, $result);
diff --git a/tests/units/DataSource/Lca/Boaviztapi/ConfigTest.php b/tests/units/DataSource/Lca/Boaviztapi/ConfigTest.php
index 7f5249e1..ef3a40b7 100644
--- a/tests/units/DataSource/Lca/Boaviztapi/ConfigTest.php
+++ b/tests/units/DataSource/Lca/Boaviztapi/ConfigTest.php
@@ -124,10 +124,6 @@ public function testConfigUpdate(array $input, array $expected)
/** @var array $CFG_GLPI */
global $CFG_GLPI;
- $CFG_GLPI['plugi:carbon']['lca_datasources'] = [
- Client::class,
- ];
-
$result = (new Config())->configUpdate($input);
$this->assertEquals($expected, $result);
}