cloud_scanner_cli/
impact_provider.rs

1//! A module to abstract the service used to retrieve impacts of cloud resources.
2use crate::model::{CloudResource, EstimatedInventory, Inventory};
3use anyhow::Result;
4use async_trait::async_trait;
5use rocket_okapi::okapi::schemars;
6use rocket_okapi::okapi::schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8
9/// A ImpactProvider trait to implement for a specific impact API/Referential.
10#[async_trait]
11pub trait ImpactProvider {
12    /// Returns a list of CloudImpacts.
13    /// usage_duration_hours allow to retrieve the impacts for a given duration (i.e. project impacts for a specific duration).
14    async fn get_impacts(
15        &self,
16        inventory: Inventory,
17        usage_duration_hours: &f32,
18        verbose: bool,
19    ) -> Result<EstimatedInventory>;
20}
21
22#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
23pub struct CloudResourceWithImpacts {
24    pub cloud_resource: CloudResource,
25    /// The impacts
26    pub impacts_values: Option<ImpactsValues>,
27    /// The duration for which impacts are calculated
28    pub impacts_duration_hours: f32,
29}
30
31// TODO: shouldn't theses fields be optional ?
32/// Impacts of an individual resource
33#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
34pub struct ImpactsValues {
35    pub adp_manufacture_kgsbeq: f64,
36    pub adp_use_kgsbeq: f64,
37    pub pe_manufacture_megajoules: f64,
38    pub pe_use_megajoules: f64,
39    pub gwp_manufacture_kgco2eq: f64,
40    pub gwp_use_kgco2eq: f64,
41    pub raw_data: Option<serde_json::Value>,
42}
43
44/// The aggregated impacts and metadata about the scan results
45#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
46pub struct ImpactsSummary {
47    pub number_of_resources_total: usize,
48    pub number_of_resources_assessed: usize,
49    pub number_of_resources_not_assessed: usize,
50    pub duration_of_use_hours: f64,
51    pub adp_manufacture_kgsbeq: f64,
52    pub adp_use_kgsbeq: f64,
53    pub pe_manufacture_megajoules: f64,
54    pub pe_use_megajoules: f64,
55    pub gwp_manufacture_kgco2eq: f64,
56    pub gwp_use_kgco2eq: f64,
57    pub aws_region: String,
58    pub country: String,
59}
60
61impl ImpactsSummary {
62    /// Returns a Summary of impacts for a list of Cloud Resources
63    pub fn new(
64        aws_region: String,
65        country: String,
66        resources_with_impacts: &EstimatedInventory,
67        duration_of_use_hours: f64,
68    ) -> Self {
69        let resources = resources_with_impacts.impacting_resources.clone();
70
71        let mut summary = ImpactsSummary {
72            number_of_resources_total: resources.len(),
73            number_of_resources_assessed: 0,
74            number_of_resources_not_assessed: 0,
75            aws_region,
76            country,
77            duration_of_use_hours,
78            adp_manufacture_kgsbeq: 0.0,
79            adp_use_kgsbeq: 0.0,
80            pe_manufacture_megajoules: 0.0,
81            pe_use_megajoules: 0.0,
82            gwp_manufacture_kgco2eq: 0.0,
83            gwp_use_kgco2eq: 0.0,
84        };
85
86        for resource in resources {
87            // Only consider the instances for which we have impact data
88            if let Some(impacts) = resource.impacts_values {
89                summary.number_of_resources_assessed += 1;
90                summary.adp_manufacture_kgsbeq += impacts.adp_manufacture_kgsbeq;
91                summary.adp_use_kgsbeq += impacts.adp_use_kgsbeq;
92                summary.pe_manufacture_megajoules += impacts.pe_manufacture_megajoules;
93                summary.pe_use_megajoules += impacts.pe_use_megajoules;
94                summary.gwp_manufacture_kgco2eq += impacts.gwp_manufacture_kgco2eq;
95                summary.gwp_use_kgco2eq += impacts.gwp_use_kgco2eq;
96            } else {
97                // Resource was not counted due to no impact
98                debug!("Skipped counting resource: {:#?} while building summary because it has no impact data", resource);
99                summary.number_of_resources_not_assessed += 1;
100            }
101        }
102        summary
103    }
104}